mirror of
https://github.com/wassname/rl_2d_walker.js.git
synced 2026-09-09 11:33:20 +08:00
moving around, webpack
This commit is contained in:
-93
@@ -1,93 +0,0 @@
|
||||
|
||||
function Agent(opt, globals) {
|
||||
this.walker = new Walker(globals.world, globals.floor)
|
||||
this.options = opt
|
||||
|
||||
this.globals = globals
|
||||
this.frequency = 20
|
||||
this.loaded = false
|
||||
|
||||
this.infos = []
|
||||
this.maxInfos = 2000
|
||||
|
||||
this.steps = 0
|
||||
this.timer = 0
|
||||
this.timerFrequency = 60 / this.frequency
|
||||
|
||||
if (this.options.dynamicallyLoaded !== true) {
|
||||
this.init(globals.brains.actor.newConfiguration(), null)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Agent.prototype.init = function (actor, critic) {
|
||||
var actions = this.walker.joints.length + 4
|
||||
var temporal = 1
|
||||
var states = this.walker.bodies.length * 10 + this.walker.joints.length * 3
|
||||
|
||||
var input = window.neurojs.Agent.getInputDimension(states, actions, temporal)
|
||||
|
||||
// Example params https://github.com/udacity/deep-reinforcement-learning/blob/master/ddpg-bipedal/ddpg_agent.py
|
||||
this.brain = new window.neurojs.Agent({
|
||||
actor: actor,
|
||||
critic: critic,
|
||||
|
||||
states: states,
|
||||
actions: actions,
|
||||
|
||||
algorithm: 'ddpg',
|
||||
|
||||
temporalWindow: temporal,
|
||||
|
||||
discount: 0.99, // time discount
|
||||
rate: 3e-4, // learning rate,
|
||||
theta: 1e-3, // progressive copy
|
||||
// alpha: 0.1, // advantage learning
|
||||
|
||||
// buffer: window.neurojs.Buffers.UniformReplayBuffer,
|
||||
experience: 100e3,
|
||||
|
||||
learningPerTick: 512,
|
||||
startLearningAt: 10000,
|
||||
})
|
||||
|
||||
this.brain.algorithm.critic.optim.regularization.l2 = 0.0001
|
||||
this.brain.algorithm.actor.optim.regularization.l2 = 0.0001
|
||||
|
||||
// this.globals.brains.shared.add('actor', this.brain.algorithm.actor)
|
||||
this.globals.brains.shared.add('critic', this.brain.algorithm.critic)
|
||||
|
||||
this.actions = actions
|
||||
this.loaded = true
|
||||
};
|
||||
|
||||
Agent.prototype.step = function () {
|
||||
if (!this.loaded) {
|
||||
return
|
||||
}
|
||||
|
||||
this.timer++
|
||||
|
||||
if (this.timer % this.timerFrequency === 0) {
|
||||
this.steps++
|
||||
var [state, reward, done, info] = this.walker.simulationStep()
|
||||
|
||||
if (done) {
|
||||
// TODO reset?
|
||||
}
|
||||
|
||||
if (this.infos.length>this.maxInfos) this.infos = this.infos.slice(1)
|
||||
|
||||
// train
|
||||
info.loss = this.brain.learn(reward)
|
||||
this.action = this.brain.policy(state)
|
||||
info.x = this.steps
|
||||
info.time = new Date().getTime()
|
||||
this.infos.push(info)
|
||||
}
|
||||
if (this.action) {
|
||||
this.walker.simulationPreStep(this.action)
|
||||
}
|
||||
|
||||
return this.timer % this.timerFrequency === 0
|
||||
};
|
||||
-243
@@ -1,243 +0,0 @@
|
||||
var requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); };
|
||||
|
||||
config = {
|
||||
time_step: 60,
|
||||
simulation_fps: 60,
|
||||
draw_fps: 60,
|
||||
velocity_iterations: 8,
|
||||
position_iterations: 3,
|
||||
max_zoom_factor: 130,
|
||||
min_motor_speed: -2,
|
||||
max_motor_speed: 2,
|
||||
population_size: 1,
|
||||
walker_health: 100,
|
||||
max_floor_tiles: 50,
|
||||
round_length: 1000,
|
||||
min_body_delta: 0,
|
||||
min_leg_delta: 0.0,
|
||||
};
|
||||
|
||||
globals = {};
|
||||
|
||||
chooseQoute = function () {
|
||||
var qoutes = [
|
||||
'Play the funky music, robot',
|
||||
'The origin of funkd',
|
||||
'The chaos computer club',
|
||||
'Only the humans that like to dance survived',
|
||||
'Classic robot dance move - the human',
|
||||
'First we dance Manhatten, then we dance the world',
|
||||
'Video of subjects one hour after ingesting substance q1043',
|
||||
'Red robot redemption',
|
||||
'Father was a rolling robot',
|
||||
'Float like a bumblebee, string like a butterfly',
|
||||
'Dance evolution',
|
||||
'Have you tried turning it off and on again?',
|
||||
'Eurovision 2050',
|
||||
'Humans must learn to crawl then walk. Robots break dance then walk',
|
||||
''
|
||||
]
|
||||
var qoute = qoutes[Math.randi(0,qoutes.length)]
|
||||
document.getElementById('page_quote').innerText = '"'+qoute+'"'
|
||||
|
||||
}
|
||||
|
||||
displayProgress = function () {
|
||||
// TODO show stats
|
||||
var stats = {
|
||||
'trainingTime': globals.step_counter / config.simulation_fps,
|
||||
'meanProgress': globals.walkers.map(w => w.last_position).reduce((s, v) => s + v) / globals.walkers.length,
|
||||
'meanReward': globals.walkers.map(w => w.reward).reduce((s, v) => s + v) / globals.walkers.length,
|
||||
'bufferSize': globals.agents[0].brain.buffer.size
|
||||
}
|
||||
document.getElementById('stats-prog').innerText = JSON.stringify(stats, null, 2)
|
||||
}
|
||||
|
||||
gameInit = function() {
|
||||
var bodyParts = 16
|
||||
var joints = 14
|
||||
var state = bodyParts * 10 + joints * 3
|
||||
var actions = joints + 4
|
||||
var input = 2 * state + 1 * actions
|
||||
|
||||
|
||||
globals.brains = {
|
||||
actor: new window.neurojs.Network.Model([
|
||||
{ type: 'input', size: input },
|
||||
{ type: 'fc', size: 256, activation: 'relu' },
|
||||
// { type: 'noise', sigma: 0.2, delta: 0.001, theta: 0.15 },
|
||||
// { type: 'fc', size: 160, activation: 'relu' },
|
||||
// { type: 'noise', sigma: 0.2, delta: 0.001, theta: 0.15 },
|
||||
// { type: 'fc', size: 100, activation: 'relu' },
|
||||
{ type: 'fc', size: 40, activation: 'relu', dropout: 0.30 },
|
||||
// delta represents the equilibrium or mean value supported by fundamentals;
|
||||
// sigma the degree of volatility around it caused by shocks,
|
||||
// theta the rate by which these shocks dissipate and the variable reverts towards the mean.
|
||||
{ type: 'fc', size: actions, activation: 'tanh' },
|
||||
{ type: 'noise', sigma: 0.3, delta: 0.1, theta: 0.15 },
|
||||
{ type: 'regression' }
|
||||
|
||||
]),
|
||||
|
||||
critic: new window.neurojs.Network.Model([
|
||||
|
||||
{ type: 'input', size: input + actions },
|
||||
{ type: 'fc', size: 256, activation: 'relu' },
|
||||
// { type: 'fc', size: 256, activation: 'relu' },
|
||||
{ type: 'fc', size: 40, activation: 'relu' },
|
||||
{ type: 'fc', size: 1 },
|
||||
{ type: 'regression' }
|
||||
|
||||
])
|
||||
|
||||
}
|
||||
|
||||
globals.brains.shared = new window.neurojs.Shared.ConfigPool()
|
||||
|
||||
// this.brains.shared.set('actor', this.brains.actor.newConfiguration())
|
||||
globals.brains.shared.set('critic', globals.brains.critic.newConfiguration())
|
||||
|
||||
|
||||
chooseQoute()
|
||||
globals.world = new b2.World(new b2.Vec2(0, -10));
|
||||
globals.floor = createFloor(globals.world);
|
||||
[globals.agents, globals.walkers] = createPopulation();
|
||||
|
||||
drawInit();
|
||||
|
||||
globals.step_counter = 0;
|
||||
|
||||
globals.display_interval = setInterval(displayProgress, Math.round(380 * 1000 / config.draw_fps));
|
||||
globals.charts_interval = setInterval(updateCharts, Math.round(380 * 1000 / config.draw_fps));
|
||||
|
||||
globals.running = true
|
||||
requestAnimFrame(loop)
|
||||
|
||||
}
|
||||
|
||||
loop = function () {
|
||||
drawFrame()
|
||||
simulationStep()
|
||||
drawFrame()
|
||||
if (globals.running) requestAnimFrame(loop); // start next timer
|
||||
}
|
||||
|
||||
|
||||
resetSimulation = function () {
|
||||
// turn training off temporarlity to avoid NaN's
|
||||
updateIfLearning(false)
|
||||
// globals.running = false
|
||||
|
||||
globals.world.Destroy() // this way we get rid of listeners and body parts and joints
|
||||
globals.world = new b2.World(new b2.Vec2(0, -10));
|
||||
globals.floor = createFloor(globals.world);
|
||||
for (var k = 0; k < config.population_size; k++) {
|
||||
globals.agents[k].walker = globals.walkers[k] = new Walker(globals.world, globals.floor)
|
||||
}
|
||||
|
||||
// globals.running = true
|
||||
setTimeout(() => updateIfLearning(true), 1000)
|
||||
// setTimeout(() => requestAnimFrame(loop), 1000)
|
||||
|
||||
}
|
||||
|
||||
simulationStep = function () {
|
||||
globals.step_counter++;
|
||||
|
||||
// step world
|
||||
globals.world.Step(1/config.time_step, config.velocity_iterations, config.position_iterations);
|
||||
populationSimulationStep();
|
||||
globals.world.ClearForces();
|
||||
|
||||
// step agents (only after step 50 when they are on the ground)
|
||||
}
|
||||
|
||||
updateCharts = function () {
|
||||
var groupN = 100
|
||||
if (globals.agents[0].infos.length>=groupN) {
|
||||
if (!globals.charts) {
|
||||
globals.charts = new Charts()
|
||||
globals.charts.init(globals.agents, groupN)
|
||||
} else {
|
||||
globals.charts.update(globals.agents, groupN, 100000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createPopulation = function(genomes) {
|
||||
var walkers = [];
|
||||
var agents = []
|
||||
for(var k = 0; k < config.population_size; k++) {
|
||||
var agent = new Agent({}, globals)
|
||||
agents.push(agent);
|
||||
walkers.push(agent.walker)
|
||||
|
||||
}
|
||||
return [agents, walkers];
|
||||
}
|
||||
|
||||
|
||||
populationSimulationStep = function() {
|
||||
for (var k = 0; k < config.population_size; k++) {
|
||||
if (globals.walkers[k].steps>150)
|
||||
globals.agents[k].step()
|
||||
else
|
||||
globals.walkers[k].simulationStep()
|
||||
}
|
||||
var steps = globals.agents[0].walker.steps
|
||||
if ((steps!==0) && (0 == steps % config.round_length)) {
|
||||
resetSimulation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveAs(dv, name) {
|
||||
var a;
|
||||
if (typeof window.downloadAnchor == 'undefined') {
|
||||
a = window.downloadAnchor = document.createElement("a");
|
||||
a.style = "display: none";
|
||||
document.body.appendChild(a);
|
||||
} else {
|
||||
a = window.downloadAnchor
|
||||
}
|
||||
|
||||
var blob = new Blob([dv], { type: 'application/octet-binary' }),
|
||||
tmpURL = window.URL.createObjectURL(blob);
|
||||
|
||||
a.href = tmpURL;
|
||||
a.download = name;
|
||||
a.click();
|
||||
|
||||
window.URL.revokeObjectURL(tmpURL);
|
||||
a.href = "";
|
||||
}
|
||||
|
||||
downloadBrain = function (n) {
|
||||
var ts = (new Date()).toISOString().replace(':','_')
|
||||
var buf = globals.agents[n].brain.export()
|
||||
saveAs(new DataView(buf), 'walker_brain_'+n+'_'+ts+'.bin')
|
||||
};
|
||||
|
||||
|
||||
readBrain = function (buf) {
|
||||
var input = event.target;
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var buffer = reader.result
|
||||
var imported = window.neurojs.NetOnDisk.readMultiPart(buffer)
|
||||
|
||||
for (var i = 0; i < globals.agents.length; i++) {
|
||||
globals.agents[i].brain.algorithm.actor.set(imported.actor.clone())
|
||||
globals.agents[i].brain.algorithm.critic.set(imported.critic)
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(input.files[0]);
|
||||
};
|
||||
|
||||
|
||||
updateIfLearning = function (value) {
|
||||
for (var i = 0; i < globals.agents.length; i++) {
|
||||
globals.agents[i].brain.learning = value
|
||||
}
|
||||
};
|
||||
+3
-1
@@ -9,7 +9,9 @@
|
||||
"jsdom": "^13.0.0",
|
||||
"phaser": "^3.15.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"devDependencies": {
|
||||
"webpack-cli": "^3.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
|
||||
@@ -3,16 +3,31 @@
|
||||
<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/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="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.6"> </script> -->
|
||||
|
||||
<!-- <script type="text/javascript" src="/js/ddpg/models.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="/js/ddpg/memory.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="/js/ddpg/prioritized_memory.js"></script>
|
||||
<script type="text/javascript" src="/js/ddpg/noise.js"></script>
|
||||
<script type="text/javascript" src="/js/ddpg/ddpg.js"></script>
|
||||
<script type="text/javascript" src="/js/ddpg/ddpg_agent.js"></script>
|
||||
<script type="text/javascript" src="/js/ddpg-traffic/index.js"></script>
|
||||
|
||||
<script src="js/walker.js"></script>
|
||||
<script src="js/game.js"></script>
|
||||
<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 src="js/charts.js"></script> -->
|
||||
|
||||
<script src="dist/bundle.js"></script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function init() {
|
||||
@@ -0,0 +1 @@
|
||||
const { Game } = require('game')
|
||||
@@ -91,3 +91,4 @@ Charts.prototype.update = function (agents) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports ={Chart}
|
||||
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
time_step: 60,
|
||||
simulation_fps: 60,
|
||||
draw_fps: 60,
|
||||
velocity_iterations: 8,
|
||||
position_iterations: 3,
|
||||
max_zoom_factor: 130,
|
||||
min_motor_speed: -2,
|
||||
max_motor_speed: 2,
|
||||
population_size: 1,
|
||||
walker_health: 100,
|
||||
max_floor_tiles: 50,
|
||||
round_length: 1000,
|
||||
min_body_delta: 0,
|
||||
min_leg_delta: 0.0,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
// class Memory {
|
||||
|
||||
// /**
|
||||
// * @param maxlen (number) Buffer limit
|
||||
// */
|
||||
// constructor(maxlen){
|
||||
// this.maxlen = maxlen;
|
||||
// this.length = 0;
|
||||
// this.start = 0;
|
||||
|
||||
// this.obs0List = Array.apply(null, Array(maxlen)).map(Number.prototype.valueOf, 0);
|
||||
// this.obs1List = Array.apply(null, Array(maxlen)).map(Number.prototype.valueOf, 0);
|
||||
// this.rewardsList = Array.apply(null, Array(maxlen)).map(Number.prototype.valueOf, 0);
|
||||
// this.actionsList = Array.apply(null, Array(maxlen)).map(Number.prototype.valueOf, 0);
|
||||
// this.terminals1List = Array.apply(null, Array(maxlen)).map(Number.prototype.valueOf, 0);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @param idx (number)
|
||||
// */
|
||||
// getItem(idx){
|
||||
// if (idx < 0 || idx >= this.length){
|
||||
// console.error("Memory.getItem: idx not in range.");
|
||||
// }
|
||||
// return this.data[(this.start + idx) % this.maxlen]
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Sample a batch
|
||||
// * @param batchSize (number)
|
||||
// * @return batch []
|
||||
// */
|
||||
// getBatch(batchSize){
|
||||
// const arrLength = this.length;
|
||||
// const batch = {
|
||||
// 'obs0': [],
|
||||
// 'obs1': [],
|
||||
// 'rewards': [],
|
||||
// 'actions': [],
|
||||
// 'terminals': [],
|
||||
// };
|
||||
// if (batchSize > this.length){
|
||||
// return batch;
|
||||
// }
|
||||
// for (let b=0; b < batchSize; b++){
|
||||
// let id = Math.floor(Math.random() * arrLength);
|
||||
// batch.obs0.push(this.obs0List[id]);
|
||||
// batch.obs1.push(this.obs1List[id]);
|
||||
// batch.rewards.push(this.rewardsList[id]);
|
||||
// batch.actions.push(this.actionsList[id]);
|
||||
// batch.terminals.push(this.terminals1List[id]);
|
||||
// }
|
||||
// return batch
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @param obs0 []
|
||||
// * @param action (number)
|
||||
// * @param reward (number)
|
||||
// * @param obs1 []
|
||||
// * @param terminal1 (boolean)
|
||||
// */
|
||||
// append(obs0, action, reward, obs1, terminal1){
|
||||
// if (this.length < this.maxlen){
|
||||
// this.length += 1;
|
||||
// }
|
||||
// else if (this.length == this.maxlen) {
|
||||
// //this.obs0List[(this.start + this.length - 1) % this.maxlen].dispose();
|
||||
// //this.obs1List[(this.start + this.length - 1) % this.maxlen].dispose();
|
||||
// //this.actionsList[(this.start + this.length - 1) % this.maxlen].dispose();
|
||||
// this.start = (this.start + 1) % this.maxlen;
|
||||
// }
|
||||
// else {
|
||||
// console.error("Memory.append: This should never be printed");
|
||||
// }
|
||||
// this.obs0List[(this.start + this.length - 1) % this.maxlen] = obs0;
|
||||
// this.obs1List[(this.start + this.length - 1) % this.maxlen] = obs1;
|
||||
// this.rewardsList[(this.start + this.length - 1) % this.maxlen] = reward;
|
||||
// this.actionsList[(this.start + this.length - 1) % this.maxlen] = action;
|
||||
// this.terminals1List[(this.start + this.length - 1) % this.maxlen] = terminal1;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// module.exports = Memory
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
const config = require('./config')
|
||||
const {Charts} = require('./charts')
|
||||
|
||||
|
||||
if typeof window !=="undefined"
|
||||
var requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); };
|
||||
else
|
||||
var requestAnimFrame = function (callback) { window.setTimeout(callback, 1000 / 60); };
|
||||
|
||||
|
||||
chooseQoute = function () {
|
||||
var qoutes = [
|
||||
'Play the funky music, robot',
|
||||
'The origin of funkd',
|
||||
'The chaos computer club',
|
||||
'Only the humans that like to dance survived',
|
||||
'Classic robot dance move - the human',
|
||||
'First we dance Manhatten, then we dance the world',
|
||||
'Video of subjects one hour after ingesting substance q1043',
|
||||
'Red robot redemption',
|
||||
'Father was a rolling robot',
|
||||
'Float like a bumblebee, string like a butterfly',
|
||||
'Dance evolution',
|
||||
'Have you tried turning it off and on again?',
|
||||
'Eurovision 2050',
|
||||
'Humans must learn to crawl then walk. Robots break dance then walk',
|
||||
''
|
||||
]
|
||||
var qoute = qoutes[Math.randi(0,qoutes.length)]
|
||||
document.getElementById('page_quote').innerText = '"'+qoute+'"'
|
||||
|
||||
}
|
||||
|
||||
class Game {
|
||||
constructor(params) {
|
||||
var bodyParts = 16
|
||||
var joints = 14
|
||||
var state = bodyParts * 10 + joints * 3
|
||||
var actions = joints + 4
|
||||
var input = 2 * state + 1 * actions
|
||||
|
||||
|
||||
chooseQoute()
|
||||
this.world = new b2.World(new b2.Vec2(0, -10));
|
||||
this.floor = createFloor(this.world);
|
||||
[this.agents, this.walkers] = createPopulation();
|
||||
|
||||
drawInit();
|
||||
|
||||
this.step_counter = 0;
|
||||
|
||||
this.display_interval = setInterval(displayProgress, Math.round(380 * 1000 / config.draw_fps));
|
||||
this.charts_interval = setInterval(updateCharts, Math.round(380 * 1000 / config.draw_fps));
|
||||
|
||||
this.running = true
|
||||
requestAnimFrame(loop)
|
||||
}
|
||||
|
||||
displayProgress() {
|
||||
var stats = {
|
||||
'trainingTime': this.step_counter / config.simulation_fps,
|
||||
'meanProgress': this.walkers.map(w => w.last_position).reduce((s, v) => s + v) / this.walkers.length,
|
||||
'meanReward': this.walkers.map(w => w.reward).reduce((s, v) => s + v) / this.walkers.length,
|
||||
'bufferSize': this.agents[0].brain.buffer.size
|
||||
}
|
||||
document.getElementById('stats-prog').innerText = JSON.stringify(stats, null, 2)
|
||||
}
|
||||
|
||||
|
||||
resetSimulation() {
|
||||
// turn training off temporarlity to avoid NaN's
|
||||
updateIfLearning(false)
|
||||
// this.running = false
|
||||
|
||||
this.world.Destroy() // this way we get rid of listeners and body parts and joints
|
||||
this.world = new b2.World(new b2.Vec2(0, -10));
|
||||
this.floor = createFloor(this.world);
|
||||
for (var k = 0; k < config.population_size; k++) {
|
||||
this.agents[k].walker = this.walkers[k] = new Walker(this.world, this.floor)
|
||||
}
|
||||
|
||||
// this.running = true
|
||||
setTimeout(() => updateIfLearning(true), 1000)
|
||||
// setTimeout(() => requestAnimFrame(loop), 1000)
|
||||
|
||||
}
|
||||
|
||||
loop() {
|
||||
drawFrame()
|
||||
simulationStep()
|
||||
drawFrame()
|
||||
if (this.running) requestAnimFrame(loop); // start next timer
|
||||
}
|
||||
|
||||
|
||||
updateCharts() {
|
||||
var groupN = 100
|
||||
var maxN = 100000
|
||||
if (this.agents[0].infos.length>=groupN) {
|
||||
if (!this.charts) {
|
||||
this.charts = new Charts()
|
||||
this.charts.init(this.agents, groupN)
|
||||
} else {
|
||||
this.charts.update(this.agents, groupN, maxN)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function saveAs(dv, name) {
|
||||
var a;
|
||||
if (typeof window.downloadAnchor == 'undefined') {
|
||||
a = window.downloadAnchor = document.createElement("a");
|
||||
a.style = "display: none";
|
||||
document.body.appendChild(a);
|
||||
} else {
|
||||
a = window.downloadAnchor
|
||||
}
|
||||
|
||||
var blob = new Blob([dv], { type: 'application/octet-binary' }),
|
||||
tmpURL = window.URL.createObjectURL(blob);
|
||||
|
||||
a.href = tmpURL;
|
||||
a.download = name;
|
||||
a.click();
|
||||
|
||||
window.URL.revokeObjectURL(tmpURL);
|
||||
a.href = "";
|
||||
}
|
||||
|
||||
// downloadBrain = function (n) {
|
||||
// var ts = (new Date()).toISOString().replace(':','_')
|
||||
// var buf = this.agents[n].brain.export()
|
||||
// saveAs(new DataView(buf), 'walker_brain_'+n+'_'+ts+'.bin')
|
||||
// };
|
||||
|
||||
|
||||
// readBrain = function (buf) {
|
||||
// var input = event.target;
|
||||
// var reader = new FileReader();
|
||||
// reader.onload = function(){
|
||||
// var buffer = reader.result
|
||||
// var imported = window.neurojs.NetOnDisk.readMultiPart(buffer)
|
||||
|
||||
// for (var i = 0; i < this.agents.length; i++) {
|
||||
// this.agents[i].brain.algorithm.actor.set(imported.actor.clone())
|
||||
// this.agents[i].brain.algorithm.critic.set(imported.critic)
|
||||
// }
|
||||
// };
|
||||
|
||||
// reader.readAsArrayBuffer(input.files[0]);
|
||||
// };
|
||||
|
||||
|
||||
module.exports = {Game, chooseQoute, saveAs}
|
||||
@@ -0,0 +1,7 @@
|
||||
var randf = (low, high) => Math.random() * (high - low) + low
|
||||
|
||||
function deg2rad(deg) {
|
||||
return deg / 180 * Math.PI
|
||||
}
|
||||
|
||||
module.exports = {deg2rad, randf}
|
||||
@@ -1,10 +1,7 @@
|
||||
// walker has fixed shapes and structures
|
||||
// shape definitions are in the constructor
|
||||
var randf = (low, high) => Math.random() * (high - low) + low
|
||||
|
||||
function deg2rad(deg) {
|
||||
return deg / 180 * Math.PI
|
||||
}
|
||||
const b2 = require('../vendor/jsbox2d')
|
||||
const { randf, deg2rad } = require('./utils.js')
|
||||
|
||||
const STRENGTH = 3
|
||||
|
||||
@@ -631,49 +628,4 @@ Walker.prototype.shuffle = function () {
|
||||
console.log('shuffle not implemented')
|
||||
}
|
||||
|
||||
|
||||
config = {
|
||||
time_step: 60,
|
||||
simulation_fps: 60,
|
||||
draw_fps: 60,
|
||||
velocity_iterations: 8,
|
||||
position_iterations: 3,
|
||||
max_zoom_factor: 130,
|
||||
min_motor_speed: -2,
|
||||
max_motor_speed: 2,
|
||||
population_size: 1,
|
||||
walker_health: 100,
|
||||
max_floor_tiles: 50,
|
||||
round_length: 1000,
|
||||
min_body_delta: 0,
|
||||
min_leg_delta: 0.0,
|
||||
};
|
||||
|
||||
var b2 = require('../vendor/jsbox2d')
|
||||
var createFloor = require('./floor.js')
|
||||
var DDPGAgent = require('./ddpg/ddpg_agent')
|
||||
var DDPGAgent = require('./ddpg/ddpg_agent')
|
||||
|
||||
|
||||
var world = new b2.World(new b2.Vec2(0, -10))
|
||||
floor = createFloor(world, config.max_floor_tiles);
|
||||
var env = new Walker(world, floor, config)
|
||||
|
||||
var nbActions = env.joints.length + 4
|
||||
var stateSize = env.bodies.length * 10 + env.joints.length * 3
|
||||
|
||||
var agent = new DDPGAgent(env, {
|
||||
stateSize,
|
||||
nbActions,
|
||||
resetEpisode: true,
|
||||
desiredActionStddev: 0.4,
|
||||
initialStddev: 0.4,
|
||||
actorFirstLayerSize: 128,
|
||||
actorSecondLayerSize: 64,
|
||||
criticFirstLayerSSize: 128,
|
||||
criticFirstLayerASize: 128,
|
||||
criticSecondLayerSize: 64,
|
||||
nbEpochs: 1000
|
||||
});
|
||||
agent.train(true);
|
||||
|
||||
module.exports = {Walker, randf}
|
||||
@@ -0,0 +1,30 @@
|
||||
var config = require('./js/config')
|
||||
const b2 = require('./vendor/jsbox2d')
|
||||
const createFloor = require('./js/floor.js')
|
||||
const DDPGAgent = require('./js/ddpg/ddpg_agent')
|
||||
const {
|
||||
Walker
|
||||
} = require('./js/walker')
|
||||
|
||||
|
||||
var world = new b2.World(new b2.Vec2(0, -10))
|
||||
floor = createFloor(world, config.max_floor_tiles);
|
||||
var env = new Walker(world, floor, config)
|
||||
|
||||
const nbActions = env.joints.length + 4
|
||||
const stateSize = env.bodies.length * 10 + env.joints.length * 3
|
||||
|
||||
var agent = new DDPGAgent(env, {
|
||||
stateSize,
|
||||
nbActions,
|
||||
resetEpisode: true,
|
||||
desiredActionStddev: 0.4,
|
||||
initialStddev: 0.4,
|
||||
actorFirstLayerSize: 128,
|
||||
actorSecondLayerSize: 64,
|
||||
criticFirstLayerSSize: 128,
|
||||
criticFirstLayerASize: 128,
|
||||
criticSecondLayerSize: 64,
|
||||
nbEpochs: 1000
|
||||
});
|
||||
agent.train(true);
|
||||
@@ -0,0 +1,9 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './js/index.js',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'bundle.js'
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user