UNPKG

ensilico

Version:

Synthetic data generation, simulated vehicles

153 lines (129 loc) 5.8 kB
<html> <head> <meta name="viewport" content="width=device-width, user-scalable=no"> <style> .unselectable { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } </style> <script src="ensilico.js"></script> <script> function Cast() { this.bot = new Bot(); this.rod = new Flexor(); this.rod.alignTo(this.bot.angle); this.lure = new Particle(); this.lure.position .load(this.rod.tipPosition) .add({x: 4, y: 0}); this.line = new Filament(this.rod.tipPosition, this.lure.position); // A value of 0 will "pin" the lure in place this.lureWarp = 1; // A value of 0 will detach and freeze the line this.lineCoupler = 1; // Use closure to avoid object allocation in inner loop var reusage = { headForce: new Pair(), tailForce: new Pair(), targetPosition: new Pair(), targetVelocity: new Pair() }; this.reusage = function() { return reusage; }; } Cast.geosphere = (function() { var waterlineY = -2; var densityWaterToAir = 784; return { gravity: new Pair().load({ x: 0, y: -9.81 }), surfaceHeight: function() { return waterlineY; }, density: function(position) { return position.y > waterlineY ? 1 : densityWaterToAir; } }; })(); Cast.prototype.preferences = { visualScale: 32, stepsize: 0.00025 }; Cast.prototype.update = function(controls) { var stepsize = controls.stepsize; var reusage = this.reusage(); var headForce = reusage.headForce; var tailForce = reusage.tailForce; var targetPosition = reusage.targetPosition; var targetVelocity = reusage.targetVelocity; this.line.update( stepsize * this.lineCoupler, Cast.geosphere, this.rod.tipPosition, this.rod.tipVelocity, this.lure.position, this.lure.velocity); this.line.storeTailForce(Cast.geosphere, tailForce); this.lure.update( stepsize * this.lineCoupler * this.lureWarp, Cast.geosphere, tailForce); this.bot.update(stepsize, controls.pointer.velocity.y); this.line.storeHeadForce(Cast.geosphere, headForce); headForce.multiplyBy(this.lineCoupler); targetPosition.loadPolar(this.rod.radius(), this.bot.angle); targetVelocity.loadCrossProduct(this.bot.rate, targetPosition); this.rod.update(stepsize, Cast.geosphere, headForce, targetPosition, targetVelocity); }; Cast.prototype.visualize = function(context, elapsedTime) { context.save(); context.translate(3, -3); var waterlineY = Cast.geosphere.surfaceHeight(); context.moveTo(-12, waterlineY); context.lineTo(6, waterlineY); // Rod flex curve var r = -this.rod.pivotOffset; var x = Math.cos(this.bot.angle); var y = Math.sin(this.bot.angle); context.moveTo(r * x, r * y); r = 0.75 * this.rod.radius(); context.quadraticCurveTo(r * x, r * y, this.rod.tipPosition.x, this.rod.tipPosition.y); if (this.lineCoupler) { this.line.visualize(context, elapsedTime); } context.restore(); }; function Bot() { // Default values this.minAngle = 0; this.maxAngle = Scalar.toRadians(90); this.gain = 0.01; this.responsiveness = 5; this.angle = this.minAngle; this.rate = 0; } Bot.prototype.update = function(stepsize, pointerVelocity) { var target = this.gain * pointerVelocity; this.rate = Scalar.lag(this.rate, target, this.responsiveness, stepsize); this.angle = Math.min( Math.max(this.minAngle, Scalar.integrate(this.angle, this.rate, stepsize)), this.maxAngle); }; var theSim; // for debug var tmpDst; // for debug </script> </head> <body onload="Executive.start('cast', new Cast(), 'cast.json')" class="unselectable"> <canvas id="cast" width="800" height="600"> Opps. </canvas> <button onclick="Executive.breakFrame('cast', function(sim){theSim=sim;})">Break</button> <button onclick="Platform.load(new Cast(), 'cast.json', function(msg){console.log(msg);}, function(dst){tmpDst=dst;debugger;})">Check</button> </body> </html>