@horizon36596/zenith-core 0.1.1

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 (244) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +18 -0
  3. package/README.md +16 -0
  4. package/dist/canonicalize.d.ts +25 -0
  5. package/dist/canonicalize.d.ts.map +1 -0
  6. package/dist/canonicalize.js +199 -0
  7. package/dist/canonicalize.js.map +1 -0
  8. package/dist/check.d.ts +26 -0
  9. package/dist/check.d.ts.map +1 -0
  10. package/dist/check.js +231 -0
  11. package/dist/check.js.map +1 -0
  12. package/dist/checks/heading.d.ts +17 -0
  13. package/dist/checks/heading.d.ts.map +1 -0
  14. package/dist/checks/heading.js +78 -0
  15. package/dist/checks/heading.js.map +1 -0
  16. package/dist/checks/intake.d.ts +28 -0
  17. package/dist/checks/intake.d.ts.map +1 -0
  18. package/dist/checks/intake.js +131 -0
  19. package/dist/checks/intake.js.map +1 -0
  20. package/dist/checks/motion.d.ts +28 -0
  21. package/dist/checks/motion.d.ts.map +1 -0
  22. package/dist/checks/motion.js +252 -0
  23. package/dist/checks/motion.js.map +1 -0
  24. package/dist/checks/schedule.d.ts +29 -0
  25. package/dist/checks/schedule.d.ts.map +1 -0
  26. package/dist/checks/schedule.js +166 -0
  27. package/dist/checks/schedule.js.map +1 -0
  28. package/dist/checks/season.d.ts +6 -0
  29. package/dist/checks/season.d.ts.map +1 -0
  30. package/dist/checks/season.js +126 -0
  31. package/dist/checks/season.js.map +1 -0
  32. package/dist/continuity.d.ts +38 -0
  33. package/dist/continuity.d.ts.map +1 -0
  34. package/dist/continuity.js +69 -0
  35. package/dist/continuity.js.map +1 -0
  36. package/dist/diff.d.ts +37 -0
  37. package/dist/diff.d.ts.map +1 -0
  38. package/dist/diff.js +258 -0
  39. package/dist/diff.js.map +1 -0
  40. package/dist/edit/command.d.ts +4 -0
  41. package/dist/edit/command.d.ts.map +1 -0
  42. package/dist/edit/command.js +16 -0
  43. package/dist/edit/command.js.map +1 -0
  44. package/dist/edit/errors.d.ts +9 -0
  45. package/dist/edit/errors.d.ts.map +1 -0
  46. package/dist/edit/errors.js +12 -0
  47. package/dist/edit/errors.js.map +1 -0
  48. package/dist/edit/fields.d.ts +40 -0
  49. package/dist/edit/fields.d.ts.map +1 -0
  50. package/dist/edit/fields.js +150 -0
  51. package/dist/edit/fields.js.map +1 -0
  52. package/dist/edit/finish.d.ts +15 -0
  53. package/dist/edit/finish.d.ts.map +1 -0
  54. package/dist/edit/finish.js +36 -0
  55. package/dist/edit/finish.js.map +1 -0
  56. package/dist/edit/groups.d.ts +66 -0
  57. package/dist/edit/groups.d.ts.map +1 -0
  58. package/dist/edit/groups.js +277 -0
  59. package/dist/edit/groups.js.map +1 -0
  60. package/dist/edit/ids.d.ts +39 -0
  61. package/dist/edit/ids.d.ts.map +1 -0
  62. package/dist/edit/ids.js +76 -0
  63. package/dist/edit/ids.js.map +1 -0
  64. package/dist/edit/index.d.ts +22 -0
  65. package/dist/edit/index.d.ts.map +1 -0
  66. package/dist/edit/index.js +22 -0
  67. package/dist/edit/index.js.map +1 -0
  68. package/dist/edit/meta.d.ts +15 -0
  69. package/dist/edit/meta.d.ts.map +1 -0
  70. package/dist/edit/meta.js +13 -0
  71. package/dist/edit/meta.js.map +1 -0
  72. package/dist/edit/path.d.ts +36 -0
  73. package/dist/edit/path.d.ts.map +1 -0
  74. package/dist/edit/path.js +135 -0
  75. package/dist/edit/path.js.map +1 -0
  76. package/dist/edit/steps.d.ts +53 -0
  77. package/dist/edit/steps.d.ts.map +1 -0
  78. package/dist/edit/steps.js +0 -0
  79. package/dist/edit/steps.js.map +1 -0
  80. package/dist/edit/template.d.ts +18 -0
  81. package/dist/edit/template.d.ts.map +1 -0
  82. package/dist/edit/template.js +30 -0
  83. package/dist/edit/template.js.map +1 -0
  84. package/dist/edit/timing.d.ts +11 -0
  85. package/dist/edit/timing.d.ts.map +1 -0
  86. package/dist/edit/timing.js +23 -0
  87. package/dist/edit/timing.js.map +1 -0
  88. package/dist/edit/tree.d.ts +32 -0
  89. package/dist/edit/tree.d.ts.map +1 -0
  90. package/dist/edit/tree.js +90 -0
  91. package/dist/edit/tree.js.map +1 -0
  92. package/dist/estimate.d.ts +48 -0
  93. package/dist/estimate.d.ts.map +1 -0
  94. package/dist/estimate.js +443 -0
  95. package/dist/estimate.js.map +1 -0
  96. package/dist/findingHelp.d.ts +18 -0
  97. package/dist/findingHelp.d.ts.map +1 -0
  98. package/dist/findingHelp.js +114 -0
  99. package/dist/findingHelp.js.map +1 -0
  100. package/dist/fix.d.ts +21 -0
  101. package/dist/fix.d.ts.map +1 -0
  102. package/dist/fix.js +180 -0
  103. package/dist/fix.js.map +1 -0
  104. package/dist/footprint.d.ts +33 -0
  105. package/dist/footprint.d.ts.map +1 -0
  106. package/dist/footprint.js +71 -0
  107. package/dist/footprint.js.map +1 -0
  108. package/dist/geometry/angle.d.ts +13 -0
  109. package/dist/geometry/angle.d.ts.map +1 -0
  110. package/dist/geometry/angle.js +21 -0
  111. package/dist/geometry/angle.js.map +1 -0
  112. package/dist/geometry/curve.d.ts +24 -0
  113. package/dist/geometry/curve.d.ts.map +1 -0
  114. package/dist/geometry/curve.js +78 -0
  115. package/dist/geometry/curve.js.map +1 -0
  116. package/dist/geometry/path.d.ts +29 -0
  117. package/dist/geometry/path.d.ts.map +1 -0
  118. package/dist/geometry/path.js +61 -0
  119. package/dist/geometry/path.js.map +1 -0
  120. package/dist/geometry/quadrature.d.ts +13 -0
  121. package/dist/geometry/quadrature.d.ts.map +1 -0
  122. package/dist/geometry/quadrature.js +57 -0
  123. package/dist/geometry/quadrature.js.map +1 -0
  124. package/dist/geometry/sat.d.ts +40 -0
  125. package/dist/geometry/sat.d.ts.map +1 -0
  126. package/dist/geometry/sat.js +86 -0
  127. package/dist/geometry/sat.js.map +1 -0
  128. package/dist/geometry/vec.d.ts +27 -0
  129. package/dist/geometry/vec.d.ts.map +1 -0
  130. package/dist/geometry/vec.js +30 -0
  131. package/dist/geometry/vec.js.map +1 -0
  132. package/dist/heading.d.ts +77 -0
  133. package/dist/heading.d.ts.map +1 -0
  134. package/dist/heading.js +164 -0
  135. package/dist/heading.js.map +1 -0
  136. package/dist/headingRanges.d.ts +48 -0
  137. package/dist/headingRanges.d.ts.map +1 -0
  138. package/dist/headingRanges.js +132 -0
  139. package/dist/headingRanges.js.map +1 -0
  140. package/dist/index.d.ts +41 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +41 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/kinematics.d.ts +63 -0
  145. package/dist/kinematics.d.ts.map +1 -0
  146. package/dist/kinematics.js +71 -0
  147. package/dist/kinematics.js.map +1 -0
  148. package/dist/ledger.d.ts +49 -0
  149. package/dist/ledger.d.ts.map +1 -0
  150. package/dist/ledger.js +136 -0
  151. package/dist/ledger.js.map +1 -0
  152. package/dist/load.d.ts +12 -0
  153. package/dist/load.d.ts.map +1 -0
  154. package/dist/load.js +12 -0
  155. package/dist/load.js.map +1 -0
  156. package/dist/mirror.d.ts +81 -0
  157. package/dist/mirror.d.ts.map +1 -0
  158. package/dist/mirror.js +282 -0
  159. package/dist/mirror.js.map +1 -0
  160. package/dist/plan.d.ts +29 -0
  161. package/dist/plan.d.ts.map +1 -0
  162. package/dist/plan.js +159 -0
  163. package/dist/plan.js.map +1 -0
  164. package/dist/prBody.d.ts +24 -0
  165. package/dist/prBody.d.ts.map +1 -0
  166. package/dist/prBody.js +112 -0
  167. package/dist/prBody.js.map +1 -0
  168. package/dist/provenance.d.ts +21 -0
  169. package/dist/provenance.d.ts.map +1 -0
  170. package/dist/provenance.js +46 -0
  171. package/dist/provenance.js.map +1 -0
  172. package/dist/render.d.ts +18 -0
  173. package/dist/render.d.ts.map +1 -0
  174. package/dist/render.js +464 -0
  175. package/dist/render.js.map +1 -0
  176. package/dist/resolve.d.ts +39 -0
  177. package/dist/resolve.d.ts.map +1 -0
  178. package/dist/resolve.js +172 -0
  179. package/dist/resolve.js.map +1 -0
  180. package/dist/season.d.ts +65 -0
  181. package/dist/season.d.ts.map +1 -0
  182. package/dist/season.js +16 -0
  183. package/dist/season.js.map +1 -0
  184. package/dist/sim/commands.d.ts +97 -0
  185. package/dist/sim/commands.d.ts.map +1 -0
  186. package/dist/sim/commands.js +185 -0
  187. package/dist/sim/commands.js.map +1 -0
  188. package/dist/sim/curves.d.ts +37 -0
  189. package/dist/sim/curves.d.ts.map +1 -0
  190. package/dist/sim/curves.js +187 -0
  191. package/dist/sim/curves.js.map +1 -0
  192. package/dist/sim/follower.d.ts +124 -0
  193. package/dist/sim/follower.d.ts.map +1 -0
  194. package/dist/sim/follower.js +472 -0
  195. package/dist/sim/follower.js.map +1 -0
  196. package/dist/sim/ideal.d.ts +103 -0
  197. package/dist/sim/ideal.d.ts.map +1 -0
  198. package/dist/sim/ideal.js +393 -0
  199. package/dist/sim/ideal.js.map +1 -0
  200. package/dist/sim/index.d.ts +11 -0
  201. package/dist/sim/index.d.ts.map +1 -0
  202. package/dist/sim/index.js +10 -0
  203. package/dist/sim/index.js.map +1 -0
  204. package/dist/sim/params.d.ts +91 -0
  205. package/dist/sim/params.d.ts.map +1 -0
  206. package/dist/sim/params.js +195 -0
  207. package/dist/sim/params.js.map +1 -0
  208. package/dist/sim/pedroPath.d.ts +41 -0
  209. package/dist/sim/pedroPath.d.ts.map +1 -0
  210. package/dist/sim/pedroPath.js +191 -0
  211. package/dist/sim/pedroPath.js.map +1 -0
  212. package/dist/sim/plant.d.ts +59 -0
  213. package/dist/sim/plant.d.ts.map +1 -0
  214. package/dist/sim/plant.js +128 -0
  215. package/dist/sim/plant.js.map +1 -0
  216. package/dist/sim/residuals.d.ts +36 -0
  217. package/dist/sim/residuals.d.ts.map +1 -0
  218. package/dist/sim/residuals.js +86 -0
  219. package/dist/sim/residuals.js.map +1 -0
  220. package/dist/sim/simulate.d.ts +27 -0
  221. package/dist/sim/simulate.d.ts.map +1 -0
  222. package/dist/sim/simulate.js +924 -0
  223. package/dist/sim/simulate.js.map +1 -0
  224. package/dist/sim/types.d.ts +209 -0
  225. package/dist/sim/types.d.ts.map +1 -0
  226. package/dist/sim/types.js +2 -0
  227. package/dist/sim/types.js.map +1 -0
  228. package/dist/tokens.d.ts +93 -0
  229. package/dist/tokens.d.ts.map +1 -0
  230. package/dist/tokens.js +93 -0
  231. package/dist/tokens.js.map +1 -0
  232. package/dist/trace.d.ts +89 -0
  233. package/dist/trace.d.ts.map +1 -0
  234. package/dist/trace.js +187 -0
  235. package/dist/trace.js.map +1 -0
  236. package/dist/types.d.ts +219 -0
  237. package/dist/types.d.ts.map +1 -0
  238. package/dist/types.js +2 -0
  239. package/dist/types.js.map +1 -0
  240. package/dist/unimplemented.d.ts +8 -0
  241. package/dist/unimplemented.d.ts.map +1 -0
  242. package/dist/unimplemented.js +11 -0
  243. package/dist/unimplemented.js.map +1 -0
  244. package/package.json +59 -0
@@ -0,0 +1,393 @@
1
+ import { integrateProfile } from "../estimate.js";
2
+ import { angleDelta, wrapAngle } from "../geometry/angle.js";
3
+ import { distance } from "../geometry/vec.js";
4
+ import { headingFunction } from "../heading.js";
5
+ import { decelInPerS2, robotLimits, velocityCapInPerS } from "../kinematics.js";
6
+ import { containsPath } from "../resolve.js";
7
+ /**
8
+ * The ideal playback level (site/docs/simulation.md, "Playback levels"): the robot follows the
9
+ * planned geometry exactly, with no wobble and no overshoot, and its heading is the heading
10
+ * interpolation exactly, the way the public Pedro visualizer draws a path. The clock is the one the
11
+ * timeline already uses, the kinematic estimate (`estimate.ts`), so a path step drives along its
12
+ * samples at `timeAtSampleS` and then holds its end pose for the settle time the estimate adds.
13
+ *
14
+ * The one thing the estimate does not time is a gap: a step that starts somewhere other than where
15
+ * the robot is, or facing another way (a literal `from`, or a heading mode whose first heading is
16
+ * not the last one). The robot has to get there, so the ideal robot does, visibly: a transition that
17
+ * turns and drives in a straight line from the pose it has to the pose the next path starts at,
18
+ * timed with the same kinematic model (the same caps, acceleration and deceleration as a path
19
+ * step, from rest to rest). A transition therefore makes the ideal run longer than the estimate by
20
+ * exactly its own duration.
21
+ *
22
+ * A wait or a command holds the pose for its estimated seconds, as the time model does. A parallel
23
+ * group follows the member that drives (its deadline when that drives, else the last member with a
24
+ * path, the same member the estimate carries the velocity through) for as long as the group lasts;
25
+ * a branch drives its `then` side, the side the instant sim takes when it cannot read the
26
+ * condition, and lasts as long as the estimate says (the longer side).
27
+ *
28
+ * Pure and deterministic, like the rest of core: the same plan and estimate give the same poses.
29
+ */
30
+ /** Position gaps below this are the same place, in inches: canonical form rounds to 1e-4. */
31
+ export const IDEAL_POSITION_TOLERANCE_IN = 0.01;
32
+ /** Heading gaps below this are the same heading, in radians. */
33
+ export const IDEAL_HEADING_TOLERANCE_RAD = 1e-3;
34
+ /** Spacing of the profile samples along a transition, in inches, the same as a path's. */
35
+ const TRANSITION_SPACING_IN = 2;
36
+ /** True when the robot has to move or turn to get from one pose to the other. */
37
+ export function posesDiffer(a, b) {
38
+ return (distance(a, b) > IDEAL_POSITION_TOLERANCE_IN ||
39
+ Math.abs(angleDelta(a.headingRad, b.headingRad)) > IDEAL_HEADING_TOLERANCE_RAD);
40
+ }
41
+ /**
42
+ * The seconds and the profile of a straight transition. A pure turn is timed at the robot's
43
+ * angular velocity limit. A move samples the line every 2 in, turns the heading evenly with the
44
+ * distance, caps each sample by the velocity ellipse at the default speed fraction and by the
45
+ * heading rate, and integrates from rest to rest with the estimate's own two-pass profile.
46
+ */
47
+ function transitionProfile(from, to, limits) {
48
+ const translateIn = distance(from, to);
49
+ const turnRad = angleDelta(from.headingRad, to.headingRad);
50
+ if (translateIn <= IDEAL_POSITION_TOLERANCE_IN) {
51
+ const seconds = limits.maxAngularVelRadPerS > 0 ? Math.abs(turnRad) / limits.maxAngularVelRadPerS : 0;
52
+ return { translateIn: 0, turnRad, sIns: [0, 0], timesS: [0, seconds] };
53
+ }
54
+ const sIns = [];
55
+ for (let s = 0; s < translateIn; s += TRANSITION_SPACING_IN)
56
+ sIns.push(s);
57
+ sIns.push(translateIn);
58
+ const travelRad = Math.atan2(to.yIn - from.yIn, to.xIn - from.xIn);
59
+ const headingRatePerIn = Math.abs(turnRad) / translateIn;
60
+ const samples = sIns.map((sIn) => {
61
+ const headingRad = wrapAngle(from.headingRad + turnRad * (sIn / translateIn));
62
+ const phiRad = wrapAngle(travelRad - headingRad);
63
+ let capInPerS = limits.defaultPathSpeedFraction * velocityCapInPerS(limits, phiRad);
64
+ if (headingRatePerIn > 1e-9)
65
+ capInPerS = Math.min(capInPerS, limits.maxAngularVelRadPerS / headingRatePerIn);
66
+ return { sIn, phiRad, capInPerS, decelInPerS2: decelInPerS2(limits, phiRad) };
67
+ });
68
+ const timing = integrateProfile(samples, limits, 0, 0);
69
+ return { translateIn, turnRad, sIns, timesS: timing.timeAtSampleS };
70
+ }
71
+ /**
72
+ * Lays the plan on the ideal clock. Throws nothing: a step without an estimate takes no time, the
73
+ * way it counts as zero in the estimate's total.
74
+ */
75
+ export function idealTrajectory(plan, estimate) {
76
+ const limits = robotLimits(plan.robot);
77
+ const byId = estimate.byStepId;
78
+ const segments = [];
79
+ const spans = [];
80
+ const transitions = [];
81
+ const push = (segment) => {
82
+ if (segment.endS - segment.startS <= 0 && segment.kind !== "path")
83
+ return;
84
+ segments.push(segment);
85
+ };
86
+ const hold = (stepId, cursor, seconds) => {
87
+ if (seconds <= 0)
88
+ return;
89
+ push({ kind: "hold", stepId, startS: cursor.clockS, endS: cursor.clockS + seconds, pose: cursor.pose });
90
+ cursor.clockS += seconds;
91
+ };
92
+ /** Moves the cursor to `target` with a transition when it is not there already; returns its seconds. */
93
+ const transitionTo = (stepId, cursor, target) => {
94
+ if (!posesDiffer(cursor.pose, target)) {
95
+ cursor.pose = target;
96
+ return 0;
97
+ }
98
+ const profile = transitionProfile(cursor.pose, target, limits);
99
+ const seconds = profile.timesS[profile.timesS.length - 1] ?? 0;
100
+ const transition = {
101
+ kind: "transition",
102
+ stepId,
103
+ startS: cursor.clockS,
104
+ endS: cursor.clockS + seconds,
105
+ fromPose: cursor.pose,
106
+ toPose: target,
107
+ translateIn: profile.translateIn,
108
+ turnRad: profile.turnRad,
109
+ sIns: profile.sIns,
110
+ timesS: profile.timesS.map((at) => cursor.clockS + at),
111
+ };
112
+ transitions.push(transition);
113
+ push(transition);
114
+ cursor.clockS = transition.endS;
115
+ cursor.pose = target;
116
+ return seconds;
117
+ };
118
+ /**
119
+ * One step from the cursor. `record` is false for members whose motion is not the one drawn (the
120
+ * non-driving members of a parallel group, the `else` side of a branch): they are still timed, so
121
+ * their spans exist, but they add no segments and do not move the robot.
122
+ */
123
+ const walk = (step, cursor, record) => {
124
+ const startS = cursor.clockS;
125
+ const ownS = byId[step.id]?.nominalS ?? null;
126
+ let transitionS = 0;
127
+ if (step.kind === "path" && step.geometry !== undefined && step.samples.length >= 2) {
128
+ const pathStep = step.step;
129
+ if (record) {
130
+ transitionS += transitionTo(step.id, cursor, step.startPose);
131
+ }
132
+ else if (posesDiffer(cursor.pose, step.startPose)) {
133
+ transitionS += transitionProfileSeconds(cursor.pose, step.startPose, limits);
134
+ cursor.clockS += transitionS;
135
+ }
136
+ const atSample = byId[step.id]?.timeAtSampleS;
137
+ const offsets = atSample !== undefined && atSample.length === step.samples.length
138
+ ? atSample
139
+ : step.samples.map((sample) => sample.t * Math.max(0, (ownS ?? 0) - limits.settleS));
140
+ const moveS = offsets[offsets.length - 1] ?? 0;
141
+ const motionStartS = cursor.clockS;
142
+ if (record) {
143
+ push({
144
+ kind: "path",
145
+ stepId: step.id,
146
+ startS: motionStartS,
147
+ endS: motionStartS + moveS,
148
+ step,
149
+ timesS: offsets.map((at) => motionStartS + at),
150
+ headingAt: pathStep.heading === undefined
151
+ ? () => step.startPose.headingRad
152
+ : headingFunction(pathStep.heading, step.geometry),
153
+ });
154
+ }
155
+ cursor.clockS = motionStartS + moveS;
156
+ cursor.pose = step.endPose ?? step.samples[step.samples.length - 1]?.pose ?? cursor.pose;
157
+ const settleS = Math.max(0, (ownS ?? moveS) - moveS);
158
+ if (record)
159
+ hold(step.id, cursor, settleS);
160
+ else
161
+ cursor.clockS += settleS;
162
+ }
163
+ else if (step.children !== undefined && step.children.length > 0) {
164
+ transitionS += walkGroup(step, cursor, record);
165
+ }
166
+ else {
167
+ // A wait, a command, or a path with nothing to drive: the robot holds where it is.
168
+ if (record)
169
+ hold(step.id, cursor, ownS ?? 0);
170
+ else
171
+ cursor.clockS += ownS ?? 0;
172
+ }
173
+ spans.push({ stepId: step.id, startS, endS: cursor.clockS, transitionS });
174
+ return transitionS;
175
+ };
176
+ const walkGroup = (step, cursor, record) => {
177
+ const children = step.children ?? [];
178
+ const startS = cursor.clockS;
179
+ const entry = cursor.pose;
180
+ const authored = step.step;
181
+ if (authored.kind === "sequence") {
182
+ let transitionS = 0;
183
+ for (const child of children)
184
+ transitionS += walk(child, cursor, record);
185
+ return transitionS;
186
+ }
187
+ if (authored.kind === "branch") {
188
+ const thenCount = authored.then.length;
189
+ const thenCursor = { clockS: startS, pose: entry };
190
+ let transitionS = 0;
191
+ for (const child of children.slice(0, thenCount))
192
+ transitionS += walk(child, thenCursor, record);
193
+ const elseCursor = { clockS: startS, pose: entry };
194
+ for (const child of children.slice(thenCount))
195
+ walk(child, elseCursor, false);
196
+ // The estimate costs a branch as its longer side; the ideal robot waits out the difference.
197
+ const endS = Math.max(thenCursor.clockS, elseCursor.clockS);
198
+ cursor.pose = thenCursor.pose;
199
+ cursor.clockS = thenCursor.clockS;
200
+ if (record)
201
+ hold(step.id, cursor, endS - thenCursor.clockS);
202
+ cursor.clockS = endS;
203
+ return transitionS;
204
+ }
205
+ // Parallel: every member starts together from the group's start; the driving one is drawn.
206
+ const group = authored;
207
+ const mover = children.find((child) => child.id === group.deadline && containsPath(child)) ??
208
+ [...children].reverse().find(containsPath);
209
+ const ends = new Map();
210
+ let transitionS = 0;
211
+ let moverCursor = null;
212
+ const moverSegments = [];
213
+ for (const child of children) {
214
+ const childCursor = { clockS: startS, pose: entry };
215
+ if (child === mover) {
216
+ const before = segments.length;
217
+ transitionS += walk(child, childCursor, record);
218
+ moverSegments.push(...segments.splice(before));
219
+ moverCursor = childCursor;
220
+ }
221
+ else {
222
+ walk(child, childCursor, false);
223
+ }
224
+ ends.set(child.id, childCursor.clockS);
225
+ }
226
+ const durations = [...ends.values()].map((endS) => endS - startS);
227
+ let groupS;
228
+ if (group.mode === "deadline" && ends.has(group.deadline ?? "")) {
229
+ groupS = ends.get(group.deadline ?? "") - startS;
230
+ }
231
+ else if (group.mode === "race") {
232
+ groupS = durations.length === 0 ? 0 : Math.min(...durations);
233
+ }
234
+ else {
235
+ groupS = durations.length === 0 ? 0 : Math.max(...durations);
236
+ }
237
+ const endS = startS + groupS;
238
+ if (!record) {
239
+ cursor.pose = moverCursor?.pose ?? entry;
240
+ cursor.clockS = endS;
241
+ return transitionS;
242
+ }
243
+ // The mover's motion, cut where the group ends (a race or a deadline can end it early).
244
+ let pose = entry;
245
+ for (const segment of moverSegments) {
246
+ if (segment.startS >= endS && segment.endS > segment.startS)
247
+ break;
248
+ if (segment.endS <= endS) {
249
+ segments.push(segment);
250
+ pose = segmentEndPose(segment);
251
+ }
252
+ else {
253
+ segments.push({ ...segment, endS });
254
+ pose = poseInSegment(segment, endS);
255
+ }
256
+ }
257
+ if (moverCursor !== null && moverCursor.clockS <= endS)
258
+ pose = moverCursor.pose;
259
+ const last = segments[segments.length - 1];
260
+ const lastS = last === undefined ? startS : Math.max(startS, last.endS);
261
+ cursor.pose = pose;
262
+ cursor.clockS = Math.min(lastS, endS);
263
+ hold(step.id, cursor, endS - cursor.clockS);
264
+ cursor.clockS = endS;
265
+ return transitionS;
266
+ };
267
+ const cursor = { clockS: 0, pose: plan.startPose };
268
+ for (const step of plan.steps)
269
+ walk(step, cursor, true);
270
+ return { startPose: plan.startPose, segments, spans, transitions, totalS: cursor.clockS };
271
+ }
272
+ /** The seconds a transition would take, for a member that is timed but not drawn. */
273
+ function transitionProfileSeconds(from, to, limits) {
274
+ const profile = transitionProfile(from, to, limits);
275
+ return profile.timesS[profile.timesS.length - 1] ?? 0;
276
+ }
277
+ /** Where a segment leaves the robot at its natural end. */
278
+ function segmentEndPose(segment) {
279
+ switch (segment.kind) {
280
+ case "hold":
281
+ return segment.pose;
282
+ case "transition":
283
+ return segment.toPose;
284
+ case "path":
285
+ return poseInSegment(segment, segment.endS);
286
+ }
287
+ }
288
+ /** Linear interpolation of a clock series: the index before `atS` and the fraction past it. */
289
+ function locate(timesS, atS) {
290
+ const count = timesS.length;
291
+ if (count < 2 || atS <= timesS[0])
292
+ return { index: 0, u: 0 };
293
+ if (atS >= timesS[count - 1])
294
+ return { index: Math.max(0, count - 2), u: 1 };
295
+ let lo = 0;
296
+ let hi = count - 1;
297
+ while (hi - lo > 1) {
298
+ const mid = (lo + hi) >> 1;
299
+ if (timesS[mid] <= atS)
300
+ lo = mid;
301
+ else
302
+ hi = mid;
303
+ }
304
+ const ta = timesS[lo];
305
+ const tb = timesS[hi];
306
+ return { index: lo, u: tb - ta <= 1e-12 ? 1 : (atS - ta) / (tb - ta) };
307
+ }
308
+ /** The pose inside one segment at a routine time, clamped to the segment. */
309
+ function poseInSegment(segment, atS) {
310
+ if (segment.kind === "hold")
311
+ return segment.pose;
312
+ if (segment.kind === "transition") {
313
+ if (segment.translateIn === 0) {
314
+ const start = segment.timesS[0];
315
+ const end = segment.timesS[segment.timesS.length - 1];
316
+ const u = end - start <= 1e-12 ? 1 : Math.min(1, Math.max(0, (atS - start) / (end - start)));
317
+ return {
318
+ xIn: segment.toPose.xIn,
319
+ yIn: segment.toPose.yIn,
320
+ headingRad: wrapAngle(segment.fromPose.headingRad + segment.turnRad * u),
321
+ };
322
+ }
323
+ const { index, u } = locate(segment.timesS, atS);
324
+ const sa = segment.sIns[index];
325
+ const sb = segment.sIns[Math.min(index + 1, segment.sIns.length - 1)];
326
+ const f = (sa + (sb - sa) * u) / segment.translateIn;
327
+ return {
328
+ xIn: segment.fromPose.xIn + (segment.toPose.xIn - segment.fromPose.xIn) * f,
329
+ yIn: segment.fromPose.yIn + (segment.toPose.yIn - segment.fromPose.yIn) * f,
330
+ headingRad: wrapAngle(segment.fromPose.headingRad + segment.turnRad * f),
331
+ };
332
+ }
333
+ const { step, timesS } = segment;
334
+ const geometry = step.geometry;
335
+ if (geometry === undefined)
336
+ return step.startPose;
337
+ const { index, u } = locate(timesS, atS);
338
+ const sa = step.samples[index].sIn;
339
+ const sb = step.samples[Math.min(index + 1, step.samples.length - 1)].sIn;
340
+ const sIn = sa + (sb - sa) * u;
341
+ const point = geometry.pointAtDistance(sIn);
342
+ return { xIn: point.xIn, yIn: point.yIn, headingRad: segment.headingAt(geometry.tAtDistance(sIn)) };
343
+ }
344
+ /**
345
+ * The ideal robot's pose at a routine time: on the planned path exactly while a path runs, on the
346
+ * straight line of a transition while it closes a gap, and still otherwise. Before 0 it is at the
347
+ * start pose, and after the end at the last pose.
348
+ */
349
+ export function idealPoseAt(trajectory, atS) {
350
+ const segments = trajectory.segments;
351
+ if (segments.length === 0)
352
+ return trajectory.startPose;
353
+ const first = segments[0];
354
+ if (atS <= first.startS)
355
+ return poseInSegment(first, first.startS);
356
+ let lo = 0;
357
+ let hi = segments.length - 1;
358
+ if (atS >= segments[hi].startS)
359
+ return poseInSegment(segments[hi], atS);
360
+ while (hi - lo > 1) {
361
+ const mid = (lo + hi) >> 1;
362
+ if (segments[mid].startS <= atS)
363
+ lo = mid;
364
+ else
365
+ hi = mid;
366
+ }
367
+ return poseInSegment(segments[lo], atS);
368
+ }
369
+ /**
370
+ * The ideal clock when the robot reaches arc-length fraction `t` of a path step, or null when the
371
+ * step is not driven on the ideal run (a member that is timed but not drawn).
372
+ */
373
+ export function idealTimeAt(trajectory, stepId, t) {
374
+ const motion = trajectory.segments.find((segment) => segment.kind === "path" && segment.stepId === stepId);
375
+ if (motion === undefined)
376
+ return null;
377
+ const { step, timesS } = motion;
378
+ const sIn = step.lengthIn * Math.min(1, Math.max(0, t));
379
+ const count = Math.min(step.samples.length, timesS.length);
380
+ if (count === 0)
381
+ return null;
382
+ for (let index = 0; index + 1 < count; index += 1) {
383
+ const sa = step.samples[index].sIn;
384
+ const sb = step.samples[index + 1].sIn;
385
+ if (sIn <= sb) {
386
+ const u = sb - sa <= 1e-12 ? 0 : (sIn - sa) / (sb - sa);
387
+ const ta = timesS[index];
388
+ return ta + (timesS[index + 1] - ta) * u;
389
+ }
390
+ }
391
+ return timesS[count - 1];
392
+ }
393
+ //# sourceMappingURL=ideal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ideal.js","sourceRoot":"","sources":["../../src/sim/ideal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The instant sim's public surface, and the ideal playback level beside it (`ideal.ts`). The
3
+ * follower, the plant and the command ports stay internal: callers get traces, the parameters the
4
+ * sim resolved, and the comparison with a Gradle run.
5
+ */
6
+ export { simulate, simulateRun, resimulate, simPoseAt } from "./simulate.js";
7
+ export { idealTrajectory, idealPoseAt, idealTimeAt, posesDiffer as idealPosesDiffer, IDEAL_POSITION_TOLERANCE_IN, IDEAL_HEADING_TOLERANCE_RAD, type IdealHold, type IdealPathMotion, type IdealSegment, type IdealSpan, type IdealTrajectory, type IdealTransition, } from "./ideal.js";
8
+ export { simResiduals, type SimResiduals, type StepResidual } from "./residuals.js";
9
+ export { followerParams as simFollowerParams, plantParams as simPlantParams, PEDRO_DEFAULTS, DEFAULT_TICK_S as SIM_DEFAULT_TICK_S, GRADLE_TICK_S as SIM_GRADLE_TICK_S, } from "./params.js";
10
+ export type { ConditionQuery, ConditionResolver, CoastModel, FollowerParams, PlantParams, SimCheckpoint, SimEvent, SimFidelity, SimOptions, SimRun, SimStepRecord, SimTrace, TraceVelocityRow, } from "./types.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sim/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,IAAI,gBAAgB,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,cAAc,IAAI,iBAAiB,EACnC,WAAW,IAAI,cAAc,EAC7B,cAAc,EACd,cAAc,IAAI,kBAAkB,EACpC,aAAa,IAAI,iBAAiB,GACnC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,QAAQ,EACR,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,QAAQ,EACR,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The instant sim's public surface, and the ideal playback level beside it (`ideal.ts`). The
3
+ * follower, the plant and the command ports stay internal: callers get traces, the parameters the
4
+ * sim resolved, and the comparison with a Gradle run.
5
+ */
6
+ export { simulate, simulateRun, resimulate, simPoseAt } from "./simulate.js";
7
+ export { idealTrajectory, idealPoseAt, idealTimeAt, posesDiffer as idealPosesDiffer, IDEAL_POSITION_TOLERANCE_IN, IDEAL_HEADING_TOLERANCE_RAD, } from "./ideal.js";
8
+ export { simResiduals } from "./residuals.js";
9
+ export { followerParams as simFollowerParams, plantParams as simPlantParams, PEDRO_DEFAULTS, DEFAULT_TICK_S as SIM_DEFAULT_TICK_S, GRADLE_TICK_S as SIM_GRADLE_TICK_S, } from "./params.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sim/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,IAAI,gBAAgB,EAC/B,2BAA2B,EAC3B,2BAA2B,GAO5B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAwC,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,cAAc,IAAI,iBAAiB,EACnC,WAAW,IAAI,cAAc,EAC7B,cAAc,EACd,cAAc,IAAI,kBAAkB,EACpC,aAAa,IAAI,iBAAiB,GACnC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { Field, Robot } from "@horizon36596/zenith-schema";
2
+ import type { FollowerParams, PlantParams, SimFidelity, SimOptions } from "./types.js";
3
+ /**
4
+ * Where every number the instant sim runs on comes from, in one place, with the order of
5
+ * preference stated: the caller's `options`, then `robot.json`, then a default. Each default is
6
+ * either Pedro Pathing v3's own `ForesightConfig` default (read from the pinned sources jar, see
7
+ * site/docs/simulation.md) or derived from a number `robot.json` already carries, and
8
+ * says which. None is a number made up for the purpose (CLAUDE.md rule 4).
9
+ *
10
+ * The follower gains, the drivetrain geometry and each condition's `ledger` meaning are optional
11
+ * keys in `robot.json` (`followerSchema` and `drivetrainSchema` in `packages/schema/src/robot.ts`,
12
+ * site/docs/file-format.md). This file still reads them structurally, so a key the schema adds
13
+ * later takes effect without a change here.
14
+ */
15
+ /** The default tick for the preview, in seconds. */
16
+ export declare const DEFAULT_TICK_S = 0.01;
17
+ /** SimLoop's `HeadlessOpModeRunner.TICK_SECONDS`: a Gradle headless sim's 50 Hz loop. */
18
+ export declare const GRADLE_TICK_S = 0.02;
19
+ /**
20
+ * Seconds the sim runs past the auto period before it gives up on a routine that has not finished:
21
+ * the same margin a Gradle headless sim gives a 30 s period (1700 ticks of 0.02 s is 34 s).
22
+ */
23
+ export declare const PERIOD_MARGIN_S = 4;
24
+ /** When the field declares no auto period, the sim stops here. FTC's auto period is 30 s. */
25
+ export declare const DEFAULT_PERIOD_S = 30;
26
+ /** SimLoop's `FakeMotor.EPS`. */
27
+ export declare const STOP_SNAP_FRACTION = 0.02;
28
+ /** `MecanumConfig.powerThreshold`'s default in Pedro's revhub. */
29
+ export declare const POWER_THRESHOLD = 0.01;
30
+ /**
31
+ * Pedro's `ForesightConfig` defaults, for the knobs Pedro gives a default to. SPEC: copied from
32
+ * `com/pedropathing/algorithm/ForesightConfig.java` in core-3.0.0-20260828.185437-17.
33
+ */
34
+ export declare const PEDRO_DEFAULTS: {
35
+ readonly headingPowerPerRad: 1.5;
36
+ readonly headingStaticPower: 0;
37
+ readonly forwardTranslationalPowerPerIn: 0.07;
38
+ readonly strafeTranslationalPowerPerIn: 0.1;
39
+ readonly brakeFeedforwardPowerPerInPerS: 0.009;
40
+ readonly coastPowerPerInPerS: 0.025;
41
+ readonly coastFeedforwardPowerPerInPerS: 0.015;
42
+ readonly maxBrakingPower: 0.2;
43
+ readonly headingDriveRatio: 0.5;
44
+ readonly cosineScale: true;
45
+ readonly turnBeforeDriving: false;
46
+ readonly brakeAggression: 1;
47
+ readonly endParametricT: 0.025;
48
+ readonly endHeadingToleranceRad: 0.007;
49
+ readonly endTranslationalToleranceIn: 0.1;
50
+ readonly endVelocityToleranceInPerS: 0.1;
51
+ readonly holdTimeoutS: 0.1;
52
+ readonly headingDeviationToleranceRad: number;
53
+ readonly translationalDeviationToleranceIn: 2.5;
54
+ readonly minCorrectionDistanceIn: 0.001;
55
+ };
56
+ /**
57
+ * The follower the sim runs. Pedro's defaults except where a Pedro default would make the preview
58
+ * meaningless for any robot that has not been tuned, and there the value is derived:
59
+ *
60
+ * - `coastFeedforwardPowerPerInPerS` defaults to 1 / maxForwardVel, the power that holds a target
61
+ * velocity on this robot's measured top speed (a robot with a 100 in/s top speed gets 0.01).
62
+ * Pedro's 0.015 would push past full power at any target, so `speedFraction` would do nothing.
63
+ * - `coastPowerPerInPerS` defaults to 0 for the same reason: V3 feeds the coast controller the
64
+ * target velocity as its "error", so a P term there is a second feedforward.
65
+ * - The brake coefficients, which Pedro makes `required()` and so has no default for, come from the
66
+ * measured coasting deceleration: stopping distance v^2 / 2a, linear term 0. APPROX: the real
67
+ * coefficients come from Pedro's braking identification OpModes and are shorter, because they
68
+ * brake under reverse power rather than coast.
69
+ */
70
+ export declare function followerParams(robot: Robot, options?: SimOptions): FollowerParams;
71
+ /**
72
+ * The mecanum lever arm: half the wheel base plus half the track width from
73
+ * `kinematics.drivetrain` when the file carries them, otherwise the arm that makes a full turn
74
+ * command reach `maxAngularVelRadPerS`, so the plant's angular limit is the one `robot.json` states.
75
+ */
76
+ export declare function plantLeverArmIn(robot: Robot): number;
77
+ /**
78
+ * The plant. The wheel response rate is `kinematics.drivetrain.wheelResponseRatePerS` when present
79
+ * (a robot's own Gradle sim sets the same rate), otherwise 2 * accel / maxForwardVel:
80
+ * the rate at which a first-order wheel loses the same time to reaching top speed, V / (2a), as the
81
+ * constant-acceleration estimate does, so the two agree about what `accelInPerS2` means.
82
+ */
83
+ export declare function plantParams(robot: Robot, field: Field, fidelity: SimFidelity, options?: SimOptions): PlantParams;
84
+ /** The tick, the fidelity and the stopping time, resolved. */
85
+ export declare function runParams(field: Field, options: SimOptions): {
86
+ tickS: number;
87
+ fidelity: SimFidelity;
88
+ maxTimeS: number;
89
+ periodS: number | null;
90
+ };
91
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/sim/params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvF;;;;;;;;;;;GAWG;AAEH,oDAAoD;AACpD,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,yFAAyF;AACzF,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,iCAAiC;AACjC,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,kEAAkE;AAClE,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;CAqBjB,CAAC;AA+BX;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,UAAe,GAAG,cAAc,CAiErF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAQpD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,UAAe,GACvB,WAAW,CAkBb;AAWD,8DAA8D;AAC9D,wBAAgB,SAAS,CACvB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,UAAU,GAClB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAOpF"}