@fboes/aerofly-custom-missions 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/dto-flight/AeroflyNavRouteBase.js +3 -2
  3. package/dist/dto-flight/AeroflyNavRouteBase.test.js +45 -15
  4. package/dist/dto-flight/AeroflyNavRouteRunway.js +5 -5
  5. package/dist/dto-flight/AeroflyNavRouteTransition.js +5 -4
  6. package/dist/dto-flight/AeroflySettingsFlight.js +12 -14
  7. package/dist/dto-flight/AeroflySettingsFlight.test.js +17 -22
  8. package/dist/node/AeroflyTypes.js +60 -0
  9. package/dist/node/Convert.js +54 -23
  10. package/dist/node/Convert.test.js +51 -21
  11. package/docs/flight.json +1 -1
  12. package/docs/flight.mcf +1 -1
  13. package/docs/flight.xml +1 -1
  14. package/package.json +1 -1
  15. package/src/dto-flight/AeroflyFlight.ts +0 -0
  16. package/src/dto-flight/AeroflyNavRouteBase.test.ts +50 -15
  17. package/src/dto-flight/AeroflyNavRouteBase.ts +5 -4
  18. package/src/dto-flight/AeroflyNavRouteRunway.ts +5 -5
  19. package/src/dto-flight/AeroflyNavRouteTransition.ts +6 -5
  20. package/src/dto-flight/AeroflyNavRouteWaypoint.ts +1 -1
  21. package/src/dto-flight/AeroflySettingsFlight.test.ts +22 -30
  22. package/src/dto-flight/AeroflySettingsFlight.ts +21 -20
  23. package/src/node/AeroflyTypes.ts +70 -0
  24. package/src/node/Convert.test.ts +115 -36
  25. package/src/node/Convert.ts +79 -27
  26. package/types/dto-flight/AeroflyNavRouteBase.d.ts +2 -2
  27. package/types/dto-flight/AeroflyNavRouteBase.d.ts.map +1 -1
  28. package/types/dto-flight/AeroflyNavRouteRunway.d.ts +1 -1
  29. package/types/dto-flight/AeroflyNavRouteRunway.d.ts.map +1 -1
  30. package/types/dto-flight/AeroflyNavRouteTransition.d.ts +1 -1
  31. package/types/dto-flight/AeroflyNavRouteTransition.d.ts.map +1 -1
  32. package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts +1 -1
  33. package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts.map +1 -1
  34. package/types/dto-flight/AeroflySettingsFlight.d.ts +9 -4
  35. package/types/dto-flight/AeroflySettingsFlight.d.ts.map +1 -1
  36. package/types/dto-flight/AeroflySettingsFuelLoad.d.ts.map +1 -1
  37. package/types/node/AeroflyTypes.d.ts +39 -0
  38. package/types/node/AeroflyTypes.d.ts.map +1 -0
  39. package/types/node/Convert.d.ts +29 -5
  40. package/types/node/Convert.d.ts.map +1 -1
@@ -1,30 +1,65 @@
1
1
  import { describe, it } from "node:test";
2
+ import { strict as assert } from "node:assert";
2
3
  import { AeroflyNavRouteDestination } from "../index.js";
3
4
 
4
5
  describe("AeroflyNavRouteBase", () => {
5
- it("should create a valid AeroflyNavRouteBase structure", () => {
6
- const waypoints = [
7
- { wp: new AeroflyNavRouteDestination("MAX-NE", 179.999, 89.999), uid: 0n },
8
- { wp: new AeroflyNavRouteDestination("MAX-SW", -179.999, -89.999), uid: 0n },
9
- { wp: new AeroflyNavRouteDestination("KEYW", -81.7599558, 24.5561197), uid: 5033914504046249216n },
10
- { wp: new AeroflyNavRouteDestination("EGLL", -0.45277777, 51.47138888), uid: 9199731073154483456n },
11
- { wp: new AeroflyNavRouteDestination("YSSY", 151.177, -33.4961), uid: 16969837613165511936n },
12
- { wp: new AeroflyNavRouteDestination("RJTT", 139.779, 35.709), uid: 16385890514078663936n },
6
+ it("should create UIDs almost matching the ingame UIDs", () => {
7
+ const testCases = [
8
+ {
9
+ wp: new AeroflyNavRouteDestination("MAX-NE", 179.999, 89.999),
10
+ assertUid: 18446694595666707712n,
11
+ ingameUid: 0n,
12
+ },
13
+ {
14
+ wp: new AeroflyNavRouteDestination("MAX-SW", -179.999, -89.999),
15
+ assertUid: 51677066167552n,
16
+ ingameUid: 0n,
17
+ },
18
+ {
19
+ wp: new AeroflyNavRouteDestination("KEYW", -81.7599558, 24.5561197),
20
+ assertUid: 5033914504046314752n,
21
+ ingameUid: 5033914504046249216n,
22
+ },
23
+ {
24
+ wp: new AeroflyNavRouteDestination("EGLL", -0.45277777, 51.47138888),
25
+ assertUid: 9200173076798702848n,
26
+ ingameUid: 9199731073154483456n,
27
+ },
28
+ {
29
+ wp: new AeroflyNavRouteDestination("YSSY", 151.177, -33.4961),
30
+ assertUid: 16969826619723154688n,
31
+ ingameUid: 16969837613165511936n,
32
+ },
33
+ {
34
+ wp: new AeroflyNavRouteDestination("RJTT", 139.779, 35.709),
35
+ assertUid: 16385782762532177152n,
36
+ ingameUid: 16385890514078663936n,
37
+ },
13
38
  ];
14
39
 
15
- for (const waypoint of waypoints) {
16
- console.log(waypoint.wp.getUidFallback(), waypoint.uid);
40
+ for (const testCase of testCases) {
41
+ assert.strictEqual(
42
+ testCase.wp.getUidFallback(),
43
+ testCase.assertUid,
44
+ `${testCase.wp.identifier} was ${testCase.ingameUid}`,
45
+ );
17
46
  }
18
47
  });
19
48
 
20
- it("should test some unpacking of UIDs", () => {
49
+ it("should unpack UIDs for airports to code 1280", () => {
21
50
  const unpackPayload = (packed: bigint) => {
22
51
  return Number(packed & 0xffffn);
23
52
  };
24
53
 
25
- console.log("KEYW", unpackPayload(5033914504046314752n));
26
- console.log("EGLL", unpackPayload(9200173076798702848n));
27
- console.log("YSSY", unpackPayload(16969826619723154688n));
28
- console.log("RJTT", unpackPayload(16385782762532177152n));
54
+ const testCases = [
55
+ { uid: 5033914504046314752n, code: 1280, airport: "KEYW" },
56
+ { uid: 9200173076798702848n, code: 1280, airport: "EGLL" },
57
+ { uid: 16969826619723154688n, code: 1280, airport: "YSSY" },
58
+ { uid: 16385782762532177152n, code: 1280, airport: "RJTT" },
59
+ ];
60
+
61
+ for (const testCase of testCases) {
62
+ assert.strictEqual(unpackPayload(testCase.uid), testCase.code, testCase.airport);
63
+ }
29
64
  });
30
65
  });
@@ -1,5 +1,6 @@
1
- import { convertLonLatToVector, convertVectorToLonLat, type AeroflyVector3Float } from "../node/Convert.js";
1
+ import { convertLonLatToVector, convertVectorToLonLat } from "../node/Convert.js";
2
2
  import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
3
+ import { AeroflyVector3Float, type AeroflyVector3FloatArray } from "../node/AeroflyTypes.js";
3
4
 
4
5
  export type AeroflyNavRouteType =
5
6
  | "origin"
@@ -77,8 +78,8 @@ export class AeroflyNavRouteBase {
77
78
  * @param {AeroflyVector3Float} position to set longitude and latitude from
78
79
  * @returns {this} for chaining
79
80
  */
80
- setPosition(position: AeroflyVector3Float): this {
81
- this.position = position;
81
+ setPosition(position: AeroflyVector3FloatArray): this {
82
+ this.position = AeroflyVector3Float.fromArray(position);
82
83
  return this;
83
84
  }
84
85
 
@@ -88,7 +89,7 @@ export class AeroflyNavRouteBase {
88
89
  .appendChild(
89
90
  "vector3_float64",
90
91
  "Position",
91
- this.position,
92
+ this.position.toArray(),
92
93
  `Lon ${this.longitude.toFixed(6)}, Lat ${this.latitude.toFixed(6)}`,
93
94
  )
94
95
  .appendChild(
@@ -1,6 +1,7 @@
1
- import { convertFeetToMeter, convertMeterToFeet, type AeroflyVector3Float } from "../node/Convert.js";
1
+ import { convertDirectionToHeading, convertFeetToMeter, convertMeterToFeet } from "../node/Convert.js";
2
2
  import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
3
3
  import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
4
+ import { AeroflyVector3Float } from "../node/AeroflyTypes.js";
4
5
 
5
6
  class AeroflyNavRouteRunway extends AeroflyNavRouteBase {
6
7
  /**
@@ -66,12 +67,11 @@ class AeroflyNavRouteRunway extends AeroflyNavRouteBase {
66
67
  * @returns {AeroflyVector3Float | null} runway direction, null if not set
67
68
  */
68
69
  get direction(): AeroflyVector3Float | null {
69
- // TODO: calculate direction vector from direction_degree
70
- return this.direction_degree !== null ? [0, 0, 0] : null;
70
+ return this.direction_degree !== null ? new AeroflyVector3Float(0, 0, 0) : null; // TODO: Get direction vector
71
71
  }
72
72
 
73
73
  set direction(direction: AeroflyVector3Float) {
74
- this.direction_degree = 0; // TODO: calculate direction_degree from direction vector
74
+ this.direction_degree = convertDirectionToHeading(direction, this.position);
75
75
  }
76
76
 
77
77
  getElement(index: number = 0): AeroflyConfigurationNode {
@@ -80,7 +80,7 @@ class AeroflyNavRouteRunway extends AeroflyNavRouteBase {
80
80
  element.appendChild(
81
81
  "vector3_float64",
82
82
  "Direction",
83
- this.direction,
83
+ this.direction.toArray(),
84
84
  `Runway direction ${Math.round(this.direction_degree ?? 0)}°`,
85
85
  );
86
86
  }
@@ -1,6 +1,7 @@
1
- import { convertFeetToMeter, convertMeterToFeet, type AeroflyVector3Float } from "../node/Convert.js";
1
+ import { convertFeetToMeter, convertMeterToFeet } from "../node/Convert.js";
2
2
  import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
3
3
  import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
4
+ import { AeroflyVector3Float } from "../node/AeroflyTypes.js";
4
5
 
5
6
  class AeroflyNavRouteTransition extends AeroflyNavRouteBase {
6
7
  /**
@@ -52,14 +53,14 @@ class AeroflyNavRouteTransition extends AeroflyNavRouteBase {
52
53
  * @returns {AeroflyVector3Float} deliberately empty
53
54
  */
54
55
  get position(): AeroflyVector3Float {
55
- return [0, 0, 0]; // sic!
56
+ return new AeroflyVector3Float(0, 0, 0); // sic!
56
57
  }
57
58
 
58
59
  /**
59
60
  * @returns {AeroflyVector3Float} deliberately empty
60
61
  */
61
62
  get direction(): AeroflyVector3Float {
62
- return [0, 0, 0]; // sic!
63
+ return new AeroflyVector3Float(0, 0, 0); // sic!
63
64
  }
64
65
 
65
66
  getElement(index: number = 0): AeroflyConfigurationNode {
@@ -67,7 +68,7 @@ class AeroflyNavRouteTransition extends AeroflyNavRouteBase {
67
68
 
68
69
  element
69
70
  .appendChild("string8u", "Airport", this.airport)
70
- .appendChild("vector3_float64", "Direction", this.direction)
71
+ .appendChild("vector3_float64", "Direction", this.direction.toArray())
71
72
  .appendChild(
72
73
  "float64",
73
74
  "Elevation",
@@ -115,7 +116,7 @@ export class AeroflyNavRouteArrival extends AeroflyNavRouteTransition {
115
116
 
116
117
  element
117
118
  .appendChild("string8u", "Airport", this.airport)
118
- .appendChild("vector3_float64", "Direction", this.direction)
119
+ .appendChild("vector3_float64", "Direction", this.direction.toArray())
119
120
  .appendChild(
120
121
  "float64",
121
122
  "Elevation",
@@ -3,10 +3,10 @@ import {
3
3
  convertLonLatToVector,
4
4
  convertMeterToFeet,
5
5
  convertVectorToLonLat,
6
- type AeroflyVector3Float,
7
6
  } from "../node/Convert.js";
8
7
  import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
9
8
  import { AeroflyNavRouteBase } from "./AeroflyNavRouteBase.js";
9
+ import type { AeroflyVector3Float } from "../node/AeroflyTypes.js";
10
10
 
11
11
  export class AeroflyNavRouteWaypoint extends AeroflyNavRouteBase {
12
12
  /**
@@ -38,36 +38,6 @@ describe("AeroflySettingsFlight", () => {
38
38
  assertValidAeroflyStructure(flight.toString());
39
39
  });
40
40
 
41
- it("should use valid orientation from main.mcf", () => {
42
- const flight = new AeroflySettingsFlight(-122.3088, 47.4502, 1000, 90, 150);
43
-
44
- // Canada
45
- flight.orientation = [
46
- -0.763419555334921, 0.645896043270811, 0.00298057365988389, -0.564914354076689, -0.665451427226094,
47
- -0.487899754622681, -0.313149094027667, -0.374155982565915, 0.872894578754952,
48
- ];
49
-
50
- console.log("Orientation:", flight.heading_degree); // should be 270, is 216
51
-
52
- // South Africa
53
- flight.orientation = [
54
- 0.324874838801671, -0.945743434574979, 0.0050690306677758, -0.526455468124437, -0.185291526716742,
55
- -0.829766045466347, 0.785685038164447, 0.266901491350839, -0.5580883574482,
56
- ];
57
-
58
- console.log("Orientation:", flight.heading_degree); // should be 270, is 301
59
-
60
- // Japan
61
- flight.orientation = [
62
- 0.717429258146935, 0.696613268777701, 0.00502128644729529, -0.393795668419003, 0.411487688662976,
63
- -0.821950639401925, -0.574647919242008, 0.587714076606685, 0.569536595021937,
64
- ];
65
-
66
- console.log("Orientation:", flight.heading_degree); // should be 270, is 331
67
-
68
- assertValidAeroflyStructure(flight.toString());
69
- });
70
-
71
41
  it("should create fallbacks for flight configurations", () => {
72
42
  const flight = new AeroflySettingsFlight(-122.3088, 47.4502, 1000, 90, 150, {
73
43
  configuration: "OnGround",
@@ -89,4 +59,26 @@ describe("AeroflySettingsFlight", () => {
89
59
  assert.ok(flight.flaps > 0, "Flaps extended");
90
60
  assert.strictEqual(flight.onGround, false);
91
61
  });
62
+
63
+ it("should convert between speed and velocity vector", () => {
64
+ const flight = new AeroflySettingsFlight(-122.3088, 47.4502, 1000, 90, 150);
65
+
66
+ assert.strictEqual(flight.speed_kts, 150);
67
+ assert.strictEqual(flight.speed_ms, 77.1666);
68
+
69
+ const velocity = flight.velocity;
70
+ assert.ok(velocity.x > 60);
71
+ assert.ok(velocity.y < -40);
72
+ assert.ok(velocity.z > 0);
73
+
74
+ // Reset speed
75
+ flight.speed_ms = 0;
76
+ assert.strictEqual(flight.speed_kts, 0);
77
+ assert.strictEqual(flight.speed_ms, 0);
78
+
79
+ // Set speed from velocity vector
80
+ flight.velocity = velocity;
81
+ assert.strictEqual(flight.speed_kts, 150);
82
+ assert.strictEqual(flight.speed_ms, 77.1666);
83
+ });
92
84
  });
@@ -1,12 +1,16 @@
1
1
  import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
2
2
  import {
3
- type AeroflyVector3Float,
4
- type AeroflyMatrix3Float,
3
+ AeroflyMatrix3Float,
4
+ AeroflyVector3Float,
5
+ type AeroflyMatrix3FloatArray,
6
+ type AeroflyVector3FloatArray,
7
+ } from "../node/AeroflyTypes.js";
8
+ import {
5
9
  convertFeetToMeter,
6
10
  convertLonLatToVector,
7
11
  convertVectorToLonLat,
8
- convertDegreeToMatrix,
9
- convertMatrixToDegree,
12
+ convertHeadingToOrientation,
13
+ convertOrientationToHeading,
10
14
  convertMeterToFeet,
11
15
  } from "../node/Convert.js";
12
16
 
@@ -103,15 +107,15 @@ export class AeroflySettingsFlight {
103
107
  }
104
108
 
105
109
  static createInCartesian(
106
- position: AeroflyVector3Float,
107
- velocity: AeroflyVector3Float,
108
- orientation: AeroflyMatrix3Float,
110
+ position: AeroflyVector3FloatArray,
111
+ velocity: AeroflyVector3FloatArray,
112
+ orientation: AeroflyMatrix3FloatArray,
109
113
  additionalAttributes: Partial<AeroflySettingsFlight> = {},
110
114
  ): AeroflySettingsFlight {
111
115
  const flight = new AeroflySettingsFlight(0, 0, 0, 0, 0, additionalAttributes);
112
- flight.position = position;
113
- flight.velocity = velocity;
114
- flight.orientation = orientation;
116
+ flight.position = AeroflyVector3Float.fromArray(position);
117
+ flight.velocity = AeroflyVector3Float.fromArray(velocity);
118
+ flight.orientation = AeroflyMatrix3Float.fromArray(orientation);
115
119
  return flight;
116
120
  }
117
121
 
@@ -142,7 +146,6 @@ export class AeroflySettingsFlight {
142
146
  break;
143
147
  default:
144
148
  this.throttle = 0;
145
- this.speed_kts = 0;
146
149
  break;
147
150
  }
148
151
  }
@@ -166,21 +169,19 @@ export class AeroflySettingsFlight {
166
169
  */
167
170
  get velocity(): AeroflyVector3Float {
168
171
  const speed = this.speed_ms;
169
- const heading_rad = this.heading_degree * (Math.PI / 180);
170
- return [Math.cos(heading_rad) * speed, Math.sin(heading_rad) * speed, 0];
172
+ return this.orientation.multiplyVector(new AeroflyVector3Float(speed, 0, 0));
171
173
  }
172
174
 
173
175
  set velocity(velocity: AeroflyVector3Float) {
174
- // TODO: implement setting velocity vector and updating speed accordingly
175
- this.speed_ms = 0;
176
+ this.speed_ms = Math.sqrt(velocity.x ** 2 + velocity.y ** 2 + velocity.z ** 2);
176
177
  }
177
178
 
178
179
  get orientation(): AeroflyMatrix3Float {
179
- return convertDegreeToMatrix(this.heading_degree);
180
+ return convertHeadingToOrientation(this.heading_degree, this.position);
180
181
  }
181
182
 
182
183
  set orientation(orientation: AeroflyMatrix3Float) {
183
- this.heading_degree = convertMatrixToDegree(orientation);
184
+ this.heading_degree = convertOrientationToHeading(orientation, this.position);
184
185
  }
185
186
 
186
187
  /**
@@ -210,14 +211,14 @@ export class AeroflySettingsFlight {
210
211
  .appendChild(
211
212
  "vector3_float64",
212
213
  "position",
213
- this.position,
214
+ this.position.toArray(),
214
215
  `Lon ${this.longitude.toFixed(6)}, Lat ${this.latitude.toFixed(6)}, ${Math.ceil(this.altitude_ft)} ft`,
215
216
  )
216
- .appendChild("vector3_float64", "velocity", this.velocity, `${Math.round(this.speed_kts)} kts`)
217
+ .appendChild("vector3_float64", "velocity", this.velocity.toArray(), `${Math.round(this.speed_kts)} kts`)
217
218
  .appendChild(
218
219
  "matrix3_float64",
219
220
  "orientation",
220
- this.orientation,
221
+ this.orientation.toArray(),
221
222
  `${Math.round(this.heading_degree)}° heading`,
222
223
  )
223
224
  .appendChild("float64", "gear", this.gear)
@@ -0,0 +1,70 @@
1
+ export type AeroflyVector3FloatArray = [number, number, number];
2
+
3
+ export class AeroflyVector3Float {
4
+ constructor(
5
+ public x: number,
6
+ public y: number,
7
+ public z: number,
8
+ ) {}
9
+
10
+ normalize(): AeroflyVector3Float {
11
+ const norm = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
12
+
13
+ if (norm === 0) {
14
+ return new AeroflyVector3Float(0, 0, 0);
15
+ }
16
+ return new AeroflyVector3Float(this.x / norm, this.y / norm, this.z / norm);
17
+ }
18
+
19
+ cross(b: AeroflyVector3Float): AeroflyVector3Float {
20
+ return new AeroflyVector3Float(
21
+ this.y * b.z - this.z * b.y,
22
+ this.z * b.x - this.x * b.z,
23
+ this.x * b.y - this.y * b.x,
24
+ );
25
+ }
26
+
27
+ static fromArray(array: AeroflyVector3FloatArray): AeroflyVector3Float {
28
+ return new this(...array);
29
+ }
30
+
31
+ toArray(): AeroflyVector3FloatArray {
32
+ return [this.x, this.y, this.z];
33
+ }
34
+ }
35
+
36
+ export type AeroflyMatrix3FloatArray = [number, number, number, number, number, number, number, number, number];
37
+
38
+ export class AeroflyMatrix3Float {
39
+ constructor(
40
+ public xx: number,
41
+ public yx: number,
42
+ public zx: number,
43
+ public xy: number,
44
+ public yy: number,
45
+ public zy: number,
46
+ public xz: number,
47
+ public yz: number,
48
+ public zz: number,
49
+ ) {}
50
+
51
+ transpose(): AeroflyMatrix3Float {
52
+ return new AeroflyMatrix3Float(this.xx, this.xy, this.xz, this.yx, this.yy, this.yz, this.zx, this.zy, this.zz);
53
+ }
54
+
55
+ multiplyVector(v: AeroflyVector3Float): AeroflyVector3Float {
56
+ return new AeroflyVector3Float(
57
+ this.xx * v.x + this.xy * v.y + this.xz * v.z,
58
+ this.yx * v.x + this.yy * v.y + this.yz * v.z,
59
+ this.zx * v.x + this.zy * v.y + this.zz * v.z,
60
+ );
61
+ }
62
+
63
+ static fromArray(array: AeroflyMatrix3FloatArray): AeroflyMatrix3Float {
64
+ return new this(...array);
65
+ }
66
+
67
+ toArray(): AeroflyMatrix3FloatArray {
68
+ return [this.xx, this.yx, this.zx, this.xy, this.yy, this.zy, this.xz, this.yz, this.zz];
69
+ }
70
+ }
@@ -2,14 +2,14 @@ import { describe, it } from "node:test";
2
2
  import { strict as assert } from "node:assert";
3
3
 
4
4
  import {
5
- convertDegreeToMatrix,
5
+ convertHeadingToOrientation,
6
6
  convertFeetToMeter,
7
7
  convertLonLatToVector,
8
- convertMatrixToDegree,
8
+ convertOrientationToHeading,
9
9
  convertMeterToFeet,
10
10
  convertVectorToLonLat,
11
- type AeroflyMatrix3Float,
12
11
  } from "./Convert.js";
12
+ import { AeroflyMatrix3Float, AeroflyVector3Float } from "./AeroflyTypes.js";
13
13
 
14
14
  describe("Convert", () => {
15
15
  it("should convert feet to meters correctly", () => {
@@ -54,45 +54,124 @@ describe("Convert", () => {
54
54
  );
55
55
  });
56
56
 
57
- it("should convert heading degree to orientation matrix and back correctly", () => {
58
- const orientationMatrix: AeroflyMatrix3Float = [0, -1, 0, 1, 0, 0, 0, 0, 1];
59
- const expectedHeadingDegree = 90;
57
+ it("should convert orientation matrix to heading degree", () => {
58
+ const positionKEYW = new AeroflyVector3Float(831922.0452075421, -5744695.679418418, 2634432.6068597846);
59
+ const positionYSSY = new AeroflyVector3Float(-4640429.92586909, 2553500.8064244, -3541489.45541516);
60
60
 
61
- const actualHeadingDegree = convertMatrixToDegree(orientationMatrix);
62
- assert.strictEqual(
63
- actualHeadingDegree.toFixed(4),
64
- expectedHeadingDegree.toFixed(4),
65
- `Expected heading degree to be ${expectedHeadingDegree.toFixed(4)}, got ${actualHeadingDegree.toFixed(4)}`,
66
- );
67
- });
61
+ const testCases = [
62
+ {
63
+ orientation: new AeroflyMatrix3Float(
64
+ -0.0668066264395785,
65
+ 0.431792064197595,
66
+ 0.899495685348041,
67
+ -0.98941528906399,
68
+ -0.145060537051883,
69
+ -0.00385050082983023,
70
+ 0.128818711490931,
71
+ -0.890232022500988,
72
+ 0.43691267512355,
73
+ ),
74
+ position: positionKEYW,
75
+ heading: 0,
76
+ },
77
+ {
78
+ orientation: new AeroflyMatrix3Float(
79
+ 0.985978516472605,
80
+ 0.166832368887515,
81
+ -0.00365044461148948,
82
+ -0.066064640816506,
83
+ 0.41034317377044,
84
+ 0.90953501470465,
85
+ 0.153237816116869,
86
+ -0.896540819166301,
87
+ 0.41561127424596,
88
+ ),
89
+ position: positionKEYW,
90
+ heading: 90,
91
+ },
68
92
 
69
- it("should convert heading degree to orientation matrix and back correctly", () => {
70
- const heading_degree = 90;
71
- const expectedHeadingDegree = 90;
72
-
73
- const orientationMatrix = convertDegreeToMatrix(heading_degree);
74
- console.log("Orientation Matrix:", orientationMatrix);
93
+ {
94
+ orientation: new AeroflyMatrix3Float(
95
+ -0.465135059130883,
96
+ -0.885151853036744,
97
+ 0.0124729239927332,
98
+ -0.489418463305539,
99
+ 0.268872261996669,
100
+ 0.829564508946978,
101
+ -0.737644185595572,
102
+ 0.379755057628484,
103
+ -0.558271575187768,
104
+ ),
105
+ position: positionYSSY,
106
+ heading: 90,
107
+ },
108
+ ];
75
109
 
76
- const actualHeadingDegree = convertMatrixToDegree(orientationMatrix);
77
- assert.strictEqual(
78
- actualHeadingDegree.toFixed(4),
79
- expectedHeadingDegree.toFixed(4),
80
- `Expected heading degree to be ${expectedHeadingDegree.toFixed(4)}, got ${actualHeadingDegree.toFixed(4)}`,
81
- );
110
+ for (const testCase of testCases) {
111
+ const calculatedHeading = convertOrientationToHeading(testCase.orientation, testCase.position);
112
+ const message = `Expected heading to be ${testCase.heading.toFixed(4)}, got ${calculatedHeading.toFixed(4)}`;
113
+ assert.strictEqual(Math.round(calculatedHeading) % 360, Math.round(testCase.heading) % 360, message);
114
+ }
82
115
  });
83
116
 
84
- it("should show the orientation at Tellruide correctly", () => {
85
- const orientationMatrix: AeroflyMatrix3Float = [
86
- -0.449510470601295, -0.541223404385256, -0.710645877610949, 0.868733701939534, -0.450067862031944,
87
- -0.206738179058507, -0.207947329711721, -0.710293000184874, 0.672489228132418,
117
+ it("should convert heading degree to orientation matrix (ignoring pitch, roll, yaw, etc.)", () => {
118
+ const positionKEYW = new AeroflyVector3Float(831922.0452075421, -5744695.679418418, 2634432.6068597846);
119
+ const positionYSSY = new AeroflyVector3Float(-4640429.92586909, 2553500.8064244, -3541489.45541516);
120
+
121
+ const testCases = [
122
+ {
123
+ orientation: new AeroflyMatrix3Float(
124
+ -0.0668066264395785,
125
+ 0.431792064197595,
126
+ 0.899495685348041,
127
+ -0.98941528906399,
128
+ -0.145060537051883,
129
+ -0.00385050082983023,
130
+ 0.128818711490931,
131
+ -0.890232022500988,
132
+ 0.43691267512355,
133
+ ),
134
+ position: positionKEYW,
135
+ heading: 0,
136
+ },
137
+ {
138
+ orientation: new AeroflyMatrix3Float(
139
+ 0.985978516472605,
140
+ 0.166832368887515,
141
+ -0.00365044461148948,
142
+ -0.066064640816506,
143
+ 0.41034317377044,
144
+ 0.90953501470465,
145
+ 0.153237816116869,
146
+ -0.896540819166301,
147
+ 0.41561127424596,
148
+ ),
149
+ position: positionKEYW,
150
+ heading: 90,
151
+ },
152
+
153
+ {
154
+ orientation: new AeroflyMatrix3Float(
155
+ -0.465135059130883,
156
+ -0.885151853036744,
157
+ 0.0124729239927332,
158
+ -0.489418463305539,
159
+ 0.268872261996669,
160
+ 0.829564508946978,
161
+ -0.737644185595572,
162
+ 0.379755057628484,
163
+ -0.558271575187768,
164
+ ),
165
+ position: positionYSSY,
166
+ heading: 90,
167
+ },
88
168
  ];
89
- const expectedHeadingDegree = 117.3585;
90
169
 
91
- const actualHeadingDegree = convertMatrixToDegree(orientationMatrix);
92
- assert.strictEqual(
93
- actualHeadingDegree.toFixed(4),
94
- expectedHeadingDegree.toFixed(4),
95
- `Expected heading degree to be ${expectedHeadingDegree.toFixed(4)}, got ${actualHeadingDegree.toFixed(4)}`,
96
- );
170
+ for (const testCase of testCases) {
171
+ const calculatedOrientation = convertHeadingToOrientation(testCase.heading, testCase.position);
172
+ const calculatedHeading = convertOrientationToHeading(calculatedOrientation, testCase.position);
173
+
174
+ assert.strictEqual(calculatedHeading, testCase.heading);
175
+ }
97
176
  });
98
177
  });