@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.
- package/LICENSE +21 -0
- package/NOTICE +18 -0
- package/README.md +16 -0
- package/dist/canonicalize.d.ts +25 -0
- package/dist/canonicalize.d.ts.map +1 -0
- package/dist/canonicalize.js +199 -0
- package/dist/canonicalize.js.map +1 -0
- package/dist/check.d.ts +26 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +231 -0
- package/dist/check.js.map +1 -0
- package/dist/checks/heading.d.ts +17 -0
- package/dist/checks/heading.d.ts.map +1 -0
- package/dist/checks/heading.js +78 -0
- package/dist/checks/heading.js.map +1 -0
- package/dist/checks/intake.d.ts +28 -0
- package/dist/checks/intake.d.ts.map +1 -0
- package/dist/checks/intake.js +131 -0
- package/dist/checks/intake.js.map +1 -0
- package/dist/checks/motion.d.ts +28 -0
- package/dist/checks/motion.d.ts.map +1 -0
- package/dist/checks/motion.js +252 -0
- package/dist/checks/motion.js.map +1 -0
- package/dist/checks/schedule.d.ts +29 -0
- package/dist/checks/schedule.d.ts.map +1 -0
- package/dist/checks/schedule.js +166 -0
- package/dist/checks/schedule.js.map +1 -0
- package/dist/checks/season.d.ts +6 -0
- package/dist/checks/season.d.ts.map +1 -0
- package/dist/checks/season.js +126 -0
- package/dist/checks/season.js.map +1 -0
- package/dist/continuity.d.ts +38 -0
- package/dist/continuity.d.ts.map +1 -0
- package/dist/continuity.js +69 -0
- package/dist/continuity.js.map +1 -0
- package/dist/diff.d.ts +37 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +258 -0
- package/dist/diff.js.map +1 -0
- package/dist/edit/command.d.ts +4 -0
- package/dist/edit/command.d.ts.map +1 -0
- package/dist/edit/command.js +16 -0
- package/dist/edit/command.js.map +1 -0
- package/dist/edit/errors.d.ts +9 -0
- package/dist/edit/errors.d.ts.map +1 -0
- package/dist/edit/errors.js +12 -0
- package/dist/edit/errors.js.map +1 -0
- package/dist/edit/fields.d.ts +40 -0
- package/dist/edit/fields.d.ts.map +1 -0
- package/dist/edit/fields.js +150 -0
- package/dist/edit/fields.js.map +1 -0
- package/dist/edit/finish.d.ts +15 -0
- package/dist/edit/finish.d.ts.map +1 -0
- package/dist/edit/finish.js +36 -0
- package/dist/edit/finish.js.map +1 -0
- package/dist/edit/groups.d.ts +66 -0
- package/dist/edit/groups.d.ts.map +1 -0
- package/dist/edit/groups.js +277 -0
- package/dist/edit/groups.js.map +1 -0
- package/dist/edit/ids.d.ts +39 -0
- package/dist/edit/ids.d.ts.map +1 -0
- package/dist/edit/ids.js +76 -0
- package/dist/edit/ids.js.map +1 -0
- package/dist/edit/index.d.ts +22 -0
- package/dist/edit/index.d.ts.map +1 -0
- package/dist/edit/index.js +22 -0
- package/dist/edit/index.js.map +1 -0
- package/dist/edit/meta.d.ts +15 -0
- package/dist/edit/meta.d.ts.map +1 -0
- package/dist/edit/meta.js +13 -0
- package/dist/edit/meta.js.map +1 -0
- package/dist/edit/path.d.ts +36 -0
- package/dist/edit/path.d.ts.map +1 -0
- package/dist/edit/path.js +135 -0
- package/dist/edit/path.js.map +1 -0
- package/dist/edit/steps.d.ts +53 -0
- package/dist/edit/steps.d.ts.map +1 -0
- package/dist/edit/steps.js +0 -0
- package/dist/edit/steps.js.map +1 -0
- package/dist/edit/template.d.ts +18 -0
- package/dist/edit/template.d.ts.map +1 -0
- package/dist/edit/template.js +30 -0
- package/dist/edit/template.js.map +1 -0
- package/dist/edit/timing.d.ts +11 -0
- package/dist/edit/timing.d.ts.map +1 -0
- package/dist/edit/timing.js +23 -0
- package/dist/edit/timing.js.map +1 -0
- package/dist/edit/tree.d.ts +32 -0
- package/dist/edit/tree.d.ts.map +1 -0
- package/dist/edit/tree.js +90 -0
- package/dist/edit/tree.js.map +1 -0
- package/dist/estimate.d.ts +48 -0
- package/dist/estimate.d.ts.map +1 -0
- package/dist/estimate.js +443 -0
- package/dist/estimate.js.map +1 -0
- package/dist/findingHelp.d.ts +18 -0
- package/dist/findingHelp.d.ts.map +1 -0
- package/dist/findingHelp.js +114 -0
- package/dist/findingHelp.js.map +1 -0
- package/dist/fix.d.ts +21 -0
- package/dist/fix.d.ts.map +1 -0
- package/dist/fix.js +180 -0
- package/dist/fix.js.map +1 -0
- package/dist/footprint.d.ts +33 -0
- package/dist/footprint.d.ts.map +1 -0
- package/dist/footprint.js +71 -0
- package/dist/footprint.js.map +1 -0
- package/dist/geometry/angle.d.ts +13 -0
- package/dist/geometry/angle.d.ts.map +1 -0
- package/dist/geometry/angle.js +21 -0
- package/dist/geometry/angle.js.map +1 -0
- package/dist/geometry/curve.d.ts +24 -0
- package/dist/geometry/curve.d.ts.map +1 -0
- package/dist/geometry/curve.js +78 -0
- package/dist/geometry/curve.js.map +1 -0
- package/dist/geometry/path.d.ts +29 -0
- package/dist/geometry/path.d.ts.map +1 -0
- package/dist/geometry/path.js +61 -0
- package/dist/geometry/path.js.map +1 -0
- package/dist/geometry/quadrature.d.ts +13 -0
- package/dist/geometry/quadrature.d.ts.map +1 -0
- package/dist/geometry/quadrature.js +57 -0
- package/dist/geometry/quadrature.js.map +1 -0
- package/dist/geometry/sat.d.ts +40 -0
- package/dist/geometry/sat.d.ts.map +1 -0
- package/dist/geometry/sat.js +86 -0
- package/dist/geometry/sat.js.map +1 -0
- package/dist/geometry/vec.d.ts +27 -0
- package/dist/geometry/vec.d.ts.map +1 -0
- package/dist/geometry/vec.js +30 -0
- package/dist/geometry/vec.js.map +1 -0
- package/dist/heading.d.ts +77 -0
- package/dist/heading.d.ts.map +1 -0
- package/dist/heading.js +164 -0
- package/dist/heading.js.map +1 -0
- package/dist/headingRanges.d.ts +48 -0
- package/dist/headingRanges.d.ts.map +1 -0
- package/dist/headingRanges.js +132 -0
- package/dist/headingRanges.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/kinematics.d.ts +63 -0
- package/dist/kinematics.d.ts.map +1 -0
- package/dist/kinematics.js +71 -0
- package/dist/kinematics.js.map +1 -0
- package/dist/ledger.d.ts +49 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +136 -0
- package/dist/ledger.js.map +1 -0
- package/dist/load.d.ts +12 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +12 -0
- package/dist/load.js.map +1 -0
- package/dist/mirror.d.ts +81 -0
- package/dist/mirror.d.ts.map +1 -0
- package/dist/mirror.js +282 -0
- package/dist/mirror.js.map +1 -0
- package/dist/plan.d.ts +29 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +159 -0
- package/dist/plan.js.map +1 -0
- package/dist/prBody.d.ts +24 -0
- package/dist/prBody.d.ts.map +1 -0
- package/dist/prBody.js +112 -0
- package/dist/prBody.js.map +1 -0
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +46 -0
- package/dist/provenance.js.map +1 -0
- package/dist/render.d.ts +18 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +464 -0
- package/dist/render.js.map +1 -0
- package/dist/resolve.d.ts +39 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +172 -0
- package/dist/resolve.js.map +1 -0
- package/dist/season.d.ts +65 -0
- package/dist/season.d.ts.map +1 -0
- package/dist/season.js +16 -0
- package/dist/season.js.map +1 -0
- package/dist/sim/commands.d.ts +97 -0
- package/dist/sim/commands.d.ts.map +1 -0
- package/dist/sim/commands.js +185 -0
- package/dist/sim/commands.js.map +1 -0
- package/dist/sim/curves.d.ts +37 -0
- package/dist/sim/curves.d.ts.map +1 -0
- package/dist/sim/curves.js +187 -0
- package/dist/sim/curves.js.map +1 -0
- package/dist/sim/follower.d.ts +124 -0
- package/dist/sim/follower.d.ts.map +1 -0
- package/dist/sim/follower.js +472 -0
- package/dist/sim/follower.js.map +1 -0
- package/dist/sim/ideal.d.ts +103 -0
- package/dist/sim/ideal.d.ts.map +1 -0
- package/dist/sim/ideal.js +393 -0
- package/dist/sim/ideal.js.map +1 -0
- package/dist/sim/index.d.ts +11 -0
- package/dist/sim/index.d.ts.map +1 -0
- package/dist/sim/index.js +10 -0
- package/dist/sim/index.js.map +1 -0
- package/dist/sim/params.d.ts +91 -0
- package/dist/sim/params.d.ts.map +1 -0
- package/dist/sim/params.js +195 -0
- package/dist/sim/params.js.map +1 -0
- package/dist/sim/pedroPath.d.ts +41 -0
- package/dist/sim/pedroPath.d.ts.map +1 -0
- package/dist/sim/pedroPath.js +191 -0
- package/dist/sim/pedroPath.js.map +1 -0
- package/dist/sim/plant.d.ts +59 -0
- package/dist/sim/plant.d.ts.map +1 -0
- package/dist/sim/plant.js +128 -0
- package/dist/sim/plant.js.map +1 -0
- package/dist/sim/residuals.d.ts +36 -0
- package/dist/sim/residuals.d.ts.map +1 -0
- package/dist/sim/residuals.js +86 -0
- package/dist/sim/residuals.js.map +1 -0
- package/dist/sim/simulate.d.ts +27 -0
- package/dist/sim/simulate.d.ts.map +1 -0
- package/dist/sim/simulate.js +924 -0
- package/dist/sim/simulate.js.map +1 -0
- package/dist/sim/types.d.ts +209 -0
- package/dist/sim/types.d.ts.map +1 -0
- package/dist/sim/types.js +2 -0
- package/dist/sim/types.js.map +1 -0
- package/dist/tokens.d.ts +93 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +93 -0
- package/dist/tokens.js.map +1 -0
- package/dist/trace.d.ts +89 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +187 -0
- package/dist/trace.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/unimplemented.d.ts +8 -0
- package/dist/unimplemented.d.ts.map +1 -0
- package/dist/unimplemented.js +11 -0
- package/dist/unimplemented.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/** The narrowest range an edit may leave, as a fraction of the path. */
|
|
2
|
+
export const MIN_RANGE_T = 0.02;
|
|
3
|
+
/** Keeps t readable in the file: boundaries land on four decimals. */
|
|
4
|
+
const roundT = (t) => Math.round(t * 10000) / 10000;
|
|
5
|
+
/** The heading a range holds at `t`, for a mode that does not need the geometry, else null. */
|
|
6
|
+
function fixedHeadingAt(range, t) {
|
|
7
|
+
const inner = range.heading;
|
|
8
|
+
if (inner.mode === "constant")
|
|
9
|
+
return inner.headingRad;
|
|
10
|
+
if (inner.mode === "linear") {
|
|
11
|
+
const span = range.endT - range.startT;
|
|
12
|
+
const local = span <= 0 ? 1 : (t - range.startT) / span;
|
|
13
|
+
return inner.fromRad + (inner.toRad - inner.fromRad) * local;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The same heading as one range from 0 to 1, or the heading itself when it is piecewise already.
|
|
19
|
+
* A step with no heading starts as one tangent range, the editor's default mode.
|
|
20
|
+
*/
|
|
21
|
+
export function toPiecewise(heading) {
|
|
22
|
+
if (heading?.mode === "piecewise")
|
|
23
|
+
return heading;
|
|
24
|
+
const inner = heading ?? { mode: "tangent" };
|
|
25
|
+
return { mode: "piecewise", ranges: [{ startT: 0, endT: 1, heading: inner }] };
|
|
26
|
+
}
|
|
27
|
+
/** The range that holds `t` strictly inside it, or -1 when t is on a boundary or outside 0..1. */
|
|
28
|
+
export function rangeContaining(heading, t) {
|
|
29
|
+
return heading.ranges.findIndex((range) => t > range.startT && t < range.endT);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Splits the range that holds `t` into two at `t`. Both halves keep the range's mode; a `linear`
|
|
33
|
+
* range is cut at the heading it passes through at `t`, so the robot turns exactly as before until
|
|
34
|
+
* either half is changed. Returns the heading unchanged when either half would be narrower than
|
|
35
|
+
* `MIN_RANGE_T`.
|
|
36
|
+
*/
|
|
37
|
+
export function splitRange(heading, t) {
|
|
38
|
+
const at = roundT(t);
|
|
39
|
+
const index = rangeContaining(heading, at);
|
|
40
|
+
if (index < 0)
|
|
41
|
+
return heading;
|
|
42
|
+
const range = heading.ranges[index];
|
|
43
|
+
if (at - range.startT < MIN_RANGE_T || range.endT - at < MIN_RANGE_T)
|
|
44
|
+
return heading;
|
|
45
|
+
let left = range.heading;
|
|
46
|
+
let right = range.heading;
|
|
47
|
+
if (range.heading.mode === "linear") {
|
|
48
|
+
const middle = fixedHeadingAt(range, at);
|
|
49
|
+
left = { mode: "linear", fromRad: range.heading.fromRad, toRad: middle };
|
|
50
|
+
right = { mode: "linear", fromRad: middle, toRad: range.heading.toRad };
|
|
51
|
+
}
|
|
52
|
+
const ranges = [
|
|
53
|
+
...heading.ranges.slice(0, index),
|
|
54
|
+
{ startT: range.startT, endT: at, heading: left },
|
|
55
|
+
{ startT: at, endT: range.endT, heading: right },
|
|
56
|
+
...heading.ranges.slice(index + 1),
|
|
57
|
+
];
|
|
58
|
+
return { mode: "piecewise", ranges };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Moves the boundary between range `index` and range `index + 1` to `t`, clamped so neither range
|
|
62
|
+
* gets narrower than `MIN_RANGE_T`. The two ranges keep their modes and values.
|
|
63
|
+
*/
|
|
64
|
+
export function moveBoundary(heading, index, t) {
|
|
65
|
+
const before = heading.ranges[index];
|
|
66
|
+
const after = heading.ranges[index + 1];
|
|
67
|
+
if (before === undefined || after === undefined)
|
|
68
|
+
return heading;
|
|
69
|
+
const lower = before.startT + MIN_RANGE_T;
|
|
70
|
+
const upper = after.endT - MIN_RANGE_T;
|
|
71
|
+
if (lower > upper)
|
|
72
|
+
return heading;
|
|
73
|
+
const at = roundT(Math.min(upper, Math.max(lower, t)));
|
|
74
|
+
const ranges = heading.ranges.map((range, position) => {
|
|
75
|
+
if (position === index)
|
|
76
|
+
return { ...range, endT: at };
|
|
77
|
+
if (position === index + 1)
|
|
78
|
+
return { ...range, startT: at };
|
|
79
|
+
return range;
|
|
80
|
+
});
|
|
81
|
+
return { mode: "piecewise", ranges };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deletes range `index`; the range before it grows to cover the gap, or the one after it when it is
|
|
85
|
+
* the first. The last range cannot be deleted: a piecewise heading needs one.
|
|
86
|
+
*/
|
|
87
|
+
export function deleteRange(heading, index) {
|
|
88
|
+
if (heading.ranges.length <= 1)
|
|
89
|
+
return heading;
|
|
90
|
+
const removed = heading.ranges[index];
|
|
91
|
+
if (removed === undefined)
|
|
92
|
+
return heading;
|
|
93
|
+
const ranges = heading.ranges.slice();
|
|
94
|
+
ranges.splice(index, 1);
|
|
95
|
+
if (index === 0) {
|
|
96
|
+
const next = ranges[0];
|
|
97
|
+
ranges[0] = { ...next, startT: removed.startT };
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const previous = ranges[index - 1];
|
|
101
|
+
ranges[index - 1] = { ...previous, endT: removed.endT };
|
|
102
|
+
}
|
|
103
|
+
return { mode: "piecewise", ranges };
|
|
104
|
+
}
|
|
105
|
+
/** Replaces range `index`'s own heading, keeping where it starts and ends. */
|
|
106
|
+
export function setRangeHeading(heading, index, inner) {
|
|
107
|
+
if (heading.ranges[index] === undefined)
|
|
108
|
+
return heading;
|
|
109
|
+
return {
|
|
110
|
+
mode: "piecewise",
|
|
111
|
+
ranges: heading.ranges.map((range, position) => (position === index ? { ...range, heading: inner } : range)),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A heading of `mode` for a range, carrying over the angle the range already holds where the new
|
|
116
|
+
* mode has one: a linear range starts where the old range started and ends where it ended.
|
|
117
|
+
*/
|
|
118
|
+
export function rangeHeadingForMode(mode, range) {
|
|
119
|
+
const start = fixedHeadingAt(range, range.startT) ?? 0;
|
|
120
|
+
const end = fixedHeadingAt(range, range.endT) ?? start;
|
|
121
|
+
switch (mode) {
|
|
122
|
+
case "constant":
|
|
123
|
+
return { mode: "constant", headingRad: start };
|
|
124
|
+
case "linear":
|
|
125
|
+
return { mode: "linear", fromRad: start, toRad: end };
|
|
126
|
+
case "facePoint":
|
|
127
|
+
return range.heading.mode === "facePoint" ? range.heading : { mode: "facePoint", xIn: 0, yIn: 0 };
|
|
128
|
+
default:
|
|
129
|
+
return { mode };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=headingRanges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headingRanges.js","sourceRoot":"","sources":["../src/headingRanges.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @horizon36596/zenith-core: geometry, heading modes, footprints, canonical form, resolution, planning and the
|
|
3
|
+
* feasibility checks. Its exports are the contract the CLI, the MCP server and the editor build on.
|
|
4
|
+
*
|
|
5
|
+
* Pure: no DOM, no clock, no randomness, no Node APIs, so the CLI, the MCP server, the editor and
|
|
6
|
+
* the tests all compute the same answer from the same files (CLAUDE.md rule 1).
|
|
7
|
+
*/
|
|
8
|
+
export * from "./geometry/vec.js";
|
|
9
|
+
export * from "./geometry/angle.js";
|
|
10
|
+
export * from "./geometry/quadrature.js";
|
|
11
|
+
export * from "./geometry/curve.js";
|
|
12
|
+
export * from "./geometry/path.js";
|
|
13
|
+
export * from "./geometry/sat.js";
|
|
14
|
+
export * from "./heading.js";
|
|
15
|
+
export * from "./headingRanges.js";
|
|
16
|
+
export * from "./footprint.js";
|
|
17
|
+
export * from "./types.js";
|
|
18
|
+
export * from "./season.js";
|
|
19
|
+
export * from "./provenance.js";
|
|
20
|
+
export * from "./trace.js";
|
|
21
|
+
export * from "./load.js";
|
|
22
|
+
export * from "./canonicalize.js";
|
|
23
|
+
export * from "./resolve.js";
|
|
24
|
+
export * from "./plan.js";
|
|
25
|
+
export * from "./check.js";
|
|
26
|
+
export * from "./continuity.js";
|
|
27
|
+
export * from "./findingHelp.js";
|
|
28
|
+
export * from "./kinematics.js";
|
|
29
|
+
export * from "./estimate.js";
|
|
30
|
+
export * from "./ledger.js";
|
|
31
|
+
export * from "./fix.js";
|
|
32
|
+
export * from "./mirror.js";
|
|
33
|
+
export * from "./tokens.js";
|
|
34
|
+
export * from "./render.js";
|
|
35
|
+
export * from "./checks/intake.js";
|
|
36
|
+
export * from "./diff.js";
|
|
37
|
+
export * from "./prBody.js";
|
|
38
|
+
export * from "./unimplemented.js";
|
|
39
|
+
export * from "./edit/index.js";
|
|
40
|
+
export * from "./sim/index.js";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @horizon36596/zenith-core: geometry, heading modes, footprints, canonical form, resolution, planning and the
|
|
3
|
+
* feasibility checks. Its exports are the contract the CLI, the MCP server and the editor build on.
|
|
4
|
+
*
|
|
5
|
+
* Pure: no DOM, no clock, no randomness, no Node APIs, so the CLI, the MCP server, the editor and
|
|
6
|
+
* the tests all compute the same answer from the same files (CLAUDE.md rule 1).
|
|
7
|
+
*/
|
|
8
|
+
export * from "./geometry/vec.js";
|
|
9
|
+
export * from "./geometry/angle.js";
|
|
10
|
+
export * from "./geometry/quadrature.js";
|
|
11
|
+
export * from "./geometry/curve.js";
|
|
12
|
+
export * from "./geometry/path.js";
|
|
13
|
+
export * from "./geometry/sat.js";
|
|
14
|
+
export * from "./heading.js";
|
|
15
|
+
export * from "./headingRanges.js";
|
|
16
|
+
export * from "./footprint.js";
|
|
17
|
+
export * from "./types.js";
|
|
18
|
+
export * from "./season.js";
|
|
19
|
+
export * from "./provenance.js";
|
|
20
|
+
export * from "./trace.js";
|
|
21
|
+
export * from "./load.js";
|
|
22
|
+
export * from "./canonicalize.js";
|
|
23
|
+
export * from "./resolve.js";
|
|
24
|
+
export * from "./plan.js";
|
|
25
|
+
export * from "./check.js";
|
|
26
|
+
export * from "./continuity.js";
|
|
27
|
+
export * from "./findingHelp.js";
|
|
28
|
+
export * from "./kinematics.js";
|
|
29
|
+
export * from "./estimate.js";
|
|
30
|
+
export * from "./ledger.js";
|
|
31
|
+
export * from "./fix.js";
|
|
32
|
+
export * from "./mirror.js";
|
|
33
|
+
export * from "./tokens.js";
|
|
34
|
+
export * from "./render.js";
|
|
35
|
+
export * from "./checks/intake.js";
|
|
36
|
+
export * from "./diff.js";
|
|
37
|
+
export * from "./prBody.js";
|
|
38
|
+
export * from "./unimplemented.js";
|
|
39
|
+
export * from "./edit/index.js";
|
|
40
|
+
export * from "./sim/index.js";
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type Robot } from "@horizon36596/zenith-schema";
|
|
2
|
+
/**
|
|
3
|
+
* The one place that reads a tunable out of `robot.json` and says what happens when the file does
|
|
4
|
+
* not carry it. Every default here is named where it is defined; nothing
|
|
5
|
+
* is invented, and nothing is read from two places without a stated order of preference.
|
|
6
|
+
*/
|
|
7
|
+
/** Seconds added to a path step for the follower to declare the end constraints met (`03` §3.7). */
|
|
8
|
+
export declare const DEFAULT_SETTLE_S = 0.25;
|
|
9
|
+
/** The estimate band until `07` fits a recorded run: nominal times one plus or minus this (`03` §3). */
|
|
10
|
+
export declare const DEFAULT_BAND_FRACTION = 0.2;
|
|
11
|
+
/** Where STRAFE_FRACTION starts warning: a fifth of a step spent sideways (`03` §4). */
|
|
12
|
+
export declare const DEFAULT_STRAFE_FRACTION_WARN = 0.2;
|
|
13
|
+
/** The fastest an intaking sweep should run, as a fraction of full speed (`03` §4, SWEEP_SPEED). */
|
|
14
|
+
export declare const DEFAULT_SWEEP_SPEED_FRACTION = 0.4;
|
|
15
|
+
/** How far off the travel direction a running mouth may point before MOUTH_LEADING fires. */
|
|
16
|
+
export declare const MOUTH_LEADING_TOLERANCE_RAD: number;
|
|
17
|
+
/** A step's `timeoutS` under this multiple of its estimate is TIMEOUT_TIGHT. */
|
|
18
|
+
export declare const TIMEOUT_TIGHT_MULTIPLE = 1.2;
|
|
19
|
+
/** Velocity and deceleration limits in the robot's own frame, already scaled by nothing. */
|
|
20
|
+
export interface RobotLimits {
|
|
21
|
+
maxForwardVelInPerS: number;
|
|
22
|
+
maxStrafeVelInPerS: number;
|
|
23
|
+
forwardDecelInPerS2: number;
|
|
24
|
+
strafeDecelInPerS2: number;
|
|
25
|
+
accelInPerS2: number;
|
|
26
|
+
maxAngularVelRadPerS: number;
|
|
27
|
+
defaultPathSpeedFraction: number;
|
|
28
|
+
settleS: number;
|
|
29
|
+
bandFraction: number;
|
|
30
|
+
/** True when the follower holds the end pose, so every path step brakes to a stop (`03` §2). */
|
|
31
|
+
holdEnd: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function robotLimits(robot: Robot): RobotLimits;
|
|
34
|
+
/**
|
|
35
|
+
* The STRAFE_FRACTION threshold. `strafeFractionWarn` is the spelling the biobuzz robot file uses;
|
|
36
|
+
* `strafeFractionThreshold` is the older one and is still read so an existing file keeps working.
|
|
37
|
+
*/
|
|
38
|
+
export declare const strafeFractionWarn: (robot: Robot) => number;
|
|
39
|
+
export declare const sweepSpeedFraction: (robot: Robot) => number;
|
|
40
|
+
/**
|
|
41
|
+
* The robot's height for the STRUCTURE z gate, and the only place it is read: the root key first,
|
|
42
|
+
* then the footprint's, then the default. Both keys are `{ value, provenance }`, so whichever wins
|
|
43
|
+
* carries its label with it.
|
|
44
|
+
*/
|
|
45
|
+
export declare const robotHeightIn: (robot: Robot) => number;
|
|
46
|
+
/**
|
|
47
|
+
* The velocity cap for a travel direction `phi` radians off the nose: the ellipse with semi-axes
|
|
48
|
+
* `maxForwardVel` and `maxStrafeVel` (`03` §3.1). `phi = 0` is nose-on, `phi = pi/2` is a pure
|
|
49
|
+
* strafe to the left.
|
|
50
|
+
*/
|
|
51
|
+
export declare function ellipseLimit(forward: number, strafe: number, phiRad: number): number;
|
|
52
|
+
/** The speed cap in in/s for a travel direction, before `speedFraction` is applied. */
|
|
53
|
+
export declare const velocityCapInPerS: (limits: RobotLimits, phiRad: number) => number;
|
|
54
|
+
/** The coasting deceleration in in/s^2 available in a travel direction (`03` §3.2). */
|
|
55
|
+
export declare const decelInPerS2: (limits: RobotLimits, phiRad: number) => number;
|
|
56
|
+
/** The stopping distance from a speed in a travel direction, which is what strafing really costs. */
|
|
57
|
+
export declare const stoppingDistanceIn: (limits: RobotLimits, velocityInPerS: number, phiRad: number) => number;
|
|
58
|
+
/**
|
|
59
|
+
* The lateral acceleration the drivetrain is assumed to hold in a corner. `03` §3.5 names
|
|
60
|
+
* `strafeDecel` as the proxy and says to label it as one, which `estimate`'s explanation does.
|
|
61
|
+
*/
|
|
62
|
+
export declare const lateralAccelLimitInPerS2: (limits: RobotLimits) => number;
|
|
63
|
+
//# sourceMappingURL=kinematics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinematics.d.ts","sourceRoot":"","sources":["../src/kinematics.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAElF;;;;GAIG;AAEH,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,wGAAwG;AACxG,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,wFAAwF;AACxF,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD,oGAAoG;AACpG,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD,6FAA6F;AAC7F,eAAO,MAAM,2BAA2B,QAAc,CAAC;AAEvD,gFAAgF;AAChF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAO1C,4FAA4F;AAC5F,MAAM,WAAW,WAAW;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wBAAwB,EAAE,MAAM,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,CAcrD;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,KAAK,KAAG,MAGpB,CAAC;AAE/B,eAAO,MAAM,kBAAkB,GAAI,OAAO,KAAK,KAAG,MAC0B,CAAC;AAE7E;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,MACwC,CAAC;AAEtF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpF;AAED,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,GAAI,QAAQ,WAAW,EAAE,QAAQ,MAAM,KAAG,MACK,CAAC;AAE9E,uFAAuF;AACvF,eAAO,MAAM,YAAY,GAAI,QAAQ,WAAW,EAAE,QAAQ,MAAM,KAAG,MACU,CAAC;AAE9E,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,gBAAgB,MAAM,EACtB,QAAQ,MAAM,KACb,MAAgF,CAAC;AAEpF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,QAAQ,WAAW,KAAG,MAAmC,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DEFAULT_ROBOT_HEIGHT_IN } from "@horizon36596/zenith-schema";
|
|
2
|
+
/**
|
|
3
|
+
* The one place that reads a tunable out of `robot.json` and says what happens when the file does
|
|
4
|
+
* not carry it. Every default here is named where it is defined; nothing
|
|
5
|
+
* is invented, and nothing is read from two places without a stated order of preference.
|
|
6
|
+
*/
|
|
7
|
+
/** Seconds added to a path step for the follower to declare the end constraints met (`03` §3.7). */
|
|
8
|
+
export const DEFAULT_SETTLE_S = 0.25;
|
|
9
|
+
/** The estimate band until `07` fits a recorded run: nominal times one plus or minus this (`03` §3). */
|
|
10
|
+
export const DEFAULT_BAND_FRACTION = 0.2;
|
|
11
|
+
/** Where STRAFE_FRACTION starts warning: a fifth of a step spent sideways (`03` §4). */
|
|
12
|
+
export const DEFAULT_STRAFE_FRACTION_WARN = 0.2;
|
|
13
|
+
/** The fastest an intaking sweep should run, as a fraction of full speed (`03` §4, SWEEP_SPEED). */
|
|
14
|
+
export const DEFAULT_SWEEP_SPEED_FRACTION = 0.4;
|
|
15
|
+
/** How far off the travel direction a running mouth may point before MOUTH_LEADING fires. */
|
|
16
|
+
export const MOUTH_LEADING_TOLERANCE_RAD = Math.PI / 6;
|
|
17
|
+
/** A step's `timeoutS` under this multiple of its estimate is TIMEOUT_TIGHT. */
|
|
18
|
+
export const TIMEOUT_TIGHT_MULTIPLE = 1.2;
|
|
19
|
+
const valueOf = (source, fallback) => (source === undefined ? fallback : source.value);
|
|
20
|
+
export function robotLimits(robot) {
|
|
21
|
+
const k = robot.kinematics;
|
|
22
|
+
return {
|
|
23
|
+
maxForwardVelInPerS: k.maxForwardVelInPerS.value,
|
|
24
|
+
maxStrafeVelInPerS: k.maxStrafeVelInPerS.value,
|
|
25
|
+
forwardDecelInPerS2: k.forwardDecelInPerS2.value,
|
|
26
|
+
strafeDecelInPerS2: k.strafeDecelInPerS2.value,
|
|
27
|
+
accelInPerS2: k.accelInPerS2.value,
|
|
28
|
+
maxAngularVelRadPerS: k.maxAngularVelRadPerS.value,
|
|
29
|
+
defaultPathSpeedFraction: k.defaultPathSpeedFraction.value,
|
|
30
|
+
settleS: valueOf(k.settleS, DEFAULT_SETTLE_S),
|
|
31
|
+
bandFraction: k.calibration?.band ?? DEFAULT_BAND_FRACTION,
|
|
32
|
+
holdEnd: k.follower.holdEnd,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The STRAFE_FRACTION threshold. `strafeFractionWarn` is the spelling the biobuzz robot file uses;
|
|
37
|
+
* `strafeFractionThreshold` is the older one and is still read so an existing file keeps working.
|
|
38
|
+
*/
|
|
39
|
+
export const strafeFractionWarn = (robot) => robot.kinematics.strafeFractionWarn?.value ??
|
|
40
|
+
robot.kinematics.strafeFractionThreshold?.value ??
|
|
41
|
+
DEFAULT_STRAFE_FRACTION_WARN;
|
|
42
|
+
export const sweepSpeedFraction = (robot) => valueOf(robot.kinematics.sweepSpeedFraction, DEFAULT_SWEEP_SPEED_FRACTION);
|
|
43
|
+
/**
|
|
44
|
+
* The robot's height for the STRUCTURE z gate, and the only place it is read: the root key first,
|
|
45
|
+
* then the footprint's, then the default. Both keys are `{ value, provenance }`, so whichever wins
|
|
46
|
+
* carries its label with it.
|
|
47
|
+
*/
|
|
48
|
+
export const robotHeightIn = (robot) => robot.heightIn?.value ?? robot.footprint.heightIn?.value ?? DEFAULT_ROBOT_HEIGHT_IN;
|
|
49
|
+
/**
|
|
50
|
+
* The velocity cap for a travel direction `phi` radians off the nose: the ellipse with semi-axes
|
|
51
|
+
* `maxForwardVel` and `maxStrafeVel` (`03` §3.1). `phi = 0` is nose-on, `phi = pi/2` is a pure
|
|
52
|
+
* strafe to the left.
|
|
53
|
+
*/
|
|
54
|
+
export function ellipseLimit(forward, strafe, phiRad) {
|
|
55
|
+
const cos = Math.cos(phiRad) / forward;
|
|
56
|
+
const sin = Math.sin(phiRad) / strafe;
|
|
57
|
+
const denominator = Math.hypot(cos, sin);
|
|
58
|
+
return denominator === 0 ? forward : 1 / denominator;
|
|
59
|
+
}
|
|
60
|
+
/** The speed cap in in/s for a travel direction, before `speedFraction` is applied. */
|
|
61
|
+
export const velocityCapInPerS = (limits, phiRad) => ellipseLimit(limits.maxForwardVelInPerS, limits.maxStrafeVelInPerS, phiRad);
|
|
62
|
+
/** The coasting deceleration in in/s^2 available in a travel direction (`03` §3.2). */
|
|
63
|
+
export const decelInPerS2 = (limits, phiRad) => ellipseLimit(limits.forwardDecelInPerS2, limits.strafeDecelInPerS2, phiRad);
|
|
64
|
+
/** The stopping distance from a speed in a travel direction, which is what strafing really costs. */
|
|
65
|
+
export const stoppingDistanceIn = (limits, velocityInPerS, phiRad) => (velocityInPerS * velocityInPerS) / (2 * decelInPerS2(limits, phiRad));
|
|
66
|
+
/**
|
|
67
|
+
* The lateral acceleration the drivetrain is assumed to hold in a corner. `03` §3.5 names
|
|
68
|
+
* `strafeDecel` as the proxy and says to label it as one, which `estimate`'s explanation does.
|
|
69
|
+
*/
|
|
70
|
+
export const lateralAccelLimitInPerS2 = (limits) => limits.strafeDecelInPerS2;
|
|
71
|
+
//# sourceMappingURL=kinematics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinematics.js","sourceRoot":"","sources":["../src/kinematics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAc,MAAM,6BAA6B,CAAC;AAElF;;;;GAIG;AAEH,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC,wGAAwG;AACxG,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAEzC,wFAAwF;AACxF,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD,oGAAoG;AACpG,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAEvD,gFAAgF;AAChF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,MAAM,OAAO,GAAG,CACd,MAAqC,EACrC,QAAgB,EACR,EAAE,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAiB9D,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC;IAC3B,OAAO;QACL,mBAAmB,EAAE,CAAC,CAAC,mBAAmB,CAAC,KAAK;QAChD,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,CAAC,KAAK;QAC9C,mBAAmB,EAAE,CAAC,CAAC,mBAAmB,CAAC,KAAK;QAChD,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,CAAC,KAAK;QAC9C,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC,KAAK;QAClC,oBAAoB,EAAE,CAAC,CAAC,oBAAoB,CAAC,KAAK;QAClD,wBAAwB,EAAE,CAAC,CAAC,wBAAwB,CAAC,KAAK;QAC1D,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,gBAAgB,CAAC;QAC7C,YAAY,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,IAAI,qBAAqB;QAC1D,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO;KAC5B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAY,EAAU,EAAE,CACzD,KAAK,CAAC,UAAU,CAAC,kBAAkB,EAAE,KAAK;IAC1C,KAAK,CAAC,UAAU,CAAC,uBAAuB,EAAE,KAAK;IAC/C,4BAA4B,CAAC;AAE/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAY,EAAU,EAAE,CACzD,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAY,EAAU,EAAE,CACpD,KAAK,CAAC,QAAQ,EAAE,KAAK,IAAI,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,IAAI,uBAAuB,CAAC;AAEtF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;AACvD,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAmB,EAAE,MAAc,EAAU,EAAE,CAC/E,YAAY,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AAE9E,uFAAuF;AACvF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAmB,EAAE,MAAc,EAAU,EAAE,CAC1E,YAAY,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AAE9E,qGAAqG;AACrG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,MAAmB,EACnB,cAAsB,EACtB,MAAc,EACN,EAAE,CAAC,CAAC,cAAc,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEpF;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,MAAmB,EAAU,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC"}
|
package/dist/ledger.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Field } from "@horizon36596/zenith-schema";
|
|
2
|
+
import { type SeasonRules, type SeasonState, type TargetId } from "./season.js";
|
|
3
|
+
import type { LedgerRow, Plan } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* The ledger of site/docs/seasons.md: what the robot holds, where
|
|
6
|
+
* every element is and what the season's own state is, stepped through the auto once.
|
|
7
|
+
*
|
|
8
|
+
* Transitions come from three places, in this order of trust:
|
|
9
|
+
*
|
|
10
|
+
* 1. `field.json` elements at kickoff, through `SeasonRules.initialState`.
|
|
11
|
+
* 2. Registry `ledger` hints on commands in `robot.json` (`launches: "count"`, `tip: "own"`).
|
|
12
|
+
* 3. A step's `expect` annotations (`collectFrom`, `launchesInto`, `tip`), which are the author
|
|
13
|
+
* telling the planner something the files cannot work out, and so win where they disagree.
|
|
14
|
+
*
|
|
15
|
+
* The core knows nothing about the game: everything below turns a step into a call on the season
|
|
16
|
+
* plugin and records what came back.
|
|
17
|
+
*/
|
|
18
|
+
/** One step's effect on the ledger, which is what the checks read. */
|
|
19
|
+
export interface LedgerEntry {
|
|
20
|
+
stepId: string;
|
|
21
|
+
/** The state as the step begins, which is what LEGAL_APPROACH and EMPTY_SHOT ask about. */
|
|
22
|
+
before: SeasonState;
|
|
23
|
+
after: SeasonState;
|
|
24
|
+
/** What the robot holds once the step has run, when the plugin tracks it. */
|
|
25
|
+
holds: Record<string, number>;
|
|
26
|
+
/** The target the ledger says is current while the step runs. */
|
|
27
|
+
target: TargetId | null;
|
|
28
|
+
/** How many pieces this step launched, and at what. */
|
|
29
|
+
launched: number;
|
|
30
|
+
collected: {
|
|
31
|
+
containerId: string;
|
|
32
|
+
count: number;
|
|
33
|
+
} | null;
|
|
34
|
+
tipped: "own" | "opponent" | null;
|
|
35
|
+
/** The row this step contributes to the panel, or null when it changed nothing. */
|
|
36
|
+
row: LedgerRow | null;
|
|
37
|
+
}
|
|
38
|
+
export interface LedgerRun {
|
|
39
|
+
entries: LedgerEntry[];
|
|
40
|
+
byStepId: Readonly<Record<string, LedgerEntry>>;
|
|
41
|
+
rows: LedgerRow[];
|
|
42
|
+
initialState: SeasonState;
|
|
43
|
+
finalState: SeasonState;
|
|
44
|
+
}
|
|
45
|
+
/** Steps the auto once and returns every transition, for the panel, the checks and the PR body. */
|
|
46
|
+
export declare function runLedger(plan: Plan, field: Field, season?: SeasonRules): LedgerRun;
|
|
47
|
+
/** The ledger rows of `03` section 6, for the panel and the pull-request body. */
|
|
48
|
+
export declare const ledger: (plan: Plan, field: Field, season?: SeasonRules) => LedgerRow[];
|
|
49
|
+
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,KAAK,EAAe,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAY,MAAM,YAAY,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AAEH,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iEAAiE;IACjE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,MAAM,EAAE,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;IAClC,mFAAmF;IACnF,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAChD,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,YAAY,EAAE,WAAW,CAAC;IAC1B,UAAU,EAAE,WAAW,CAAC;CACzB;AAiCD,mGAAmG;AACnG,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,MAAM,GAAE,WAA2B,GAClC,SAAS,CAsGX;AAkBD,kFAAkF;AAClF,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,EAAE,OAAO,KAAK,EAAE,SAAQ,WAA2B,KAAG,SAAS,EAC3D,CAAC"}
|
package/dist/ledger.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { noSeasonRules } from "./season.js";
|
|
2
|
+
const toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
3
|
+
/**
|
|
4
|
+
* How many pieces a command launches: the registry hint names either a number or one of the
|
|
5
|
+
* command's own parameters, and `expect.count` overrides both.
|
|
6
|
+
*/
|
|
7
|
+
function launchCount(spec, args, expected) {
|
|
8
|
+
if (expected !== undefined)
|
|
9
|
+
return expected;
|
|
10
|
+
const hint = spec?.ledger?.["launches"];
|
|
11
|
+
if (hint === undefined)
|
|
12
|
+
return null;
|
|
13
|
+
if (typeof hint === "number")
|
|
14
|
+
return hint;
|
|
15
|
+
const fromArgs = toNumber(args?.[hint]);
|
|
16
|
+
if (fromArgs !== null)
|
|
17
|
+
return fromArgs;
|
|
18
|
+
const param = spec?.params?.[hint];
|
|
19
|
+
if (param !== undefined && "default" in param) {
|
|
20
|
+
const fallback = toNumber(param.default);
|
|
21
|
+
if (fallback !== null)
|
|
22
|
+
return fallback;
|
|
23
|
+
}
|
|
24
|
+
return toNumber(Number(hint));
|
|
25
|
+
}
|
|
26
|
+
const tipHint = (spec) => {
|
|
27
|
+
const hint = spec?.ledger?.["tip"];
|
|
28
|
+
return hint === "own" || hint === "opponent" ? hint : null;
|
|
29
|
+
};
|
|
30
|
+
/** Steps the auto once and returns every transition, for the panel, the checks and the PR body. */
|
|
31
|
+
export function runLedger(plan, field, season = noSeasonRules) {
|
|
32
|
+
const robot = plan.robot;
|
|
33
|
+
const alliance = plan.auto.alliance;
|
|
34
|
+
const specOf = (name) => robot.commands.find((command) => command.name === name);
|
|
35
|
+
const initialState = season.initialState(field);
|
|
36
|
+
let state = season.start === undefined
|
|
37
|
+
? initialState
|
|
38
|
+
: season.start(initialState, plan.auto.start.holds ?? {});
|
|
39
|
+
const withStart = state;
|
|
40
|
+
const entries = [];
|
|
41
|
+
const byStepId = {};
|
|
42
|
+
const apply = (step) => {
|
|
43
|
+
const before = state;
|
|
44
|
+
const target = season.currentTarget(state, alliance);
|
|
45
|
+
const expect = "expect" in step.step ? step.step.expect : undefined;
|
|
46
|
+
let launched = 0;
|
|
47
|
+
let collected = null;
|
|
48
|
+
let tipped = null;
|
|
49
|
+
if (step.step.kind === "command") {
|
|
50
|
+
const call = step.step;
|
|
51
|
+
const spec = specOf(call.name);
|
|
52
|
+
const count = launchCount(spec, call.args, expect?.count);
|
|
53
|
+
if (count !== null && count > 0) {
|
|
54
|
+
launched = count;
|
|
55
|
+
state = season.onLaunch(state, expect?.launchesInto ?? target ?? "", count, step.startPose);
|
|
56
|
+
}
|
|
57
|
+
tipped = expect?.tip ?? tipHint(spec);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (expect?.launchesInto !== undefined && (expect.count ?? 0) > 0) {
|
|
61
|
+
launched = expect.count ?? 0;
|
|
62
|
+
state = season.onLaunch(state, expect.launchesInto, launched, step.startPose);
|
|
63
|
+
}
|
|
64
|
+
tipped = expect?.tip ?? null;
|
|
65
|
+
}
|
|
66
|
+
if (expect?.collectFrom !== undefined) {
|
|
67
|
+
const count = expect.count ?? 1;
|
|
68
|
+
collected = { containerId: expect.collectFrom, count };
|
|
69
|
+
state = season.onCollect(state, expect.collectFrom, count);
|
|
70
|
+
}
|
|
71
|
+
if (tipped !== null && season.onTip !== undefined) {
|
|
72
|
+
state = season.onTip(state, tipped, alliance);
|
|
73
|
+
}
|
|
74
|
+
const holds = season.holds === undefined ? {} : season.holds(state);
|
|
75
|
+
const detail = season.describe === undefined ? null : season.describe(before, state);
|
|
76
|
+
const changed = before !== state;
|
|
77
|
+
const row = changed
|
|
78
|
+
? {
|
|
79
|
+
stepId: step.id,
|
|
80
|
+
label: describeStep(step, launched, collected, tipped),
|
|
81
|
+
...(detail === null ? {} : { detail }),
|
|
82
|
+
holds,
|
|
83
|
+
}
|
|
84
|
+
: null;
|
|
85
|
+
const entry = {
|
|
86
|
+
stepId: step.id,
|
|
87
|
+
before,
|
|
88
|
+
after: state,
|
|
89
|
+
holds,
|
|
90
|
+
target,
|
|
91
|
+
launched,
|
|
92
|
+
collected,
|
|
93
|
+
tipped,
|
|
94
|
+
row,
|
|
95
|
+
};
|
|
96
|
+
entries.push(entry);
|
|
97
|
+
byStepId[step.id] = entry;
|
|
98
|
+
};
|
|
99
|
+
const walk = (steps) => {
|
|
100
|
+
for (const step of steps) {
|
|
101
|
+
apply(step);
|
|
102
|
+
if (step.children === undefined)
|
|
103
|
+
continue;
|
|
104
|
+
if (step.step.kind === "branch") {
|
|
105
|
+
// Only one side of a branch runs, and `resolve` already takes the `then` side as the one
|
|
106
|
+
// that defines where the robot ends up, so the ledger follows the same side.
|
|
107
|
+
walk(step.children.slice(0, step.step.then.length));
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
walk(step.children);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
walk(plan.steps);
|
|
114
|
+
return {
|
|
115
|
+
entries,
|
|
116
|
+
byStepId,
|
|
117
|
+
rows: [...entries.flatMap((entry) => (entry.row === null ? [] : [entry.row])), ...season.summary(state)],
|
|
118
|
+
initialState: withStart,
|
|
119
|
+
finalState: state,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** What the step did, in the words the ledger panel prints in its first column. */
|
|
123
|
+
function describeStep(step, launched, collected, tipped) {
|
|
124
|
+
const parts = [];
|
|
125
|
+
if (launched > 0)
|
|
126
|
+
parts.push(`launched ${String(launched)}`);
|
|
127
|
+
if (collected !== null) {
|
|
128
|
+
parts.push(`collected ${String(collected.count)} from ${collected.containerId}`);
|
|
129
|
+
}
|
|
130
|
+
if (tipped !== null)
|
|
131
|
+
parts.push(`tipped the ${tipped} hive`);
|
|
132
|
+
return parts.length === 0 ? step.id : `${step.id}: ${parts.join(", ")}`;
|
|
133
|
+
}
|
|
134
|
+
/** The ledger rows of `03` section 6, for the panel and the pull-request body. */
|
|
135
|
+
export const ledger = (plan, field, season = noSeasonRules) => runLedger(plan, field, season).rows;
|
|
136
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
|
package/dist/load.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Auto, type Field, type Link, type Robot, type Waypoints } from "@horizon36596/zenith-schema";
|
|
2
|
+
/**
|
|
3
|
+
* Parse, migrate and schema-validate. These throw SchemaError with every failing key named; the
|
|
4
|
+
* CLI turns that into a SCHEMA finding. Reading the bytes is the caller's job: core has no Node
|
|
5
|
+
* APIs (CLAUDE.md rule 1).
|
|
6
|
+
*/
|
|
7
|
+
export declare const loadAuto: (json: unknown) => Auto;
|
|
8
|
+
export declare const loadRobot: (json: unknown) => Robot;
|
|
9
|
+
export declare const loadField: (json: unknown) => Field;
|
|
10
|
+
export declare const loadWaypoints: (json: unknown) => Waypoints;
|
|
11
|
+
export declare const loadLink: (json: unknown) => Link;
|
|
12
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,IAAI,EACT,KAAK,KAAK,EACV,KAAK,IAAI,EACT,KAAK,KAAK,EACV,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,MAAM,OAAO,KAAG,IAAuB,CAAC;AACjE,eAAO,MAAM,SAAS,GAAI,MAAM,OAAO,KAAG,KAAyB,CAAC;AACpE,eAAO,MAAM,SAAS,GAAI,MAAM,OAAO,KAAG,KAAyB,CAAC;AACpE,eAAO,MAAM,aAAa,GAAI,MAAM,OAAO,KAAG,SAAiC,CAAC;AAChF,eAAO,MAAM,QAAQ,GAAI,MAAM,OAAO,KAAG,IAAuB,CAAC"}
|
package/dist/load.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { parseAuto, parseField, parseLink, parseRobot, parseWaypoints, } from "@horizon36596/zenith-schema";
|
|
2
|
+
/**
|
|
3
|
+
* Parse, migrate and schema-validate. These throw SchemaError with every failing key named; the
|
|
4
|
+
* CLI turns that into a SCHEMA finding. Reading the bytes is the caller's job: core has no Node
|
|
5
|
+
* APIs (CLAUDE.md rule 1).
|
|
6
|
+
*/
|
|
7
|
+
export const loadAuto = (json) => parseAuto(json);
|
|
8
|
+
export const loadRobot = (json) => parseRobot(json);
|
|
9
|
+
export const loadField = (json) => parseField(json);
|
|
10
|
+
export const loadWaypoints = (json) => parseWaypoints(json);
|
|
11
|
+
export const loadLink = (json) => parseLink(json);
|
|
12
|
+
//# sourceMappingURL=load.js.map
|
package/dist/load.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,UAAU,EACV,cAAc,GAMf,MAAM,6BAA6B,CAAC;AAErC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAa,EAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAa,EAAS,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAa,EAAS,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAa,EAAa,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAChF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAa,EAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC"}
|