Skip to content

Commit f161211

Browse files
committed
Added smoothing to interpolation.
1 parent da6461d commit f161211

File tree

4 files changed

+87
-18
lines changed

4 files changed

+87
-18
lines changed

src/telemetry/data.ts

+71-14
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,85 @@ export class DataPacket {
44
/**
55
* Interpolate between two data packets
66
* @param alpha Value 0-1, determines how close to this packet(0)
7-
* or the other packet(1) the output should be
8-
* @param other The packet to interpolate between
7+
* or the after packet(1) the output should be
8+
* @param before The packet before "this" packet, used to get the derivative for smoothing. Can be undefined.
9+
* @param after The packet to interpolate to. Can be undefined.
10+
* @param twoAfter The packet after "after", used to get the derivative for smoothing. Can be undefined.
911
*/
10-
interpolate(alpha: number, other: DataPacket): DataPacket {
11-
if(other === undefined) {
12+
interpolate(alpha: number, before: DataPacket, after: DataPacket, twoAfter: DataPacket): DataPacket {
13+
if(after === undefined) {
1214
return this;
1315
}
14-
let old_ra = this.ra;
15-
let new_ra = other.ra;
16-
if(Math.abs(this.ra - other.ra) > Math.PI) {
17-
if(this.ra < other.ra) {
18-
old_ra += 2 * Math.PI;
16+
17+
let before_ra = undefined;
18+
let cur_ra = this.ra;
19+
let after_ra = after.ra;
20+
let two_after_ra = undefined;
21+
22+
after_ra = this.loopAngleToBeCloseTo(after_ra, cur_ra);
23+
24+
if (before)
25+
before_ra = this.loopAngleToBeCloseTo(before.ra, cur_ra);
26+
if (twoAfter)
27+
two_after_ra = this.loopAngleToBeCloseTo(twoAfter.ra, after_ra);
28+
29+
let before_dist = undefined;
30+
let two_after_dist = undefined;
31+
if (before)
32+
before_dist = before.distance;
33+
if (twoAfter)
34+
two_after_dist = twoAfter.distance;
35+
36+
return new DataPacket(
37+
this.interpolateValue(alpha, before_ra, cur_ra, after_ra, two_after_ra),
38+
this.interpolateValue(alpha, before_dist, this.distance, after.distance, two_after_dist)
39+
);
40+
}
41+
42+
private loopAngleToBeCloseTo(to_be_looped: number, to_be_close_to: number): number {
43+
if (Math.abs(to_be_close_to - to_be_looped) > Math.PI) {
44+
if (to_be_close_to < to_be_looped) {
45+
to_be_looped -= 2 * Math.PI;
1946
}
2047
else {
21-
new_ra += 2 * Math.PI;
48+
to_be_looped += 2 * Math.PI;
2249
}
2350
}
51+
return to_be_looped;
52+
}
2453

25-
return new DataPacket(
26-
(alpha * new_ra + (1 - alpha) * old_ra),
27-
(alpha * other.distance + (1 - alpha) * this.distance)
28-
);
54+
/**
55+
* Interpolates beteween "curVal" and "afterVal", using beforeVal and twoAfterVal to get the derivatives in order to smooth.
56+
* @param alpha Value 0-1, determines how close to this packet(0)
57+
* or the after packet(1) the output should be
58+
* @param beforeVal The value before curVal, used to get the derivative for smoothing. Can be undefined.
59+
* @param curVal The value to start interpolating from
60+
* @param afterVal The value to interpolate to.
61+
* @param twoAfterVal The value after afterVal, used to get the derivative for smoothing. Can be undefined.
62+
*/
63+
private interpolateValue(alpha: number, beforeVal: number, curVal: number, afterVal: number, twoAfterVal: number): number {
64+
// linear => (alpha * afterVal + (1 - alpha) * curVal)
65+
66+
let y1 = curVal;
67+
let y2 = afterVal;
68+
69+
let middleDeriv = afterVal - curVal;
70+
71+
let m1 = middleDeriv;
72+
let m2 = middleDeriv;
73+
74+
if (beforeVal)
75+
m1 = ((curVal - beforeVal) + middleDeriv) / 2;
76+
77+
if (twoAfterVal)
78+
m2 = ((twoAfterVal - afterVal) + middleDeriv) / 2;
79+
80+
let a = m2 + m1 - 2*y2 + 2*y1;
81+
let b = -m2 - 2*m1 + 3*y2 - 3*y1;
82+
let c = m1;
83+
let d = y1;
84+
85+
return a * Math.pow(alpha, 3) + b * Math.pow(alpha, 2) + c * alpha + d;
2986
}
3087
}
3188

src/telemetry/telemetry.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,21 @@ export class Telemetry {
6969
return undefined;
7070
}
7171

72-
let beforeKey = this.data.getKey(index - 1);
72+
let beforeKey = undefined;
73+
if (index >= 2)
74+
beforeKey = this.data.getKey(index - 2);
75+
let curKey = this.data.getKey(index - 1);
7376
let afterKey = this.data.getKey(index);
77+
let twoAfterKey = undefined;
78+
if (index < this.data.numKeys() - 1)
79+
twoAfterKey = this.data.getKey(index + 1);
7480

7581
let beforeData = this.data.get(beforeKey);
82+
let curData = this.data.get(curKey);
7683
let afterData = this.data.get(afterKey);
84+
let twoAfterData = this.data.get(twoAfterKey);
7785

78-
return beforeData.interpolate((timestamp - beforeKey) / (afterKey - beforeKey), afterData);
86+
return curData.interpolate((timestamp - curKey) / (afterKey - curKey), beforeData, afterData, twoAfterData);
7987
}
8088
}
8189

src/util/dict.ts

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ export class NearestKeyDict<T> {
3535
return this.findKeyIndexHelper(key, start, i);
3636
}
3737
}
38+
39+
numKeys(): number {
40+
return this.keys.length;
41+
}
3842
}
3943

4044
export default NearestKeyDict;

tests/unit/data.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ describe('DataPacket', () => {
1111
it('can interpolate', () => {
1212
let d0 = new DataPacket(0, 0);
1313
let d2 = new DataPacket(2, 2);
14-
let d1 = d0.interpolate(0.5, d2);
14+
let d1 = d0.interpolate(0.5, undefined, d2, undefined);
1515

1616
expect(d1).to.not.be.null;
1717
expect(d1.ra).to.equal(1);
1818
expect(d1.distance).to.equal(1);
1919

20-
let d = d0.interpolate(0.25, d2);
20+
let d = d0.interpolate(0.25, undefined, d2, undefined);
2121

2222
expect(d).to.not.be.null;
2323
expect(d.ra).to.equal(0.5);

0 commit comments

Comments
 (0)