This commit is contained in:
wassname
2018-11-26 19:14:59 +08:00
parent 42c5c8b76a
commit d05a4d61d4
5 changed files with 117 additions and 11 deletions
+12
View File
@@ -3,6 +3,8 @@
<head>
<title>HTML5 Genetic Algorithm Biped Walkers</title>
<link rel="stylesheet" href="css/walkers.css" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="vendor/jsbox2d.js"></script>
<script src="vendor/neurojs-v2.js"></script>
<script src="js/walker.js"></script>
@@ -10,6 +12,7 @@
<script src="js/floor.js"></script>
<script src="js/draw.js"></script>
<script src="js/agent.js"></script>
<script src="js/charts.js"></script>
<script>
function init() {
@@ -39,6 +42,15 @@
<div style="margin-top: 20px"><input type="checkbox" onclick="window.updateIfLearning(this.checked);" checked>Learning</div>
<div id="stats-wrapper">
<h3>Progress</h3>
<pre id="stats-prog"></pre>
<h3>Agent 1</h3>
<pre id="stats-ag0"></pre>
</div>
<div id="charts"></div>
</div>
</body>
</html>
+2 -2
View File
@@ -75,12 +75,12 @@ Agent.prototype.step = function () {
// TODO reset?
}
this.infos.push(info)
if (this.infos.length>this.maxInfos) this.infos = this.infos.slice(1)
// train
this.loss = this.brain.learn(reward)
info.loss = this.brain.learn(reward)
this.action = this.brain.policy(state)
this.infos.push(info)
}
if (this.action) {
this.walker.simulationPreStep(this.action)
+82
View File
@@ -0,0 +1,82 @@
var Charts = function() {
this.__constructor.apply(this, arguments);
}
Charts.prototype.__constructor = function () {
}
Charts.prototype.collect = function (agents) {
var data = {}
// collect data
var keys = Object.keys(agents[0].infos[0])
for (const key of keys) {
if (key === 'x') continue
data[key] = []
for (let i = 0; i < agents.length; i++) {
const infos = agents[i].infos;
// var borderColor = "hsl("+agents[i].walkerhue+",45%,"+(100-15*agents[i].walker.health/config.walker_health)+"%)";
// build dataset
var dataset = {
label: 'Agent ' + i, data: [], fill: false,
// borderColor
}
for (const info of infos) {
// a datapoint
dataset.data.push({
x: info['x'],
y: info[key]
})
}
data[key].push(dataset)
}
}
for (let i = 0; i < agents.length; i++) {
agents[i].infos = [] // empty it
}
return data
}
Charts.prototype.init = function (agents) {
var data = this.collect(agents)
var div = document.getElementById('charts');
// make charts
this.charts = []
for (const key in data) {
var canvas = document.createElement("canvas");
div.appendChild(canvas)
var ctx = canvas.getContext('2d');
var lineChart = new Chart(ctx, {
type: 'scatter',
data: { datasets: data[key] },
options: {
title: { text: key, display: true },
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
}
}
});
this.charts.push(lineChart)
}
}
Charts.prototype.update = function (agents) {
var data = this.collect(agents)
for (const chart of this.charts) {
var newDatasets = data[chart.config.options.title.text]
chart.data.datasets.forEach((dataset) => {
var dat = newDatasets.filter(d=>d.label==dataset.label)[0].data
dataset.data.push(...dat);
});
chart.update();
}
}
+13 -7
View File
@@ -45,7 +45,6 @@ displayProgress = function () {
'meanReward': globals.walkers.map(w => w.reward).reduce((s, v) => s + v) / globals.walkers.length,
}
document.getElementById('stats-prog').innerText = JSON.stringify(stats, null, 2)
document.getElementById('stats-ag0').innerText = JSON.stringify(globals.walkers[0].rewards, null, 2)
}
gameInit = function() {
@@ -98,15 +97,11 @@ gameInit = function() {
globals.simulation_interval = setInterval(simulationStep, Math.round(1000/config.simulation_fps));
globals.draw_interval = setInterval(drawFrame, Math.round(1000 / config.draw_fps));
globals.reset_interval = setInterval(resetSimulation, Math.round(config.round_length * 1000 / config.draw_fps));
globals.logr_interval = setInterval(logRewards, Math.round(800 * 1000 / config.draw_fps));
globals.display_interval = setInterval(displayProgress, Math.round(80 * 1000 / config.draw_fps));
globals.charts_interval = setInterval(updateCharts, Math.round(80 * 1000 / config.draw_fps));
}
logRewards = function () {
for(var k = 0; k < config.population_size; k++) {
console.table(globals.walkers[k].rewards)
}
}
resetSimulation = function () {
// turn training off temporarlity to avoid NaN's
@@ -129,6 +124,17 @@ simulationStep = function () {
populationSimulationStep();
}
updateCharts = function () {
if (globals.agents[0].infos.length) {
if (!globals.charts) {
globals.charts = new Charts()
globals.charts.init(globals.agents)
} else {
globals.charts.update(globals.agents)
}
}
}
// setSimulationFps = function(fps) {
// config.simulation_fps = fps;
// clearInterval(globals.simulation_interval);
+8 -2
View File
@@ -6,12 +6,12 @@ function deg2rad(deg) {
return deg/180*Math.PI
}
const STRENGTH = 6
var Walker = function() {
this.__constructor.apply(this, arguments);
}
const STRENGTH = 6
Walker.prototype.__constructor = function(world) {
this.world = globals.world;
@@ -337,6 +337,7 @@ Walker.prototype.simulationPreStep = function (motorSpeeds) {
}
Walker.prototype.simulationStep = function (motorSpeeds) {
this.steps ++
/* score/reward */
// reward copied from OpenAI Gym Humanoid Walker https://github.com/openai/gym/blob/master/gym/envs/mujoco/humanoid.py
// also see https://github.com/AdamStelmaszczyk/learning2run/blob/master/osim-rl/osim/env/run.py#L67
@@ -381,7 +382,12 @@ Walker.prototype.simulationStep = function (motorSpeeds) {
this.last_left_left_forward = left_leg_forward
var info = {}
var info = {
x: this.steps,
reward:this.reward,
position,
...this.rewards
}
var done = 0
return [this.getState(), this.reward, done, info]
}