This commit is a combination of changes after an internal play test with the Scratch Team, as well as code cleanup.

Motors:
- motor position will now initially report 0 instead of false
- removed remaining motor position zeroing functions.
- removed startBraking().
- turnOn() and turnOnForDegrees() are now using an absolute max power as per the protocol documentation.
- the "turn for rotations"-block now accepts negative values.
-- turnOnForDegrees() accepts a direction to reflect the change above. The direction from the block is calculated against the motors current direction.
- commented EV3 tacho calculation code for motor positioning removed.
- Changed BoostMotorLabel to reflect actual motor block argument.
- startMotorPower() renamed to setMotorPower() since it doesn't start the motor.
- setMotorPower() will not start the motor.
- Max number of rotations for a motor-block is clamped to 100 rotations.
- 'Default' removed from BoostMotorLabel-enum as it wasn't used.

Sensors:
- removed remaining distance-related functions.
- color-reporters default value is now none rather than black.
- tilt-angles left and right switched to reflect the hubs orientation.
This commit is contained in:
Kevin Andersen 2019-03-04 12:38:02 -05:00
parent 669ff1abf1
commit 852ae43348

View file

@ -168,8 +168,6 @@ const BoostOutputExecution = {
COMMAND_FEEDBACK: 0x01, COMMAND_FEEDBACK: 0x01,
} }
/** /**
* Enum for Boost Motor end states * Enum for Boost Motor end states
* @readonly * @readonly
@ -192,7 +190,6 @@ const BoostMotorProfile = {
DECELERATION: 0x02 DECELERATION: 0x02
} }
/** /**
* Enum for when Boost IO's are attached/detached * Enum for when Boost IO's are attached/detached
* @readonly * @readonly
@ -290,13 +287,6 @@ class BoostMotor {
*/ */
this._position = 0; this._position = 0;
/**
* This motor's current zero position, which the relative position can be calculated against.
* @type {number}
* @private
*/
this._positionZero = 0;
/** /**
* Is this motor currently moving? * Is this motor currently moving?
* @type {boolean} * @type {boolean}
@ -334,18 +324,10 @@ class BoostMotor {
*/ */
this._pendingPromiseFunction = null; this._pendingPromiseFunction = null;
this.startBraking = this.startBraking.bind(this); //this.startBraking = this.startBraking.bind(this);
this.turnOff = this.turnOff.bind(this); this.turnOff = this.turnOff.bind(this);
} }
/**
* @return {number} - the duration of active braking after a call to startBraking(). Afterward, turn the motor off.
* @constructor
*/
static get BRAKE_TIME_MS () {
return 1000;
}
/** /**
* @return {int} - this motor's current direction: 1 for "this way" or -1 for "that way" * @return {int} - this motor's current direction: 1 for "this way" or -1 for "that way"
*/ */
@ -401,20 +383,6 @@ class BoostMotor {
this._position = value; this._position = value;
} }
/**
* @return {int} - this motor's current zero position, which the current position is relative to.
*/
get positionZero () {
return this._positionZero;
}
/**
* @param {int} value - set this motor's zero position.
*/
set positionZero (value) {
this._positionZero = value;
}
/** /**
* @return {boolean} - true if this motor is currently moving, false if this motor is off or braking. * @return {boolean} - true if this motor is currently moving, false if this motor is off or braking.
*/ */
@ -443,7 +411,6 @@ class BoostMotor {
return this._pendingPromiseFunction; return this._pendingPromiseFunction;
} }
/** /**
* Turn this motor on indefinitely. * Turn this motor on indefinitely.
*/ */
@ -454,8 +421,10 @@ class BoostMotor {
BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK,
BoostOutputSubCommand.START_SPEED, BoostOutputSubCommand.START_SPEED,
[this._power * this._direction, [this._power * this._direction,
this._power * this._direction, this._power,
BoostMotorProfile.DO_NOT_USE]); BoostMotorProfile.DO_NOT_USE]);
console.log(this._power * this._direction)
this._parent.send(BoostBLE.characteristic, cmd); this._parent.send(BoostBLE.characteristic, cmd);
@ -472,14 +441,15 @@ class BoostMotor {
milliseconds = Math.max(0, milliseconds); milliseconds = Math.max(0, milliseconds);
this.turnOn(); this.turnOn();
this._setNewTimeout(this.startBraking, milliseconds); this._setNewTimeout(this.turnOff, milliseconds);
} }
/** /**
* Turn this motor on for a specific rotation in degrees. * Turn this motor on for a specific rotation in degrees.
* @param {number} degrees - run the motor for this amount of degrees. * @param {number} degrees - run the motor for this amount of degrees.
* @param {number} direction - rotate in this direction
*/ */
turnOnForDegrees (degrees) { turnOnForDegrees (degrees, direction) {
if (this._power === 0) return; if (this._power === 0) return;
degrees = Math.max(0, degrees); degrees = Math.max(0, degrees);
@ -488,8 +458,8 @@ class BoostMotor {
BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK, BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK,
BoostOutputSubCommand.START_SPEED_FOR_DEGREES, BoostOutputSubCommand.START_SPEED_FOR_DEGREES,
[...numberToInt32Array(degrees), [...numberToInt32Array(degrees),
this._power * this._direction, // power in range 0-100 this._power * this._direction * direction, // power in range 0-100
this._power * this._direction, // max speed this._power, // max speed
BoostMotorEndState.BRAKE, BoostMotorEndState.BRAKE,
BoostMotorProfile.DO_NOT_USE] // byte for using acceleration/braking profile BoostMotorProfile.DO_NOT_USE] // byte for using acceleration/braking profile
); );
@ -498,29 +468,6 @@ class BoostMotor {
this._parent.send(BoostBLE.characteristic, cmd); this._parent.send(BoostBLE.characteristic, cmd);
} }
/**
* Start active braking on this motor. After a short time, the motor will turn off.
* // TODO: rename this to coastAfter?
* // TODO: eliminate this function by changing turnOff() to use BoostMotorEndState.BRAKE?
*/
startBraking () {
if (this._power === 0) return;
const cmd = this._parent.generateOutputCommand(
this._index,
BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK,
BoostOutputSubCommand.START_SPEED,
[BoostMotorEndState.FLOAT,
BoostMotorEndState.FLOAT,
BoostMotorProfile.DO_NOT_USE]
);
this._parent.send(BoostBLE.characteristic, cmd);
this._status = BoostOutputCommandFeedback.IDLE;
this._setNewTimeout(this.turnOff, BoostMotor.BRAKE_TIME_MS);
}
/** /**
* Turn this motor off. * Turn this motor off.
* @param {boolean} [useLimiter=true] - if true, use the rate limiter * @param {boolean} [useLimiter=true] - if true, use the rate limiter
@ -619,7 +566,7 @@ class Boost {
this._sensors = { this._sensors = {
tiltX: 0, tiltX: 0,
tiltY: 0, tiltY: 0,
color: 0, color: BoostColor.NONE,
}; };
/* /*
@ -663,14 +610,6 @@ class Boost {
return this._sensors.tiltY; return this._sensors.tiltY;
} }
/**
* @return {number} - the latest value received from the distance sensor.
*//*
get distance () {
return this._sensors.distance;
}
*/
/** /**
* @return {number} - the latest color value received from the vision sensor. * @return {number} - the latest color value received from the vision sensor.
*/ */
@ -787,8 +726,8 @@ class Boost {
this._sensors = { this._sensors = {
tiltX: 0, tiltX: 0,
tiltY: 0, tiltY: 0,
color: 0, color: BoostColor.NONE,
oldColor: 0, oldColor: BoostColor.NONE,
}; };
if (this._ble) { if (this._ble) {
@ -948,12 +887,6 @@ class Boost {
break; break;
case BoostIO.MOTOREXT: case BoostIO.MOTOREXT:
case BoostIO.MOTORINT: case BoostIO.MOTORINT:
// Taken from EV3 extension tacho motor calculation
/*let value = data[4] + (data[5] * 256) + (data[6] * 256 * 256) + (data[7] * 256 * 256 * 256);
if (value > 0x7fffffff) {
value = value - 0x100000000;
}*/
//console.log(data)
this._motors[portID]._position = int32ArrayToNumber(data.slice(4,8)) this._motors[portID]._position = int32ArrayToNumber(data.slice(4,8))
break; break;
case BoostIO.CURRENT: case BoostIO.CURRENT:
@ -1009,31 +942,31 @@ class Boost {
// Set input format for tilt or distance sensor // Set input format for tilt or distance sensor
var m = null var mode = null
switch(type) { switch(type) {
case BoostIO.MOTORINT: case BoostIO.MOTORINT:
case BoostIO.MOTOREXT: case BoostIO.MOTOREXT:
m = BoostMode.MOTOR_SENSOR mode = BoostMode.MOTOR_SENSOR
break; break;
case BoostIO.COLOR: case BoostIO.COLOR:
m = BoostMode.COLOR mode = BoostMode.COLOR
break; break;
case BoostIO.LED: case BoostIO.LED:
m = BoostMode.LED mode = BoostMode.LED
this.setLEDMode(); this.setLEDMode();
this.setLED(0x00FF00); this.setLED(0x00FF00);
break; break;
case BoostIO.TILT: case BoostIO.TILT:
m = BoostMode.TILT mode = BoostMode.TILT
break; break;
default: default:
m = BoostMode.UNKNOWN mode = BoostMode.UNKNOWN
} }
const cmd = this.generateInputCommand( const cmd = this.generateInputCommand(
portID, portID,
m, mode,
1, 1,
true true
); );
@ -1052,7 +985,7 @@ class Boost {
this._sensors.tiltX = this._sensors.tiltY = 0; this._sensors.tiltX = this._sensors.tiltY = 0;
} }
if (type === BoostIO.COLOR) { if (type === BoostIO.COLOR) {
this._sensors.color = 0; this._sensors.color = BoostColor.NONE;
} }
this._ports[portID] = 'none'; this._ports[portID] = 'none';
this._motors[portID] = null; this._motors[portID] = null;
@ -1065,11 +998,10 @@ class Boost {
* @enum {string} * @enum {string}
*/ */
const BoostMotorLabel = { const BoostMotorLabel = {
DEFAULT: 'motor', A: 'A',
A: 'motor A', B: 'B',
B: 'motor B', C: 'C',
C: 'motor C', D: 'D',
D: 'motor D',
ALL: 'all motors' ALL: 'all motors'
}; };
@ -1229,11 +1161,11 @@ class Scratch3BoostBlocks {
} }
}, },
{ {
opcode: 'startMotorPower', opcode: 'setMotorPower',
text: formatMessage({ text: formatMessage({
id: 'boost.startMotorPower', id: 'boost.setMotorPower',
default: 'set motor [MOTOR_ID] power to [POWER] %', default: 'set motor [MOTOR_ID] power to [POWER] %',
description: 'set the motor\'s power and turn it on' description: 'set the motor\'s power without turning it on'
}), }),
blockType: BlockType.COMMAND, blockType: BlockType.COMMAND,
arguments: { arguments: {
@ -1253,7 +1185,7 @@ class Scratch3BoostBlocks {
text: formatMessage({ text: formatMessage({
id: 'boost.setMotorDirection', id: 'boost.setMotorDirection',
default: 'set motor [MOTOR_ID] direction to [MOTOR_DIRECTION]', default: 'set motor [MOTOR_ID] direction to [MOTOR_DIRECTION]',
description: 'set the motor\'s turn direction' description: 'set the motor\'s turn direction without turning it on'
}), }),
blockType: BlockType.COMMAND, blockType: BlockType.COMMAND,
arguments: { arguments: {
@ -1327,15 +1259,6 @@ class Scratch3BoostBlocks {
} }
} }
}, },
/*{
opcode: 'getDistance',
text: formatMessage({
id: 'boost.getDistance',
default: 'distance',
description: 'the value returned by the distance sensor'
}),
blockType: BlockType.REPORTER
},*/
{ {
opcode: 'isTilted', opcode: 'isTilted',
text: formatMessage({ text: formatMessage({
@ -1397,27 +1320,7 @@ class Scratch3BoostBlocks {
defaultValue: 5 defaultValue: 5
} }
} }
}, },
/*{
opcode: 'whenDistance',
text: formatMessage({
id: 'boost.whenDistance',
default: 'when distance [OP] [REFERENCE]',
description: 'check for when distance is < or > than reference'
}),
blockType: BlockType.HAT,
arguments: {
OP: {
type: ArgumentType.STRING,
menu: 'OP',
defaultValue: '<'
},
REFERENCE: {
type: ArgumentType.NUMBER,
defaultValue: 50
}
}
},*/
], ],
menus: { menus: {
MOTOR_ID: [ MOTOR_ID: [
@ -1691,12 +1594,16 @@ class Scratch3BoostBlocks {
motorOnForRotation (args) { motorOnForRotation (args) {
// TODO: cast args.MOTOR_ID? // TODO: cast args.MOTOR_ID?
let degrees = Cast.toNumber(args.ROTATION) * 360; let degrees = Cast.toNumber(args.ROTATION) * 360;
degrees = MathUtil.clamp(degrees, 0, 36000); console.log(degrees)
// TODO: Clamps to 100 rotations. Does that make sense?
let sign = Math.sign(degrees)
degrees = Math.abs(MathUtil.clamp(degrees, -360000, 360000));
console.log(degrees)
return new Promise(resolve => { return new Promise(resolve => {
this._forEachMotor(args.MOTOR_ID, motorIndex => { this._forEachMotor(args.MOTOR_ID, motorIndex => {
const motor = this._peripheral.motor(motorIndex); const motor = this._peripheral.motor(motorIndex);
if (motor) { if (motor) {
motor.turnOnForDegrees(degrees); motor.turnOnForDegrees(degrees, sign);
motor._pendingPromiseFunction = resolve motor._pendingPromiseFunction = resolve
} }
}); });
@ -1748,13 +1655,13 @@ class Scratch3BoostBlocks {
} }
/** /**
* Turn specified motor(s) off. * Set the power level of the specified motor(s).
* @param {object} args - the block's arguments. * @param {object} args - the block's arguments.
* @property {MotorID} MOTOR_ID - the motor(s) to be affected. * @property {MotorID} MOTOR_ID - the motor(s) to be affected.
* @property {int} POWER - the new power level for the motor(s). * @property {int} POWER - the new power level for the motor(s).
* @return {Promise} - a Promise that resolves after some delay. * @return {Promise} - a Promise that resolves after some delay.
*/ */
startMotorPower (args) { setMotorPower (args) {
// TODO: cast args.MOTOR_ID? // TODO: cast args.MOTOR_ID?
this._forEachMotor(args.MOTOR_ID, motorIndex => { this._forEachMotor(args.MOTOR_ID, motorIndex => {
const motor = this._peripheral.motor(motorIndex); const motor = this._peripheral.motor(motorIndex);
@ -1803,7 +1710,7 @@ class Scratch3BoostBlocks {
if (motor.pendingTimeoutDelay) { if (motor.pendingTimeoutDelay) {
motor.turnOnFor(motor.pendingTimeoutStartTime + motor.pendingTimeoutDelay - Date.now()); motor.turnOnFor(motor.pendingTimeoutStartTime + motor.pendingTimeoutDelay - Date.now());
} else { } else {
motor.turnOn(); //motor.turnOn();
} }
} }
} }
@ -1814,30 +1721,7 @@ class Scratch3BoostBlocks {
resolve(); resolve();
}, BLESendInterval); }, BLESendInterval);
}); });
} }
/**
* Set the motor(s) position to 0.
* @param {object} args - the block's arguments.
* @property {MotorID} MOTOR_ID - the motor(s) to activate.
* @return {Promise} - a Promise that resolves after some delay.
*/
motorZero (args) {
// TODO: cast args.MOTOR_ID?
this._forEachMotor(args.MOTOR_ID, motorIndex => {
const motor = this._peripheral.motor(motorIndex);
if (motor) {
// TODO: Do this on the hardware, i.e. https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#encoding-of-writedirectmodedata-0x81-0x51
motor.positionZero = motor.position;
}
});
return new Promise(resolve => {
window.setTimeout(() => {
resolve();
}, BLESendInterval);
});
}
/** /**
* Set the LED's hue. * Set the LED's hue.
@ -1878,26 +1762,6 @@ class Scratch3BoostBlocks {
this.setLightHue(n); this.setLightHue(n);
} }
/**
* Compare the distance sensor's value to a reference.
* @param {object} args - the block's arguments.
* @property {string} OP - the comparison operation: '<' or '>'.
* @property {number} REFERENCE - the value to compare against.
* @return {boolean} - the result of the comparison, or false on error.
whenDistance (args) {
switch (args.OP) {
case '<':
return this._peripheral.distance < Cast.toNumber(args.REFERENCE);
case '>':
return this._peripheral.distance > Cast.toNumber(args.REFERENCE);
default:
log.warn(`Unknown comparison operator in whenDistance: ${args.OP}`);
return false;
}
}
*/
/** /**
* Test whether the tilt sensor is currently tilted. * Test whether the tilt sensor is currently tilted.
* @param {object} args - the block's arguments. * @param {object} args - the block's arguments.
@ -1918,18 +1782,11 @@ class Scratch3BoostBlocks {
return this._isColor(args.COLOR); return this._isColor(args.COLOR);
} }
/**
* @return {number} - the distance sensor's value, scaled to the [0,100] range.
getDistance () {
return this._peripheral.distance;
}*/
/** /**
* @return {number} - the vision sensor's color value. Indexed LEGO brick colors. * @return {number} - the vision sensor's color value. Indexed LEGO brick colors.
*/ */
getColor () { getColor () {
//return this._peripheral.color; // To get a string representation, lookup the key of the BoostColor-enum value
return Object.keys(BoostColor).find(key => BoostColor[key] === this._peripheral.color).toLowerCase() return Object.keys(BoostColor).find(key => BoostColor[key] === this._peripheral.color).toLowerCase()
} }
@ -1942,7 +1799,6 @@ class Scratch3BoostBlocks {
_isColor (color) { _isColor (color) {
switch(color) { switch(color) {
case BoostColorLabel.ANY: case BoostColorLabel.ANY:
//console.log(this.getColor() + " versus " + Object.keys(BoostColor).find(key => BoostColor[key]).toLowerCase())
if(Object.keys(BoostColor).find(key => BoostColor[key]).toLowerCase() != this.getColor()) { if(Object.keys(BoostColor).find(key => BoostColor[key]).toLowerCase() != this.getColor()) {
if(this.getColor() == this._peripheral.oldColor) { if(this.getColor() == this._peripheral.oldColor) {
return false return false
@ -1951,8 +1807,6 @@ class Scratch3BoostBlocks {
return true return true
} }
} }
//console.log(this.getColor() != 'none')
//return this.getColor() != 'none';
default: default:
return this.getColor() == color; return this.getColor() == color;
} }
@ -1984,7 +1838,7 @@ class Scratch3BoostBlocks {
if(portID && this._peripheral._motors[portID]) { if(portID && this._peripheral._motors[portID]) {
return MathUtil.wrapClamp(this._peripheral._motors[portID].position,0,360); return MathUtil.wrapClamp(this._peripheral._motors[portID].position,0,360);
} }
return false; return 0;
} }
/** /**
@ -2036,9 +1890,9 @@ class Scratch3BoostBlocks {
case BoostTiltDirection.DOWN: case BoostTiltDirection.DOWN:
return this._peripheral.tiltY > 90 ? this._peripheral.tiltY - 256 : this._peripheral.tiltY; return this._peripheral.tiltY > 90 ? this._peripheral.tiltY - 256 : this._peripheral.tiltY;
case BoostTiltDirection.LEFT: case BoostTiltDirection.LEFT:
return this._peripheral.tiltX > 90 ? 256 - this._peripheral.tiltX : -this._peripheral.tiltX;
case BoostTiltDirection.RIGHT:
return this._peripheral.tiltX > 90 ? this._peripheral.tiltX - 256 : this._peripheral.tiltX; return this._peripheral.tiltX > 90 ? this._peripheral.tiltX - 256 : this._peripheral.tiltX;
case BoostTiltDirection.RIGHT:
return this._peripheral.tiltX > 90 ? 256 - this._peripheral.tiltX : -this._peripheral.tiltX;
default: default:
log.warn(`Unknown tilt direction in _getTiltAngle: ${direction}`); log.warn(`Unknown tilt direction in _getTiltAngle: ${direction}`);
} }
@ -2066,7 +1920,6 @@ class Scratch3BoostBlocks {
motors = [BoostPort.D]; motors = [BoostPort.D];
break; break;
case BoostMotorLabel.ALL: case BoostMotorLabel.ALL:
case BoostMotorLabel.DEFAULT:
motors = [BoostPort.A, BoostPort.B, BoostPort.C, BoostPort.D]; motors = [BoostPort.A, BoostPort.B, BoostPort.C, BoostPort.D];
break; break;
default: default: