mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Fixed conflicts
This commit is contained in:
commit
75fc37aa30
2 changed files with 74 additions and 44 deletions
|
@ -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,16 +365,16 @@ 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 {
|
||||
this._power = p;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue