|
|
|
@ -21,7 +21,7 @@
|
|
|
|
|
var simInfo = { |
|
|
|
|
maxSteps: 50000, // maximal number of simulation steps to run
|
|
|
|
|
airDrag: 0.1, // "air" friction of enviroment; 0 is vacuum, 0.9 is molasses
|
|
|
|
|
boxFric: 0.005, // friction between boxes during collisions
|
|
|
|
|
boxFric: 0.001, // friction between boxes during collisions
|
|
|
|
|
boxMass: 0.01, // mass of boxes
|
|
|
|
|
boxSize: 10, // size of the boxes, in pixels
|
|
|
|
|
robotSize: 13, // approximate robot radius, in pixels (note the SVG gets scaled down)
|
|
|
|
@ -30,25 +30,20 @@ var simInfo = {
|
|
|
|
|
bayScale: 2, // scale within 2nd, inset canvas showing robot in it's "bay"
|
|
|
|
|
debugSensors: true, // plot sensor rays and mark detected objects
|
|
|
|
|
debugMouse: true, // allow dragging any object with the mouse
|
|
|
|
|
wanderRate: 0.0002, |
|
|
|
|
}; |
|
|
|
|
class Lemming extends Robot { |
|
|
|
|
constructor(props) { |
|
|
|
|
super(Object.assign({ |
|
|
|
|
sensors: [ |
|
|
|
|
new DistanceSensor('distR', { |
|
|
|
|
attachAngle: Math.PI/(2.5), // where the sensor is mounted on robot body
|
|
|
|
|
color: [150, 0, 0], // sensor color [in RGB], to distinguish them
|
|
|
|
|
lookAngle: (Math.PI/7 - Math.PI/(2.5)), |
|
|
|
|
attachRadius: 20 |
|
|
|
|
}), |
|
|
|
|
// define another sensor
|
|
|
|
|
new DistanceSensor('distL', { |
|
|
|
|
new DistanceSensor('dist', { |
|
|
|
|
attachAngle: -Math.PI/7, |
|
|
|
|
color: [0, 150, 0],
|
|
|
|
|
attachRadius: 20 |
|
|
|
|
attachRadius: 20, |
|
|
|
|
lookAngle: Math.PI/4, |
|
|
|
|
}), |
|
|
|
|
new Gyroscope('gyro', { |
|
|
|
|
attachAngle: 0, |
|
|
|
|
attachRadius: 5, |
|
|
|
|
color: [100,100,0] |
|
|
|
|
}), |
|
|
|
@ -60,33 +55,26 @@ class Lemming extends Robot {
|
|
|
|
|
dist: 5, |
|
|
|
|
width: 15, |
|
|
|
|
}), |
|
|
|
|
new DistanceSensor('wallR', { |
|
|
|
|
attachAngle: Math.PI/2.5, // where the sensor is mounted on robot body
|
|
|
|
|
color: [150, 0, 0], // sensor color [in RGB], to distinguish them
|
|
|
|
|
filter: x => x.role == 'wall', |
|
|
|
|
lookAngle: (Math.PI/7 - Math.PI/2.5), |
|
|
|
|
attachRadius: 20, |
|
|
|
|
|
|
|
|
|
}), |
|
|
|
|
// define another sensor
|
|
|
|
|
new DistanceSensor('wallL', { |
|
|
|
|
new DistanceSensor('wall', { |
|
|
|
|
attachAngle: -Math.PI/7, |
|
|
|
|
color: [0, 150, 0],
|
|
|
|
|
filter: x => x.role == 'wall', |
|
|
|
|
attachRadius: 20 |
|
|
|
|
filter: x => x.role != 'box', |
|
|
|
|
attachRadius: 20, |
|
|
|
|
lookAngle: Math.PI/4, |
|
|
|
|
}), |
|
|
|
|
].concat(props.sensors || []) |
|
|
|
|
}, props)) |
|
|
|
|
} |
|
|
|
|
turnDeg(rads, cb) { |
|
|
|
|
if (Math.abs(rads) >= 320) |
|
|
|
|
return this.turnDeg(320, x => this.turnDeg(rads -320, cb)) |
|
|
|
|
const torque = Math.sign(rads) * 0.01 |
|
|
|
|
turnDeg(degs, cb) { |
|
|
|
|
if (Math.abs(degs) >= 320) |
|
|
|
|
return this.turnDeg(320, x => this.turnDeg(degs -320, cb)) |
|
|
|
|
const torque = Math.sign(degs) * 0.002 |
|
|
|
|
const start = this.getSensorValById('gyro') |
|
|
|
|
this.move = function() { |
|
|
|
|
const curAngle = this.getSensorValById('gyro') |
|
|
|
|
const turned = ((curAngle - start) * Math.sign(rads) + 360) % 360 |
|
|
|
|
if (turned < 340 && (turned - Math.abs(rads) > 0)) { |
|
|
|
|
const turned = ((curAngle - start) * Math.sign(degs) + 360) % 360 |
|
|
|
|
if (turned < 340 && (turned - Math.abs(degs) > 0)) { |
|
|
|
|
delete this.move |
|
|
|
|
if (cb) cb() |
|
|
|
|
} else { |
|
|
|
@ -97,7 +85,7 @@ class Lemming extends Robot {
|
|
|
|
|
move() { |
|
|
|
|
//if (sim.curSteps % 250 == 0) this.turnDeg(-90)
|
|
|
|
|
// TODO: Define Lemming program here.
|
|
|
|
|
const {carry: [r,g,b], distL, distR, wallL, wallR} = this.getSensors() |
|
|
|
|
const {carry: [r,g,b], dist, wall} = this.getSensors() |
|
|
|
|
let block = 0 |
|
|
|
|
if (r > (g+b)) { |
|
|
|
|
block = 'red' |
|
|
|
@ -105,13 +93,13 @@ class Lemming extends Robot {
|
|
|
|
|
block = 'blue' |
|
|
|
|
} |
|
|
|
|
this.block = block |
|
|
|
|
if (distL < wallL - 5 || distR < wallR - 5) { |
|
|
|
|
if (dist < wall - 5) { |
|
|
|
|
this.state = 'block' |
|
|
|
|
// if it senses a block
|
|
|
|
|
if (!block) return this.drive(2e-4) // no block: drive towards block?
|
|
|
|
|
if (block == 'blue') void 0; // if blue: ignore
|
|
|
|
|
if (block == 'red') return this.turnDeg(-90) // if red: leave block
|
|
|
|
|
} else if (wallL < Infinity || wallR < Infinity) { |
|
|
|
|
} else if (wall < Infinity) { |
|
|
|
|
this.state = 'wall' |
|
|
|
|
// no block: turn left or right
|
|
|
|
|
if (!block) return this.turnDeg(90 * (Math.random() < 0.5 ? -1 : 1)) |
|
|
|
@ -121,14 +109,16 @@ class Lemming extends Robot {
|
|
|
|
|
this.state = 'nothing' |
|
|
|
|
} |
|
|
|
|
// by default: wander
|
|
|
|
|
this.rotate(+0.001); |
|
|
|
|
this.rotate(simInfo.wanderRate); |
|
|
|
|
this.drive(0.0002); |
|
|
|
|
} |
|
|
|
|
getDisplay() { |
|
|
|
|
return "carrying " + this.block + "\nseeing " + this.state |
|
|
|
|
return "carrying " + (this.block || "no") + " block seeing " + this.state |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
var sim = null |
|
|
|
|
var resultsTable = null |
|
|
|
|
let sim_id_counter = 0 |
|
|
|
|
class Simulation { |
|
|
|
|
constructor() { |
|
|
|
|
this.bay = null |
|
|
|
@ -139,6 +129,7 @@ class Simulation {
|
|
|
|
|
this.curSteps = 0 |
|
|
|
|
this.doContinue = false |
|
|
|
|
this.robots = [] |
|
|
|
|
this.id = sim_id_counter++ |
|
|
|
|
} |
|
|
|
|
init() { |
|
|
|
|
const arena = document.getElementById("arenaLemming"), |
|
|
|
@ -229,7 +220,7 @@ class Simulation {
|
|
|
|
|
padnumber(simInfo.maxSteps, 5); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
this.toggle() |
|
|
|
|
this.stop() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
draw() { |
|
|
|
|