Skip to content

Commit 28be083

Browse files
committed
finalizing the new steering example
1 parent c8b1a38 commit 28be083

File tree

4 files changed

+82
-51
lines changed

4 files changed

+82
-51
lines changed

examples/NeuroEvolution-steering/vehicle.js renamed to examples/NeuroEvolution-steering/creature.js

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
class Vehicle {
1+
class Creature {
22
constructor(x, y, brain) {
33
this.position = createVector(x, y);
44
this.velocity = createVector(0, 0);
@@ -11,44 +11,48 @@ class Vehicle {
1111
this.brain = brain;
1212
} else {
1313
this.brain = ml5.neuralNetwork({
14-
inputs: 2,
14+
inputs: 5,
1515
outputs: 2,
1616
task: "regression",
1717
neuroEvolution: true,
1818
});
1919
}
2020
}
2121

22-
eat(food) {
23-
let d = p5.Vector.dist(this.position, food);
24-
if (d < 10) {
25-
this.fitness++;
26-
target = createVector(random(width), random(height));
27-
}
28-
}
29-
30-
think(food) {
31-
let v = p5.Vector.sub(food, this.position);
22+
seek(target) {
23+
let v = p5.Vector.sub(target.position, this.position);
24+
let distance = v.mag();
3225
v.normalize();
33-
let inputs = [v.x, v.y];
26+
let inputs = [
27+
v.x,
28+
v.y,
29+
distance / width,
30+
this.velocity.x / this.maxspeed,
31+
this.velocity.y / this.maxspeed,
32+
];
3433

3534
// Predicting the force to apply
36-
const outputs = this.brain.predictSync(inputs);
35+
let outputs = this.brain.predictSync(inputs);
3736
let angle = outputs[0].value * TWO_PI;
3837
let magnitude = outputs[1].value;
3938
let force = p5.Vector.fromAngle(angle).setMag(magnitude);
4039
this.applyForce(force);
4140
}
4241

4342
// Method to update location
44-
update() {
43+
update(target) {
4544
// Update velocity
4645
this.velocity.add(this.acceleration);
4746
// Limit speed
4847
this.velocity.limit(this.maxspeed);
4948
this.position.add(this.velocity);
5049
// Reset acceleration to 0 each cycle
5150
this.acceleration.mult(0);
51+
52+
let d = p5.Vector.dist(this.position, target.position);
53+
if (d < this.r + target.r) {
54+
this.fitness++;
55+
}
5256
}
5357

5458
applyForce(force) {
@@ -61,6 +65,7 @@ class Vehicle {
6165
let angle = this.velocity.heading();
6266
fill(127);
6367
stroke(0);
68+
strokeWeight(1);
6469
push();
6570
translate(this.position.x, this.position.y);
6671
rotate(angle);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Glow {
2+
constructor() {
3+
this.xoff = 0;
4+
this.yoff = 1000;
5+
this.position = createVector();
6+
this.r = 24;
7+
}
8+
9+
update() {
10+
this.position.x = noise(this.xoff) * width;
11+
this.position.y = noise(this.yoff) * height;
12+
this.xoff += 0.01;
13+
this.yoff += 0.01;
14+
}
15+
16+
show() {
17+
stroke(0);
18+
strokeWeight(2);
19+
fill(200);
20+
circle(this.position.x, this.position.y, this.r * 2);
21+
}
22+
}

examples/NeuroEvolution-steering/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
<script src="../../dist/ml5.js"></script>
1010
</head>
1111
<body>
12-
<script src="vehicle.js"></script>
12+
<script src="glow.js"></script>
13+
<script src="creature.js"></script>
1314
<script src="sketch.js"></script>
1415
</body>
1516
</html>
Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,82 @@
1-
let vehicles = [];
1+
let creatures = [];
22
let timeSlider;
3-
let lifetime = 0;
4-
let target;
3+
let lifeSpan = 250; // How long should each generation live
4+
let lifeCounter = 0; // Timer for cycle of generation
5+
let food;
6+
let generations = 0;
57

68
function setup() {
79
createCanvas(640, 240);
10+
ml5.tf.setBackend("cpu");
811
for (let i = 0; i < 50; i++) {
9-
vehicles[i] = new Vehicle(random(width), random(height));
12+
creatures[i] = new Creature(random(width), random(height));
1013
}
11-
ml5.tf.setBackend("cpu");
12-
target = createVector(random(width), random(height));
14+
glow = new Glow();
1315
timeSlider = createSlider(1, 20, 1);
1416
}
1517

1618
function draw() {
1719
background(255);
18-
for (let i = 0; i < timeSlider.value(); i++) {
19-
for (let v of vehicles) {
20-
v.think(target);
21-
v.eat(target);
22-
v.update();
23-
}
24-
lifetime++;
25-
}
2620

27-
for (let v of vehicles) {
28-
v.show();
21+
glow.update();
22+
glow.show();
23+
24+
for (let creature of creatures) {
25+
creature.show();
2926
}
3027

31-
fill(0, 0, 255, 150);
32-
noStroke();
33-
circle(target.x, target.y, 32);
28+
for (let i = 0; i < timeSlider.value(); i++) {
29+
for (let creature of creatures) {
30+
creature.seek(glow);
31+
creature.update(glow);
32+
}
33+
lifeCounter++;
34+
}
3435

35-
if (lifetime > 500) {
36+
if (lifeCounter > lifeSpan) {
3637
normalizeFitness();
3738
reproduction();
38-
target = createVector(random(width), random(height));
39-
lifetime = 0;
39+
lifeCounter = 0;
40+
generations++;
4041
}
4142
fill(0);
42-
text(lifetime, 10, 30);
43+
noStroke();
44+
text("Generation #: " + generations, 10, 18);
45+
text("Cycles left: " + (lifeSpan - lifeCounter), 10, 36);
4346
}
4447

4548
function normalizeFitness() {
46-
for (let v of vehicles) {
47-
v.fitness = pow(2, v.fitness);
49+
for (let creature of creatures) {
50+
creature.fitness = pow(2, creature.fitness);
4851
}
4952
let sum = 0;
50-
for (let v of vehicles) {
51-
sum += v.fitness;
53+
for (let creature of creatures) {
54+
sum += creature.fitness;
5255
}
53-
for (let v of vehicles) {
54-
v.fitness = v.fitness / sum;
56+
for (let creature of creatures) {
57+
creature.fitness = creature.fitness / sum;
5558
}
5659
}
5760

5861
function reproduction() {
59-
let nextVehicles = [];
60-
for (let i = 0; i < vehicles.length; i++) {
62+
let nextCreatures = [];
63+
for (let i = 0; i < creatures.length; i++) {
6164
let parentA = weightedSelection();
6265
let parentB = weightedSelection();
6366
let child = parentA.crossover(parentB);
6467
child.mutate(0.1);
65-
nextVehicles[i] = new Vehicle(random(width), random(height), child);
68+
nextCreatures[i] = new Creature(random(width), random(height), child);
6669
}
67-
vehicles = nextVehicles;
70+
creatures = nextCreatures;
6871
}
6972

7073
function weightedSelection() {
7174
let index = 0;
7275
let start = random(1);
7376
while (start > 0) {
74-
start = start - vehicles[index].fitness;
77+
start = start - creatures[index].fitness;
7578
index++;
7679
}
7780
index--;
78-
return vehicles[index].brain;
81+
return creatures[index].brain;
7982
}

0 commit comments

Comments
 (0)