Fixed conflicts

This commit is contained in:
Kevin Andersen 2019-04-09 14:57:27 -04:00
commit 75fc37aa30
2 changed files with 74 additions and 44 deletions

View file

@ -33,10 +33,13 @@ const BoostBLE = {
};
/**
* Boost Motor Max Power.
* Boost Motor Max Power Add. Defines how much more power than the target speed
* the motors may supply to reach the target speed faster.
* Lower number == softer, slower reached target speed.
* Higher number == harder, faster reached target speed.
* @constant {number}
*/
const BoostMotorMaxPower = 100;
const BoostMotorMaxPowerAdd = 10;
/**
* A time interval to wait (in milliseconds) in between battery check calls.
@ -280,7 +283,7 @@ class BoostMotor {
* @type {number}
* @private
*/
this._power = 100;
this._power = 50;
/**
* This motor's current relative position
@ -362,17 +365,17 @@ class BoostMotor {
}
/**
* @param {int} value - this motor's new power level, in the range [0,100].
* @param {int} value - this motor's new power level, in the range [10,100].
*/
set power (value) {
const p = Math.max(0, Math.min(value, 100));
// The Boost motors barely move at speed 1 - solution is to step up to 2.
if (p === 1) {
this._power = 2;
} else {
/**
* Scale the motor power to a range between 10 and 100,
* to make sure the motors will run with something built onto them.
*/
const p = MathUtil.scale(value, 0, 100, 10, 100);
this._power = p;
}
}
/**
* @return {int} - this motor's current position, in the range of [-MIN_INT32,MAX_INT32]
@ -440,13 +443,14 @@ class BoostMotor {
if (this._power === 0) return;
const cmd = this._parent.generateOutputCommand(
this._index,
BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK,
BoostOutputExecution.EXECUTE_IMMEDIATELY,
BoostOutputSubCommand.START_SPEED,
[
this._power * this._direction,
BoostMotorMaxPower,
this.power * this.direction,
MathUtil.clamp(this.power + BoostMotorMaxPowerAdd, 0, 100),
BoostMotorProfile.DO_NOT_USE
]);
this._status = BoostPortFeedback.BUSY_OR_FULL;
this._parent.send(BoostBLE.characteristic, cmd);
@ -458,7 +462,7 @@ class BoostMotor {
* @param {number} milliseconds - run the motor for this long.
*/
turnOnFor (milliseconds) {
if (this._power === 0) return;
if (this.power === 0) return;
milliseconds = Math.max(0, milliseconds);
this.turnOn();
@ -480,19 +484,19 @@ class BoostMotor {
const cmd = this._parent.generateOutputCommand(
this._index,
BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK,
(BoostOutputExecution.EXECUTE_IMMEDIATELY ^ BoostOutputExecution.COMMAND_FEEDBACK),
BoostOutputSubCommand.START_SPEED_FOR_DEGREES,
[
...numberToInt32Array(degrees),
this._power * this._direction * direction,
BoostMotorMaxPower,
this.power * this.direction * direction,
MathUtil.clamp(this.power + BoostMotorMaxPowerAdd, 0, 100),
BoostMotorEndState.BRAKE,
BoostMotorProfile.DO_NOT_USE
]
);
this._pendingPositionOrigin = this._position;
this._pendingPositionDestination = this._position + (degrees * this._direction * direction);
this._pendingPositionOrigin = this.position;
this._pendingPositionDestination = this.position + (degrees * this.direction * direction);
this._parent.send(BoostBLE.characteristic, cmd);
}
@ -501,7 +505,7 @@ class BoostMotor {
* @param {boolean} [useLimiter=true] - if true, use the rate limiter
*/
turnOff (useLimiter = true) {
if (this._power === 0) return;
if (this.power === 0) return;
const cmd = this._parent.generateOutputCommand(
this._index,
@ -594,7 +598,8 @@ class Boost {
this._sensors = {
tiltX: 0,
tiltY: 0,
color: BoostColor.NONE
color: BoostColor.NONE,
previousColor: BoostColor.NONE
};
/**
@ -602,7 +607,7 @@ class Boost {
* @type {Array}
* @private
*/
this._colorBucket = [];
this._colorSamples = [];
/**
* The Bluetooth connection socket for reading/writing peripheral data.
@ -738,7 +743,7 @@ class Boost {
dataPrefix: [0x97, 0x03, 0x00, 0x40],
mask: [0xFF, 0xFF, 0, 0xFF]
}
} */
} commented out until feature is enabled in scratch-link */
}],
optionalServices: []
}, this._onConnect, this.disconnect);
@ -764,7 +769,7 @@ class Boost {
tiltX: 0,
tiltY: 0,
color: BoostColor.NONE,
oldColor: BoostColor.NONE
previousColor: BoostColor.NONE
};
if (this._ble) {
@ -883,7 +888,7 @@ class Boost {
/**
* First three bytes are the common header:
* 0: Length of message
* 1: Hub ID (always 0x00 at the moment)
* 1: Hub ID (always 0x00 at the moment, unused)
* 2: Message Type
* 3: Port ID
* We base our switch-case on Message Type
@ -918,11 +923,11 @@ class Boost {
this._sensors.tiltY = data[5];
break;
case BoostIO.COLOR:
this._colorBucket.unshift(data[4]);
if (this._colorBucket.length > BoostColorSampleSize) {
this._colorBucket.pop();
if (this._colorBucket.every((v, i, arr) => v === arr[0])) {
this._sensors.color = this._colorBucket[0];
this._colorSamples.unshift(data[4]);
if (this._colorSamples.length > BoostColorSampleSize) {
this._colorSamples.pop();
if (this._colorSamples.every((v, i, arr) => v === arr[0])) {
this._sensors.color = this._colorSamples[0];
} else {
this._sensors.color = BoostColor.NONE;
}
@ -947,9 +952,12 @@ class Boost {
const motor = this.motor(portID);
if (motor) {
motor._status = feedback;
if (feedback === (BoostPortFeedback.COMPLETED ^ BoostPortFeedback.IDLE) &&
motor.pendingPromiseFunction) {
// Makes sure that commands resolve both when they actually complete and when they fail
const isBusy = feedback & BoostPortFeedback.IN_PROGRESS;
const commandCompleted = feedback & (BoostPortFeedback.COMPLETED ^ BoostPortFeedback.DISCARDED);
if (!isBusy && commandCompleted && motor.pendingPromiseFunction) {
motor.pendingPromiseFunction();
motor.pendingPromiseFunction = null;
}
}
break;
@ -957,7 +965,6 @@ class Boost {
case BoostMessage.ERROR:
log.warn(`Error reported by hub: ${data}`);
break;
default:
}
}
@ -1645,6 +1652,11 @@ class Scratch3BoostBlocks {
const promises = motors.map(portID => {
const motor = this._peripheral.motor(portID);
if (motor) {
if (motor.pendingPromiseFunction) {
// If there's already a promise for this motor it must be resolved to avoid hanging blocks.
motor.pendingPromiseFunction();
motor.pendingPromiseFunction = null;
}
return new Promise(resolve => {
motor.pendingPromiseFunction = resolve;
motor.turnOnForDegrees(degrees, sign);
@ -1718,9 +1730,11 @@ class Scratch3BoostBlocks {
if (motor.isOn) {
if (motor.pendingTimeoutDelay) {
motor.turnOnFor(motor.pendingTimeoutStartTime + motor.pendingTimeoutDelay - Date.now());
} else if (motor.pendingPositionDestination) {
const p = motor.pendingPositionDestination - motor.position;
motor.turnOnForDegrees(p, Math.sign(p) * motor.direction);
} else if (motor.pendingPromiseFunction) {
const p = Math.abs(motor.pendingPositionDestination - motor.position);
motor.turnOnForDegrees(p, Math.sign(p));
} else {
motor.turnOn();
}
}
}
@ -1757,9 +1771,11 @@ class Scratch3BoostBlocks {
if (motor.isOn) {
if (motor.pendingTimeoutDelay) {
motor.turnOnFor(motor.pendingTimeoutStartTime + motor.pendingTimeoutDelay - Date.now());
} else if (motor.pendingPositionDestination) {
const p = motor.pendingPositionDestination - motor.position;
motor.turnOnForDegrees(p, Math.sign(p) * motor.direction);
} else if (motor.pendingPromiseFunction) {
const p = Math.abs(motor.pendingPositionDestination - motor.position);
motor.turnOnForDegrees(p, Math.sign(p));
} else {
motor.turnOn();
}
}
}
@ -1790,8 +1806,8 @@ class Scratch3BoostBlocks {
log.warn('Asked for a motor position that doesnt exist!');
return false;
}
if (portID && this._peripheral._motors[portID]) {
return MathUtil.wrapClamp(this._peripheral._motors[portID].position, 0, 360);
if (portID && this.motor(portID)) {
return MathUtil.wrapClamp(this.motor(portID).position, 0, 360);
}
return 0;
}
@ -1930,10 +1946,10 @@ class Scratch3BoostBlocks {
case BoostColorLabel.ANY:
if (Object.keys(BoostColor).find(key => BoostColor[key])
.toLowerCase() !== this.getColor()) {
if (this.getColor() === this._peripheral.oldColor) {
if (this.getColor() === this._peripheral._sensors.previousColor) {
return false;
}
this._peripheral.oldColor = this.getColor();
this._peripheral._sensors.previousColor = this.getColor();
return true;
}
break;

View file

@ -77,6 +77,20 @@ class MathUtil {
const sorted = elts.slice(0).sort((a, b) => a - b);
return elts.map(e => sorted.indexOf(e));
}
/**
* Scales a number from one range to another.
* @param {number} i number to be scaled
* @param {number} iMin input range minimum
* @param {number} iMax input range maximum
* @param {number} oMin output range minimum
* @param {number} oMax output range maximum
* @return {number} scaled number
*/
static scale (i, iMin, iMax, oMin, oMax) {
const p = (i - iMin) / (iMax - iMin);
return (p * (oMax - oMin)) + oMin;
}
}
module.exports = MathUtil;