scratch-vm/src/util/math-util.js
Kevin Andersen ecbbacd4c0 It seems like there's a tradeoff between how we choose to set the max power of the motors. Previously, I had set the motors' max power (torque) to follow their target speed, meaning they accelerated smoothly, but also lost their torque. Then in the following commit I changed the max power to 100 which means maximum torque to achieve the target speed, which resulted in very abrupt accelerations and erratic motor movement when changing speeds:
873b56c985

In the following commit I changed the functionality so that we add a fixed amount (10) more power than the target speed, e.g. for speed 50 it would provide power 60. This is fine for high speeds, but for low speeds it provides poor torque:

e3cdbffa2a

I assume it would be possible to design some sort of calculation that enabled high torque for low speeds, and vice versa. I will discuss with the team.
2019-04-08 17:56:54 -04:00

96 lines
2.9 KiB
JavaScript

class MathUtil {
/**
* Convert a value from degrees to radians.
* @param {!number} deg Value in degrees.
* @return {!number} Equivalent value in radians.
*/
static degToRad (deg) {
return deg * Math.PI / 180;
}
/**
* Convert a value from radians to degrees.
* @param {!number} rad Value in radians.
* @return {!number} Equivalent value in degrees.
*/
static radToDeg (rad) {
return rad * 180 / Math.PI;
}
/**
* Clamp a number between two limits.
* If n < min, return min. If n > max, return max. Else, return n.
* @param {!number} n Number to clamp.
* @param {!number} min Minimum limit.
* @param {!number} max Maximum limit.
* @return {!number} Value of n clamped to min and max.
*/
static clamp (n, min, max) {
return Math.min(Math.max(n, min), max);
}
/**
* Keep a number between two limits, wrapping "extra" into the range.
* e.g., wrapClamp(7, 1, 5) == 2
* wrapClamp(0, 1, 5) == 5
* wrapClamp(-11, -10, 6) == 6, etc.
* @param {!number} n Number to wrap.
* @param {!number} min Minimum limit.
* @param {!number} max Maximum limit.
* @return {!number} Value of n wrapped between min and max.
*/
static wrapClamp (n, min, max) {
const range = (max - min) + 1;
return n - (Math.floor((n - min) / range) * range);
}
/**
* Convert a value from tan function in degrees.
* @param {!number} angle in degrees
* @return {!number} Correct tan value
*/
static tan (angle) {
angle = angle % 360;
switch (angle) {
case -270:
case 90:
return Infinity;
case -90:
case 270:
return -Infinity;
default:
return parseFloat(Math.tan((Math.PI * angle) / 180).toFixed(10));
}
}
/**
* Given an array of unique numbers,
* returns a reduced array such that each element of the reduced array
* represents the position of that element in a sorted version of the
* original array.
* E.g. [5, 19. 13, 1] => [1, 3, 2, 0]
* @param {Array<number>} elts The elements to sort and reduce
* @return {Array<number>} The array of reduced orderings
*/
static reducedSortOrdering (elts) {
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;