Spaces:
Running
Running
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>The AI Creature</title> | |
<!-- Babylon.js --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> | |
<script src="https://preview.babylonjs.com/ammo.js"></script> | |
<script src="https://preview.babylonjs.com/cannon.js"></script> | |
<script src="https://preview.babylonjs.com/Oimo.js"></script> | |
<script src="https://preview.babylonjs.com/earcut.min.js"></script> | |
<script src="https://preview.babylonjs.com/babylon.js"></script> | |
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> | |
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> | |
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> | |
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> | |
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> | |
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> | |
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> | |
<!-- tf.js --> | |
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script> | |
<script src="agent_sac.js"></script> | |
<style> | |
html, body { | |
overflow: hidden; | |
width: 100%; | |
height: 100%; | |
margin: 0; | |
padding: 0; | |
} | |
#renderCanvas { | |
width: 100%; | |
height: 100%; | |
touch-action: none; | |
} | |
#testCanvas0 { | |
position:absolute; | |
width: 128px; | |
height: 128px; | |
right:600px; | |
bottom: 0; | |
} | |
#testCanvas1 { | |
position:absolute; | |
width: 128px; | |
height: 128px; | |
right:450px; | |
bottom: 0; | |
} | |
#testCanvas2 { | |
position:absolute; | |
width: 128px; | |
height: 128px; | |
right: 300px; | |
bottom: 0; | |
} | |
#testCanvas3 { | |
position: absolute; | |
width: 128px; | |
height: 128px; | |
right: 150px; | |
bottom: 0; | |
} | |
#testCanvas4 { | |
position: absolute; | |
width: 128px; | |
height: 128px; | |
right: 0px; | |
bottom: 0; | |
} | |
/* #votes { | |
position: absolute; | |
border: 1px solid black; | |
bottom: 200px; | |
right: 0px; | |
width: 100px; | |
height: 150px; | |
} */ | |
.vote { | |
position: absolute; | |
display:none; | |
width: 60px; | |
height: 60px; | |
right: 10px; | |
} | |
.vote:hover { | |
cursor: pointer; | |
} | |
#like { | |
bottom: 200px; | |
} | |
#dislike { | |
bottom: 120px; | |
-webkit-transform: scaleX(-1); | |
transform: scaleX(-1); | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="renderCanvas"></canvas> | |
<canvas id="testCanvas0"></canvas> | |
<canvas id="testCanvas1"></canvas> | |
<canvas id="testCanvas2"></canvas> | |
<canvas id="testCanvas3"></canvas> | |
<canvas id="testCanvas4"></canvas> | |
<!-- <div id="votes"> --> | |
<div class="vote" id="like"> | |
<img src="data:image/png;base64,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" alt="like"> | |
</div> | |
<div class="vote" id="dislike"> | |
<img src="data:image/png;base64,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" alt=""> | |
</div> | |
<!-- </div> --> | |
<script> | |
window.engine = null; | |
window.scene = null; | |
window.sceneToRender = null; | |
const agent = new AgentSac({trainable: false, verbose: false}) | |
const canvas = document.getElementById("renderCanvas"); | |
const createDefaultEngine = () => new BABYLON.Engine(canvas, true, { | |
preserveDrawingBuffer: true, | |
stencil: true, | |
disableWebGL2Support: false | |
}) | |
window.vote = 0 | |
document.getElementById("like").addEventListener("click", () => { | |
// if (!transitions.length) return | |
window.reward = 1 | |
// transitions[transitions.length - 1].reward += reward | |
// globalReward += reward | |
// console.log('reward like: ', transitions[transitions.length - 1].reward, globalReward) | |
}) | |
document.getElementById("dislike").addEventListener("click", () => { | |
// if (!transitions.length) return | |
window.reward = -1 | |
// transitions[transitions.length - 1].reward += reward | |
// globalReward += reward | |
// console.log('reward dislike: ', transitions[transitions.length - 1].reward, globalReward) | |
}) | |
window.transitions = [] | |
window.globalReward = 0 | |
const BINOCULAR = true | |
const createScene = async () => { | |
await agent.init() | |
// This creates a basic Babylon Scene object (non-mesh) | |
const scene = new BABYLON.Scene(engine); | |
scene.collisionsEnabled = true | |
// Environment | |
const hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("3d/env/environment.dds", scene); | |
hdrTexture.name = "envTex"; | |
hdrTexture.gammaSpace = false; | |
scene.environmentTexture = hdrTexture; | |
const skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:1000.0}, scene); | |
const skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene); | |
skyboxMaterial.backFaceCulling = false; | |
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("3d/env/skybox", scene); | |
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE; | |
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0); | |
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0); | |
skybox.material = skyboxMaterial; | |
//CAMERA | |
const camera = new BABYLON.ArcRotateCamera("Camera", BABYLON.Tools.ToRadians(-120), BABYLON.Tools.ToRadians(80), 65, new BABYLON.Vector3(0, -15, 0), scene); | |
camera.attachControl(canvas, true); | |
camera.lowerRadiusLimit = 10; | |
camera.upperRadiusLimit = 120; | |
camera.collisionRadius = new BABYLON.Vector3(2, 2, 2); | |
camera.checkCollisions = true; | |
//enable Physics in the scene vector = gravity | |
scene.enablePhysics(new BABYLON.Vector3(0, 0, 0), new BABYLON.AmmoJSPlugin(false)); | |
const physicsEngine = scene.getPhysicsEngine() | |
// physicsEngine.setSubTimeStep(physicsEngine.getTimeStep()/3 * 1000) | |
physicsEngine.setTimeStep(1 / 60) | |
physicsEngine.setSubTimeStep(1) | |
//LIGHTS | |
const light1 = new BABYLON.PointLight("light1", new BABYLON.Vector3(0, 5,-6), scene); | |
const light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(6, 5, 3.5), scene); | |
const light3 = new BABYLON.DirectionalLight("light3", new BABYLON.Vector3(20, -5, 20), scene); | |
light1.intensity = 15; | |
light2.intensity = 5; | |
engine.displayLoadingUI(); | |
await Promise.all([ | |
BABYLON.SceneLoader.AppendAsync("3d/marbleTower.glb"), | |
BABYLON.SceneLoader.AppendAsync("https://models.babylonjs.com/Marble/marble/marble.gltf") | |
]) | |
scene.getMeshByName("marble").isVisible = false | |
const tower = scene.getMeshByName("tower"); | |
tower.setParent(null) | |
tower.checkCollisions = true; | |
tower.impostor = new BABYLON.PhysicsImpostor(tower, BABYLON.PhysicsImpostor.MeshImpostor, { | |
mass: 0, | |
friction: 1 | |
}, scene); | |
tower.material = scene.getMaterialByName("stone") | |
tower.material.backFaceCulling = false | |
/* CREATURE */ | |
const creature = BABYLON.MeshBuilder.CreateSphere("creature", {diameter: 1, segments:32}, scene) | |
creature.parent = null | |
creature.setParent(null) | |
creature.position = new BABYLON.Vector3(0,-5,0) | |
creature.isPickable = false | |
const crMat = new BABYLON.StandardMaterial("cr_mat", scene); | |
crMat.alpha = 0 // for screenshots | |
creature.material = crMat | |
creature.impostor = new BABYLON.PhysicsImpostor(creature, BABYLON.PhysicsImpostor.SphereImpostor, { | |
mass: 1, | |
friction: 0, | |
stiffness: 0, | |
restitution: 0 | |
}, scene) | |
BABYLON.ParticleHelper.SnippetUrl = "3d/snippet"; | |
// Sparks | |
creature.sparks = await BABYLON.ParticleHelper.CreateFromSnippetAsync("UY098C-3.json", scene, false); | |
creature.sparks.emitter = creature; | |
// Core | |
creature.glow = await BABYLON.ParticleHelper.CreateFromSnippetAsync("EXUQ7M-5.json", scene, false); | |
creature.glow.emitter = creature; | |
/* CREATURE's CAMERA */ | |
const crCameraLeft = new BABYLON.UniversalCamera("cr_camera_l", new BABYLON.Vector3(0, 0, 0), scene) | |
crCameraLeft.parent = creature | |
crCameraLeft.position = new BABYLON.Vector3(-0.5, 0, 0)//new BABYLON.Vector3(0, 5, -10) | |
crCameraLeft.fov = 2 | |
crCameraLeft.setTarget(new BABYLON.Vector3(-1, 0, 0.6)) | |
const crCameraRight = new BABYLON.UniversalCamera("cr_camera_r", new BABYLON.Vector3(0, 0, 0), scene) | |
crCameraRight.parent = creature | |
crCameraRight.position = new BABYLON.Vector3(0.5, 0, 0)//new BABYLON.Vector3(0, 5, -10) | |
crCameraRight.fov = 2 | |
crCameraRight.setTarget(new BABYLON.Vector3(1, 0, 0.6)) | |
const crCameraLeftPl = BABYLON.MeshBuilder.CreateSphere("crCameraLeftPl", {diameter: 0.1, segments: 32}, scene); | |
crCameraLeftPl.parent = creature | |
crCameraLeftPl.position = new BABYLON.Vector3(-0.5, 0, 0) | |
const crCameraLeftPlclMat = new BABYLON.StandardMaterial("crCameraLeftPlclMat", scene) | |
crCameraLeftPlclMat.alpha = 0.3 // for screenshots | |
crCameraLeftPlclMat.diffuseColor = new BABYLON.Color3(0, 0, 0) | |
crCameraLeftPl.material = crCameraLeftPlclMat | |
const crCameraRightPl = BABYLON.MeshBuilder.CreateSphere("crCameraRightPl", {diameter: 0.1, segments: 32}, scene); | |
crCameraRightPl.parent = creature | |
crCameraRightPl.position = new BABYLON.Vector3(0.5, 0, 0) | |
const crCameraRightPlclMat = new BABYLON.StandardMaterial("crCameraRightPlclMat", scene) | |
crCameraRightPlclMat.alpha = 0.3 // for screenshots | |
crCameraRightPlclMat.diffuseColor = new BABYLON.Color3(0, 0, 0) | |
crCameraRightPl.material = crCameraRightPlclMat | |
// crCameraLeft.rotation = new BABYLON.Vector3(0, -(Math.PI - 0.3), 0) | |
// crCameraLeft.fovMode = BABYLON.Camera.PERSPECTIVE_CAMERA; | |
// crCameraRight.rotation = new BABYLON.Vector3(0, +(Math.PI - 0.3), 0) | |
// crCameraRight.fovMode = BABYLON.Camera.FOVMODE_HORIZONTAL_FIXED; | |
// crCameraRight.checkCollisions = true; | |
// crCamera.rotation = (new BABYLON.Vector3(0.5, 0, 0)) | |
// crCamera.ellipsoid = new BABYLON.Vector3(1, 1, 1); | |
// crCamera.ellipsoidOffset = new BABYLON.Vector3(3, 3, 3); | |
// creature.checkCollisions = true; | |
// scene.collisionsEnabled = true; | |
// crCamera.applyGravity = true; | |
// crCamera.fovMode = BABYLON.Camera.PERSPECTIVE_CAMERA; | |
// crCamera.fovMode = BABYLON.Camera.FOVMODE_HORIZONTAL_FIXED; | |
// crCamera.inertia = 2 | |
// crCamera.setTarget(new BABYLON.Vector3(2, 0, 0)) | |
// const crCameraMesh = BABYLON.MeshBuilder.CreateSphere("cr_camera_mesh", {diameter: 1, segments: 32}, scene); | |
// crCameraMesh.parent = crCamera | |
// crCameraMesh.isVisible = 1 | |
/* CLIENT */ | |
const client = BABYLON.MeshBuilder.CreateSphere("client", {diameter: 3, segments: 32}, scene); | |
client.parent = camera | |
client.setParent(camera) | |
// client.position = new BABYLON.Vector3(0, -12,0) | |
const clMat = new BABYLON.StandardMaterial("cl_mat", scene) | |
clMat.diffuseColor = new BABYLON.Color3(0, 0, 0) | |
client.material = clMat | |
engine.hideLoadingUI(); | |
/* CAGE */ | |
const cage = BABYLON.MeshBuilder.CreateSphere("cage", { | |
segements: 64, | |
diameter: 50 | |
}, scene) | |
// const cage = BABYLON.MeshBuilder.CreateBox("cage", { | |
// width: 100, | |
// depth: 100, | |
// height: 40 | |
// }, scene) | |
cage.parent = null | |
cage.setParent(null) | |
cage.position = new BABYLON.Vector3(0, -12,0) | |
cage.isPickable = true | |
const cageMat = new BABYLON.StandardMaterial("cage_mat", scene); | |
cageMat.alpha = 0.1 // for ray hit | |
cage.material = cageMat | |
cage.material.backFaceCulling = false | |
cage.impostor = new BABYLON.PhysicsImpostor(cage, BABYLON.PhysicsImpostor.MeshImpostor, { | |
mass: 0, | |
friction: 1 | |
}, scene); | |
/* MIRROR */ | |
/* const mirror = BABYLON.MeshBuilder.CreateBox("mirror", { | |
width: 10, | |
depth: 0.1, | |
height: 5 | |
}, scene) | |
mirror.material = new BABYLON.StandardMaterial("mirror_mat", scene) | |
mirror.position = new BABYLON.Vector3(20, 0, 0) | |
// mirror.addRotation(0, Math.PI/2, 0) | |
mirror.isVisible = true | |
// How to use: mirror.material.diffuseTexture = new BABYLON.Texture(base64Data, scene) // timer ~1ms | |
*/ | |
// const [ballRed, ballGreen, ballBlue, ballPurple, ballYellow] = ['red', 'green', 'blue', 'purple', 'yellow'].map(color => { | |
const ballPos = [[-10,-10,10], [10,-10,-10], [-10,-10,-10], [10,-10,10]] | |
// const balls = ['red', 'green', 'blue', 'purple'].map((color, i) => { | |
const balls = ['green', 'green', 'red', 'red'].map((color, i) => { | |
const ball = BABYLON.MeshBuilder.CreateSphere("ball_"+ color + i, {diameter: 7, segments: 64}, scene) | |
ball.position = new BABYLON.Vector3(...ballPos[i]) | |
ball.parent = null | |
ball.setParent(null) | |
ball.isPickable = true | |
ball.impostor = new BABYLON.PhysicsImpostor(ball, BABYLON.PhysicsImpostor.SphereImpostor, { | |
mass: 7, | |
friction: 1, | |
stiffness: 1, | |
restitution: 1 | |
}, scene); | |
ball.material = scene.getMaterialByName(color + "Mat") | |
ball.checkCollisions = true | |
ball.material.backFaceCulling = false | |
return ball | |
}) | |
// balls[0].position = new BABYLON.Vector3(10, 0, 0) | |
/* SHuffle */ | |
// scene.onPointerDown = function(evt, pickInfo) { | |
// if(pickInfo.hit && pickInfo.pickedMesh.id.startsWith('cage')) { | |
// const getRand = () => new BABYLON.Vector3(Math.random()/10 - 0.1, Math.random()/10 - 0.1, Math.random()/10 - 0.1) | |
// balls.forEach(ball => ball.impostor.applyImpulse(getRand(), BABYLON.Vector3.Zero())) | |
// } | |
// } | |
// setInterval(()=>{ | |
// const getRand = () => new BABYLON.Vector3(Math.random()/10 - 0.1, Math.random()/10 - 0.1, Math.random()/10 - 0.1) | |
// balls.forEach(ball => ball.impostor.applyImpulse(getRand(), BABYLON.Vector3.Zero())) | |
// }, 1000) | |
// ballRed.impostor.applyImpulse(new BABYLON.Vector3(0, -20, 0), BABYLON.Vector3.Zero()) | |
// ballGr.impostor.applyImpulse(new BABYLON.Vector3(0, -20, 0), BABYLON.Vector3.Zero()) | |
/* WORKER */ | |
const worker = new Worker('worker.js') | |
let inited = false | |
worker.addEventListener('message', e => { | |
const { weights, frame } = e.data | |
tf.tidy(() => { | |
if (weights) { | |
inited = true | |
agent.actor.setWeights(weights.map(w => tf.tensor(w))) // timer ~30ms | |
if (Math.random() > 0.99) console.log('weights:', weights) | |
} | |
}) | |
}) | |
/* COLLISIONS DETECTION */ | |
const impostors = scene.getPhysicsEngine()._impostors.filter(im => im.object.id !== creature.id) | |
creature.impostor.registerOnPhysicsCollide(impostors, (body1, body2) => {}) | |
impostors.forEach(impostor => { | |
impostor.onCollide = e => { | |
if (window.onCollide) { | |
const collision = e.point.subtract(creature.position).normalize() | |
window.onCollide(collision, impostor.object.id) | |
} | |
} | |
}) | |
// ;(() => { | |
// let coll | |
// creature.impostor.onCollide = e => { | |
// coll = e.point.subtract(creature.position).normalize() | |
// console.log('crea', coll) | |
// if (window.onCollide) | |
// window.onCollide(coll) | |
// } | |
// balls.forEach(ball => { | |
// ball.impostor.onCollide = e => { | |
// const collision = e.point.subtract(creature.position).normalize() | |
// console.log('crea ball', coll, collision) | |
// if (window.onCollide) | |
// window.onCollide(collision, ball.id) | |
// // if (ball.id.endsWith('_red')) | |
// console.log('onCollide mesh:', ball.id) | |
// } | |
// }) | |
// })() | |
const base64ToImg = (base64) => new Promise((res, _) => { | |
const img = new Image() | |
img.src = base64 | |
img.onload = () => res(img) | |
}) | |
const TRANSITIONS_BUFFER_SIZE = 2 | |
const frameEvery = 1000/30 // ~33ms ~24frames/sec | |
const frameStack = [] | |
// const transitions = [] | |
// let start = Date.now() + frameEvery | |
let timer = Date.now() | |
let busy = false | |
let stateId = 0 | |
let prevLinearVelocity = BABYLON.Vector3.Zero() | |
window.collision = BABYLON.Vector3.Zero() | |
window.reward = 0 | |
window.globalReward = 0 | |
// let collisionMesh = null | |
const testLayer = agent.actor.layers[4] | |
const spy = tf.model({inputs: agent.actor.inputs, outputs: testLayer.output}) | |
scene.registerAfterRender(async () => { // timer ~ 20-90ms | |
if (/*Date.now() < start || */busy || !inited) return | |
// const delta = (Date.now() - timestamp) / 1000 // sec | |
// timestamp = Date.now() | |
// start = Date.now() + frameEvery | |
busy = true | |
// const timerLbl = 'TimerLabel-' + start | |
/* | |
console.time(timerLbl) | |
console.timeEnd(timerLbl) | |
console.log('numTensors BEFORE: ' + tf.memory().numTensors) | |
console.log('numTensors AFTER: ' + tf.memory().numTensors) | |
*/ | |
// const screenShots = [] | |
// screenShots.push( | |
// BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync(engine, crCameraLeft, { // ~ 7-60ms | |
// height: agent._frameShape[0], | |
// width: agent._frameShape[1] | |
// }) | |
// ) | |
// screenShots.push( | |
// BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync(engine, crCameraRight, { // ~ 7-60ms | |
// height: agent._frameShape[0], | |
// width: agent._frameShape[1] | |
// }) | |
// ) | |
// const base64Data = await Promise.all(screenShots) | |
// frameStack.push(base64Data) | |
//delay | |
if (!frameStack.length) { | |
frameStack.push([ | |
await BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync(engine, crCameraLeft, { // ~ 7-60ms | |
height: agent._frameShape[0], | |
width: agent._frameShape[1] | |
}) | |
]) | |
} else { | |
frameStack[0].push( | |
await BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync(engine, crCameraRight, { // ~ 7-60ms | |
height: agent._frameShape[0], | |
width: agent._frameShape[1] | |
}) | |
) | |
} | |
if (frameStack.length >= agent._nFrames && frameStack[0].length == 2) { // ~20ms | |
if (frameStack.length > agent._nFrames) | |
throw new Error("(⊙_⊙')") | |
const imgs = await Promise.all(frameStack.flat().map(fr => base64ToImg(fr))) | |
const framesNorm = tf.tidy(() => { | |
const greyScaler = tf.tensor([0.299, 0.587, 0.114], [1, 1, 3]) | |
let imgTensors = imgs.map(img => tf.browser.fromPixels(img) | |
//.mul(greyScaler).sum(-1, true) | |
) | |
// optic chiasma | |
// imgTensors = imgTensors.map(img => tf.split(img, 2, 1)) | |
// for (let i = 0; i < imgTensors.length; i = i + 2) { | |
// const first = tf.concat([imgTensors[i][0], imgTensors[i+1][0]], -1) | |
// const second = tf.concat([imgTensors[i][1], imgTensors[i+1][1]], -1) | |
// imgTensors[i] = first | |
// imgTensors[i+1] = second | |
// } | |
// imgTensors = [ | |
// imgTensors[0].concat(imgTensors[1], 1), | |
// //imgTensors[2].concat(imgTensors[3], 1) | |
// ] | |
// if (collisionMesh) { | |
imgTensors = imgTensors.map((t, i) => { | |
const canv = document.getElementById('testCanvas' + (i+3)) | |
if (canv) { | |
tf.browser.toPixels(t, canv) // timer ~1ms | |
} | |
return t | |
.sub(255/2) | |
.div(255/2) | |
}) | |
// } | |
const resL = tf.concat(imgTensors.filter((el, i) => i%2==0), -1) | |
const resR = tf.concat(imgTensors.filter((el, i) => i%2==1), -1) | |
return [resL, resR] | |
// return [tf.concat(imgTensors, -1)] | |
// let frTest = tf.unstack(res, -1) | |
// // frTest = [tf.concat(frTest.slice(0,3), -1), tf.concat(frTest.slice(3), -1)] | |
// console.log(frTest[0].arraySync()[30][0][0], frTest[3].arraySync()[30][0][0]) | |
// console.log(tf.concat(tf.unstack(tf.concat(imgTensors, 2), -1), -1).arraySync()[30][0][0]) | |
}) | |
const framesBatch = framesNorm.map(fr => tf.stack([fr])) | |
const delta = (Date.now() - timer) / 1000 // sec | |
console.log('delta (s)', delta) | |
const linearVelocity = creature.impostor.getLinearVelocity() | |
const linearVelocityNorm = linearVelocity.normalize() | |
const acceleration = linearVelocity.subtract(prevLinearVelocity).scale(1/delta).normalize() | |
timer = Date.now() | |
prevLinearVelocity = linearVelocity | |
const ray = new BABYLON.Ray(creature.position, linearVelocityNorm) | |
const hit = scene.pickWithRay(ray) | |
let lidar = 0 | |
if (hit.pickedMesh) { | |
lidar = Math.tanh((hit.distance - creature.impostor.getRadius())/10) // stretch tanh by 10 for precision | |
// console.log('Hit: ', hit.pickedMesh.name, hit.distance, lidar, linearVelocity, collision) | |
} | |
const telemetry = [ | |
linearVelocityNorm.x, | |
linearVelocityNorm.y, | |
linearVelocityNorm.z, | |
acceleration.x, | |
acceleration.y, | |
acceleration.z, | |
window.collision.x, | |
window.collision.y, | |
window.collision.z, | |
lidar | |
] | |
const reward = window.reward | |
//collisionMesh && | |
// if (collisionMesh && transitions.length) { | |
// tf.tidy(() => { | |
// let frTest = tf.unstack(tf.tensor(transitions[transitions.length - 1].state[1], [64,128, agent._nFrames]), -1) | |
// // frTest = [tf.stack(frTest.slice(0,3), -1), tf.stack(frTest.slice(3), -1)] | |
// let i = 0 | |
// for (const fr of frTest) { | |
// i++ | |
// tf.browser.toPixels(fr, document.getElementById('testCanvas' + i)) // timer ~1ms | |
// } | |
// }) | |
// } | |
window.collision = BABYLON.Vector3.Zero() // reset collision point | |
window.reward = -0.01 | |
window.onCollide = undefined | |
const telemetryBatch = tf.tensor(telemetry, [1, agent._nTelemetry]) | |
const action = agent.sampleAction([telemetryBatch, ...framesBatch]) // timer ~5ms | |
// TODO: !!!!!await find the way to avoid framesNorm.array() | |
console.time('await') | |
const [framesArrL, framesArrR,[actionArr]] = await Promise.all([...(framesNorm.map(fr => fr.array())), action.array()]) // action come as a batch of size 1 | |
console.timeEnd('await') | |
// DEBUG Conv encoder | |
tf.tidy(() => { // timer ~2.5ms | |
const testOutput = spy.predict([telemetryBatch, ...framesBatch], {batchSize: 1}) | |
console.log('spy', testLayer.name, testOutput.arraySync()) | |
return | |
let tiles = tf.clipByValue(tf.squeeze(testOutput), 0, 1) | |
tiles = tf.transpose(tiles, [2,0,1]) | |
tiles = tf.unstack(tiles) | |
let res = [], line = [] | |
for (const [i, tile] of tiles.entries()) { | |
line.push(tile) | |
if ((i+1) % 8 == 0 && i) { | |
res.push(tf.concat(line, 1)) | |
line = [] | |
} | |
} | |
const testFr = tf.concat(res) | |
tf.browser.toPixels(testFr, document.getElementById('testCanvas2')) // timer ~1ms | |
}) | |
const | |
impulse = actionArr.slice(0, 3)//.map(el => el/10)//, // [0,-1, 0], // | |
// rotation = actionArr.slice(3, 7).map(el => el), | |
// color = actionArr.slice(3, 6).map(el => el)/.map(el => el) // [-1,1] => [0,2] => [0, 255] | |
// look = actionArr.slice(3, 6) | |
// console.log('tel tel: ', telemetry.map(t=> t.toFixed(3))) | |
// console.log('tel imp:', impulse.map(t=> t.toFixed(3))) | |
console.assert(actionArr.length === 3, actionArr.length) | |
console.assert(impulse.length === 3) | |
// console.assert(look.length === 3) | |
// console.assert(rotation.length === 4) | |
// console.assert(color.length === 3) | |
// [0,-1,0] | |
creature.impostor.setAngularVelocity(BABYLON.Quaternion.Zero()) // just in case, probably redundant | |
// creature.impostor.setLinearVelocity(BABYLON.Vector3.Zero()) // contact point zero | |
creature.impostor.applyImpulse(new BABYLON.Vector3(...impulse), creature.getAbsolutePosition()) // contact point zero | |
creature.impostor.setAngularVelocity(BABYLON.Quaternion.Zero()) | |
// creature.glow.color2 = new BABYLON.Color4(...color) | |
// after applyImpulse the linear velocity is recalculated right away | |
const newLinearVelocity = creature.impostor.getLinearVelocity().normalize() | |
// creature.lookAt(new BABYLON.Vector3(0, -1, 0), 0, 0, 0, BABYLON.Space.LOCAL) | |
creature.lookAt(creature.position.add(newLinearVelocity)) | |
//if (!window.rr) window.rr = | |
// creature.lookAt(creature.position.add(new BABYLON.Vector3(0,1,0))) | |
const transtion = { | |
id: stateId++, | |
state: [telemetry, framesArrL, framesArrR], // 20ms vs 50ms || size 200kb vs 1.5mb | |
action: actionArr, | |
reward | |
} | |
transitions.push(transtion) | |
window.onCollide = (collision, mesh) => { | |
window.collision = collision | |
window.reward += -0.05 | |
if (mesh.startsWith('ball_')) { | |
console.log('reward', mesh) | |
window.reward = 1 | |
if (mesh.includes('red')) | |
window.reward = -1 | |
} | |
window.onCollide = undefined | |
} | |
if (transitions.length >= TRANSITIONS_BUFFER_SIZE) { | |
if (transitions.length > TRANSITIONS_BUFFER_SIZE || TRANSITIONS_BUFFER_SIZE < 2) | |
throw new Error("(⊙_⊙')") | |
const transition = transitions.shift() | |
// if (transition.reward > 0) { | |
// transition.priority = 7 | |
// console.log('reward prio:', transition, transition.state[0]) | |
// } | |
window.globalReward += transition.reward | |
console.log('reward', transition.reward, window.globalReward) | |
worker.postMessage({action: 'newTransition', transition}) // timer ~ 6ms | |
} | |
// imgTensors.forEach(t => t.dispose()) | |
// frames.dispose() | |
framesNorm.map(fr => fr.dispose()) | |
framesBatch.map(fr => fr.dispose()) | |
telemetryBatch.dispose() | |
action.dispose() | |
// if (stateId%1 == 0) | |
// frameStack.forEach((base64Data, i) => { | |
// const img = new Image() | |
// img.onload = () => document.getElementById('testCanvas' + (i+2)) | |
// .getContext('2d') | |
// .drawImage(img, 0, 0, 256, 128) | |
// img.src = base64Data | |
// }) | |
frameStack.length = 0 // I will regret about this :D | |
} | |
//mirror.material.diffuseTexture = new BABYLON.Texture(base64Data, scene) // timer ~1ms | |
// const img = await base64ToImg(base64Data) // timer ~2-12ms | |
// const tensor = tf.browser.fromPixels(img) // timer ~ 1ms | |
// const arr = await tensor.array() // timer ~ 6-15ms | |
// worker.postMessage(arr) // timer ~ 6ms | |
// tensor.dispose() | |
busy = false | |
}) | |
return scene | |
}; | |
window.initFunction = async function() { | |
await Ammo(); | |
const asyncEngineCreation = async function() { | |
try { | |
return createDefaultEngine(); | |
} catch(e) { | |
console.log("the available createEngine function failed. Creating the default engine instead"); | |
return createDefaultEngine(); | |
} | |
} | |
window.engine = await asyncEngineCreation(); | |
if (!engine) throw 'engine should not be null.'; | |
window.scene = await createScene(); | |
}; | |
initFunction().then(() => { | |
sceneToRender = scene; | |
engine.runRenderLoop(function () { | |
if (sceneToRender && sceneToRender.activeCamera) { | |
sceneToRender.render(); | |
} | |
}); | |
}); | |
window.addEventListener("resize", function () { | |
engine.resize(); | |
}); | |
</script> | |
</body> | |
</html> | |