mirror of
https://github.com/wassname/rl_2d_walker.js.git
synced 2026-09-10 12:32:46 +08:00
charts
This commit is contained in:
+12
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user