Motorworks2 (#141)

* fixing polarity

* allocate motor on motorUsed only

* perform sub-step integration step for better precision
This commit is contained in:
Peli de Halleux 2017-12-28 09:07:57 -08:00 committed by GitHub
parent a9a9a89811
commit 01f7fe633c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 19 deletions

View File

@ -115,12 +115,29 @@ namespace pxsim {
return this.brickNode; return this.brickNode;
} }
motorUsed(port:number, large: boolean) {
for(let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
const p = 1 << i;
if (port & p) {
const motorPort = this.motorMap[p];
if (!this.outputNodes[motorPort])
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
}
}
}
getMotor(port: number, large?: boolean): MotorNode[] { getMotor(port: number, large?: boolean): MotorNode[] {
if (port == 0xFF) return this.getMotors(); // Return all motors const r = [];
const motorPort = this.motorMap[port]; for(let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (!this.outputNodes[motorPort]) const p = 1 << i;
this.outputNodes[motorPort] = new MotorNode(motorPort, large); if (port & p) {
return [this.outputNodes[motorPort]]; const motorPort = this.motorMap[p];
const outputNode = this.outputNodes[motorPort];
if (outputNode)
r.push(outputNode);
}
}
return r;
} }
getMotors() { getMotors() {

View File

@ -2,8 +2,8 @@
namespace pxsim.motors { namespace pxsim.motors {
export function __motorUsed(port: number, large: boolean) { export function __motorUsed(port: number, large: boolean) {
console.log("MOTOR INIT " + port); //console.log("MOTOR INIT " + port);
const motors = ev3board().getMotor(port, large); ev3board().motorUsed(port, large);
runtime.queueDisplayUpdate(); runtime.queueDisplayUpdate();
} }
} }
@ -11,7 +11,7 @@ namespace pxsim.motors {
namespace pxsim.sensors { namespace pxsim.sensors {
export function __sensorUsed(port: number, type: number) { export function __sensorUsed(port: number, type: number) {
console.log("SENSOR INIT " + port + ", type: " + type); //console.log("SENSOR INIT " + port + ", type: " + type);
const sensor = ev3board().getSensor(port, type); const sensor = ev3board().getSensor(port, type);
runtime.queueDisplayUpdate(); runtime.queueDisplayUpdate();
} }

View File

@ -19,8 +19,8 @@ namespace pxsim {
// console.log("motor before read"); // console.log("motor before read");
for (let port = 0; port < DAL.NUM_OUTPUTS; ++port) { for (let port = 0; port < DAL.NUM_OUTPUTS; ++port) {
const output = outputs[port]; const output = outputs[port];
const speed = output ? Math.round(outputs[port].getSpeed()) : 0; const speed = output ? outputs[port].getSpeed() : 0;
const angle = output ? Math.round(outputs[port].getAngle()) : 0; const angle = output ? outputs[port].getAngle() : 0;
const tci = MotorDataOff.TachoCounts + port * MotorDataOff.Size; const tci = MotorDataOff.TachoCounts + port * MotorDataOff.Size;
const tsi = MotorDataOff.TachoSensor + port * MotorDataOff.Size; const tsi = MotorDataOff.TachoSensor + port * MotorDataOff.Size;
data[tci] = data[tci + 1] = data[tci + 2] = data[tci + 3] = 0; // Tacho count data[tci] = data[tci + 1] = data[tci + 2] = data[tci + 3] = 0; // Tacho count

View File

@ -8,8 +8,8 @@ namespace pxsim {
private angle: number = 0; private angle: number = 0;
private tacho: number = 0; private tacho: number = 0;
private speed: number = 0; private speed: number = 0;
private polarity: number = 1; // -1, 1 or -1
private polarity: boolean;
private started: boolean; private started: boolean;
private speedCmd: DAL; private speedCmd: DAL;
private speedCmdValues: number[]; private speedCmdValues: number[];
@ -22,7 +22,7 @@ namespace pxsim {
} }
getSpeed() { getSpeed() {
return this.speed; return this.speed * (this.polarity == 0 ? -1 : 1);
} }
getAngle() { getAngle() {
@ -42,12 +42,18 @@ namespace pxsim {
setLarge(large: boolean) { setLarge(large: boolean) {
this.id = large ? NodeType.LargeMotor : NodeType.MediumMotor; this.id = large ? NodeType.LargeMotor : NodeType.MediumMotor;
// large 170 rpm (https://education.lego.com/en-us/products/ev3-large-servo-motor/45502)
this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000; this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000;
} }
setPolarity(polarity: number) { setPolarity(polarity: number) {
// Either 1 or 255 (reverse) // Either 1 or 255 (reverse)
this.polarity = polarity === 255; /*
-1 : Motor will run backward
0 : Motor will run opposite direction
1 : Motor will run forward
*/
this.polarity = polarity;
} }
reset() { reset() {
@ -68,6 +74,18 @@ namespace pxsim {
} }
updateState(elapsed: number) { updateState(elapsed: number) {
console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`)
const interval = Math.min(20, elapsed);
let t = 0;
while(t < elapsed) {
let dt = interval;
if (t + dt > elapsed) dt = elapsed - t;
this.updateStateStep(dt);
t += dt;
}
}
private updateStateStep(elapsed: number) {
// compute new speed // compute new speed
switch (this.speedCmd) { switch (this.speedCmd) {
case DAL.opOutputSpeed: case DAL.opOutputSpeed:
@ -99,12 +117,13 @@ namespace pxsim {
if (brake) this.speed = 0; if (brake) this.speed = 0;
this.clearSpeedCmd(); this.clearSpeedCmd();
} }
this.speed = Math.round(this.speed); // integer only
break; break;
} }
// compute delta angle // compute delta angle
const rotations = this.speed / 100 * this.rotationsPerMilliSecond * elapsed; const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed;
const deltaAngle = rotations * 360; const deltaAngle = Math.round(rotations * 360);
if (deltaAngle) { if (deltaAngle) {
this.angle += deltaAngle; this.angle += deltaAngle;
this.tacho += Math.abs(deltaAngle); this.tacho += Math.abs(deltaAngle);
@ -113,9 +132,9 @@ namespace pxsim {
// if the motor was stopped or there are no speed commands, // if the motor was stopped or there are no speed commands,
// let it coast to speed 0 // let it coast to speed 0
if (this.speed && (!this.started || !this.speedCmd)) { if (this.speed && !(this.started || this.speedCmd)) {
// decay speed 5% per tick // decay speed 5% per tick
this.speed = Math.max(0, Math.abs(this.speed) - 5) * Math.sign(this.speed); this.speed = Math.round(Math.max(0, Math.abs(this.speed) - 10) * Math.sign(this.speed));
} }
} }
} }

View File

@ -358,14 +358,14 @@ namespace pxsim.visuals {
if (!this.running) return; if (!this.running) return;
const fps = GAME_LOOP_FPS; const fps = GAME_LOOP_FPS;
let now; let now;
let then = Date.now(); let then = pxsim.U.now();
let interval = 1000 / fps; let interval = 1000 / fps;
let delta; let delta;
let that = this; let that = this;
function loop() { function loop() {
const animationId = requestAnimationFrame(loop); const animationId = requestAnimationFrame(loop);
that.lastAnimationIds.push(animationId); that.lastAnimationIds.push(animationId);
now = Date.now(); now = pxsim.U.now();
delta = now - then; delta = now - then;
if (delta > interval) { if (delta > interval) {
then = now; then = now;