Motor sync support in simulator (#159)
* parse sync motor command * better sim support * sync support * fixing tank
This commit is contained in:
parent
1bc93013e6
commit
c35dbdd38f
@ -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.",
|
||||
|
@ -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",
|
||||
|
@ -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
4683
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user