Motor sync support in simulator (#159)

* parse sync motor command

* better sim support

* sync support

* fixing tank
This commit is contained in:
Peli de Halleux 2018-01-02 16:20:00 -08:00 committed by GitHub
parent 1bc93013e6
commit c35dbdd38f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 4758 additions and 19 deletions

View File

@ -77,7 +77,7 @@
"motors.MotorBase.stop": "Stops the motor(s).",
"motors.SynchedMotorPair.steer": "Turns the motor and the follower motor by a number of rotations",
"motors.SynchedMotorPair.steer|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
"motors.SynchedMotorPair.steer|param|steering": "the ratio of power sent to the follower motor, from ``-100`` to ``100``",
"motors.SynchedMotorPair.steer|param|turnRatio": "the ratio of power sent to the follower motor, from ``-200`` to ``200``, eg: 100",
"motors.SynchedMotorPair.steer|param|unit": "the meaning of the value",
"motors.SynchedMotorPair.steer|param|value": "the move quantity, eg: 2",
"motors.SynchedMotorPair.tank": "The Move Tank block can make a robot drive forward, backward, turn, or stop. \nUse the Move Tank block for robot vehicles that have two Large Motors, \nwith one motor driving the left side of the vehicle and the other the right side. \nYou can make the two motors go at different speeds or in different directions \nto make your robot turn.",

View File

@ -54,7 +54,7 @@
"motors.MotorBase.setBrake|block": "set %motor|brake %brake",
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed",
"motors.MotorBase.setSpeed|block": "set speed of %motor|to %speed|%",
"motors.SynchedMotorPair.steer|block": "steer %chassis|%steering|%|at speed %speed|%|by %value|%unit",
"motors.SynchedMotorPair.steer|block": "steer %chassis|%turnRatio|%|at speed %speed|%|by %value|%unit",
"motors.SynchedMotorPair.tank|block": "tank %chassis|left %speedLeft|%|right %speedRight|%|by %value|%unit",
"motors.largeAB|block": "large A+B",
"motors.largeAD|block": "large A+D",

View File

@ -14,7 +14,7 @@ enum Output {
//% block="C+D"
CD = Output.C | Output.D,
//% block="A+D"
AD = Output.B | Output.C,
AD = Output.A | Output.D,
//% block="All"
ALL = 0x0f
}
@ -439,17 +439,17 @@ namespace motors {
/**
* Turns the motor and the follower motor by a number of rotations
* @param turnRatio the ratio of power sent to the follower motor, from ``-200`` to ``200``, eg: 100
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
* @param value the move quantity, eg: 2
* @param unit the meaning of the value
* @param steering the ratio of power sent to the follower motor, from ``-100`` to ``100``
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
*/
//% blockId=motorPairTurn block="steer %chassis|%steering|%|at speed %speed|%|by %value|%unit"
//% blockId=motorPairTurn block="steer %chassis|%turnRatio|%|at speed %speed|%|by %value|%unit"
//% weight=9 blockGap=8
//% steering.min=-100 steering=100
//% turnRatio.min=-200 turnRatio=200
//% inlineInputMode=inline
//% group="Chassis"
steer(steering: number, speed: number, value: number, unit: MoveUnit) {
steer(turnRatio: number, speed: number, value: number, unit: MoveUnit) {
this.init();
speed = Math.clamp(-100, 100, speed >> 0);
if (!speed) {
@ -457,7 +457,7 @@ namespace motors {
return;
}
const turnRatio = Math.clamp(-200, 200, steering + 100 >> 0);
turnRatio = Math.clamp(-200, 200, turnRatio >> 0);
let useSteps: boolean;
let stepsOrTime: number;
switch (unit) {
@ -470,7 +470,7 @@ namespace motors {
useSteps = true;
break;
default:
stepsOrTime = value;
stepsOrTime = value >> 0;
useSteps = false;
break;
}
@ -502,10 +502,10 @@ namespace motors {
//% inlineInputMode=inline
//% group="Chassis"
tank(speedLeft: number, speedRight: number, value: number, unit: MoveUnit) {
speedLeft = Math.clamp(speedLeft >> 0, -100, 100);
speedRight = Math.clamp(speedRight >> 0, -100, 100);
const steering = (speedRight * 100 / speedLeft) >> 0;
this.steer(speedLeft, steering, value, unit);
speedLeft = Math.clamp(-100, 100, speedLeft >> 0);
speedRight = Math.clamp(-100, 100, speedRight >> 0);
const turnRatio = speedLeft == 0 ? 0 : speedRight / speedLeft * 100;
this.steer(turnRatio, speedLeft, value, unit);
}
/**

4683
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ namespace pxsim {
private speedCmdValues: number[];
private speedCmdTacho: number;
private speedCmdTime: number;
private _synchedMotor: MotorNode; // non-null if master motor
constructor(port: number, large: boolean) {
super(port);
@ -22,22 +23,34 @@ namespace pxsim {
}
getSpeed() {
return this.speed * (this.polarity == 0 ? -1 : 1);
return this.speed * (this.polarity == 0 ? -1 : 1);
}
getAngle() {
return this.angle;
}
// returns the slave motor if any
getSynchedMotor() {
return this._synchedMotor;
}
setSpeedCmd(cmd: DAL, values: number[]) {
this.speedCmd = cmd;
this.speedCmdValues = values;
this.speedCmdTacho = this.angle;
this.speedCmdTime = pxsim.U.now();
delete this._synchedMotor;
}
setSyncCmd(motor: MotorNode, cmd: DAL, values: number[]) {
this.setSpeedCmd(cmd, values);
this._synchedMotor = motor;
}
clearSpeedCmd() {
delete this.speedCmd;
delete this._synchedMotor;
}
setLarge(large: boolean) {
@ -77,7 +90,7 @@ namespace pxsim {
console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`)
const interval = Math.min(20, elapsed);
let t = 0;
while(t < elapsed) {
while (t < elapsed) {
let dt = interval;
if (t + dt > elapsed) dt = elapsed - t;
this.updateStateStep(dt);
@ -97,14 +110,14 @@ namespace pxsim {
case DAL.opOutputTimeSpeed:
case DAL.opOutputTimePower:
case DAL.opOutputStepPower:
case DAL.opOutputStepSpeed:
case DAL.opOutputStepSpeed: {
// ramp up, run, ramp down, <brake> using time
const speed = this.speedCmdValues[0];
const step1 = this.speedCmdValues[1];
const step2 = this.speedCmdValues[2];
const step3 = this.speedCmdValues[3];
const brake = this.speedCmdValues[4];
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
if (dstep < step1) // rampup
@ -117,9 +130,33 @@ namespace pxsim {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
this.speed = Math.round(this.speed); // integer only
break;
}
case DAL.opOutputStepSync:
case DAL.opOutputTimeSync: {
if (!this._synchedMotor) // handled in other motor code
break;
const otherMotor = this._synchedMotor;
const speed = this.speedCmdValues[0];
const turnRatio = this.speedCmdValues[1];
const stepsOrTime = this.speedCmdValues[2];
const brake = this.speedCmdValues[3];
const dstep = this.speedCmd == DAL.opOutputTimeSync
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
if (dstep < stepsOrTime)
this.speed = speed;
else {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
// send synched motor state
otherMotor.speed = Math.floor(this.speed * turnRatio / 100);
break;
}
}
this.speed = Math.round(this.speed); // integer only
// compute delta angle
const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed;

View File

@ -56,6 +56,25 @@ namespace pxsim {
motors.forEach(motor => motor.setSpeedCmd(cmd, [speed, step1, step2, step3, brake]));
return 2;
}
case DAL.opOutputStepSync:
case DAL.opOutputTimeSync: {
const port = buf.data[1];
const speed = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2); // signed byte
// note that b[3] is padding
const turnRatio = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int16LE, 4);
// b[6], b[7] is padding
const stepsOrTime = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int32LE, 8);
const brake = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 12);
const motors = ev3board().getMotor(port);
for (const motor of motors) {
const otherMotor = motors.filter(m => m.port != motor.port)[0];
motor.setSyncCmd(
motor.port < otherMotor.port ? otherMotor : undefined,
cmd, [speed, turnRatio, stepsOrTime, brake]);
}
return 2;
}
case DAL.opOutputStop: {
// stop
const port = buf.data[1];