feat(rover): add drive profiles and leased remote command channel
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Rover control behaviour prototype
|
||||
|
||||
Status: **offline behavioural reference; no production actuation adapter**.
|
||||
Requested by the owner while unavailable for physical testing, 2026-09-24.
|
||||
Neither Core composition nor Node/VESC runtime imports these modules. No new
|
||||
driver, service, firmware, motor settings or authority capability is installed.
|
||||
|
||||
`src/profile.ts` contains the versioned desired-profile parser, Tank and Arcade
|
||||
mixers, continuous deadband, linear/squared response, relative output scaling,
|
||||
and fan-out to any number of UUID-bound motors on both sides. UUIDs must be
|
||||
unique; a missing side is rejected. `forwardSign` is the verified sign at the
|
||||
future actuator adapter, not a copy of `m_invert_direction` and not a second
|
||||
automatic inversion of the current VESC configuration.
|
||||
|
||||
The normalized result has no electrical units. It cannot be sent as amperes,
|
||||
watts, duty, ERPM or speed without a separately qualified adapter and individual
|
||||
motor, battery/BMS and braking limits. A profile output scale of 80% is **not**
|
||||
the owner's proposed 20% safety margin against verified equipment ratings.
|
||||
The current real RC path is PPM Duty Cycle; this prototype does not change it.
|
||||
|
||||
Arcade uses continuous diamond desaturation, with forward positive and right
|
||||
yaw positive. For shaped inputs `v` and `r`, the pair is `(v+r, v-r)` multiplied
|
||||
by `max(abs(v),abs(r))/(abs(v)+abs(r))`, or zero at the origin. This follows the
|
||||
WPILib ArcadeDriveIK geometry with the steering sign adapted to the UI.
|
||||
Reverse plus right still requests right yaw; it is not a car steering-wheel
|
||||
convention, curvature drive, a turn-radius controller or omnidirectional motion.
|
||||
No VESC Tool calibration algorithm is reproduced.
|
||||
|
||||
References inspected 2026-09-24:
|
||||
|
||||
- [WPILib drive classes](https://docs.wpilib.org/en/stable/docs/software/hardware-apis/motors/wpi-drive-classes.html)
|
||||
- [ArcadeDriveIK source](https://github.com/wpilibsuite/allwpilib/blob/main/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp)
|
||||
|
||||
## Authority model
|
||||
|
||||
`src/authority.ts` is a pure deterministic model. Its output contains **intent**
|
||||
to stop all drives, revoke the Core epoch, flush queued motion and cancel
|
||||
autonomous motion tasks; it does not actually stop a motor or cancel a process.
|
||||
The future actuator must enforce the gate synchronously before asynchronous
|
||||
task cancellation. RC reception, drive supervision and telemetry must survive.
|
||||
|
||||
Boot, input loss, controller loss, stale/invalid data, a timing gap or Core
|
||||
command loss enter hold. First RC deflection while Core owns motion consumes
|
||||
the gesture and revokes the old token. Every assigned input must then be neutral
|
||||
and every motor must have trusted physical-stop evidence for the full configured
|
||||
interval. A held first gesture or repeated packet does not qualify. The next
|
||||
gesture starts RC manual operation. Neutral never resumes the previous Core
|
||||
task. Reacquisition requires a new explicit, nonreplayed request in neutral.
|
||||
Old Core commands cannot cross an epoch or process boot identity.
|
||||
|
||||
Policy values are mandatory constructor arguments. The demo uses 100 ms
|
||||
freshness / 200 ms neutral solely as synthetic fixtures, **not accepted rover
|
||||
reaction limits**. Use one monotonic clock domain from an authenticated local
|
||||
producer and a fresh unpredictable boot identity per instance. A token is a
|
||||
stale-command fence, not authentication or a replacement for access control.
|
||||
Calls and input types belong to a trusted model harness; this is not a public
|
||||
network request parser. Run a supervisory tick even when no new input arrives.
|
||||
|
||||
`link.live`, sample acquisition timestamps/sequences and `drive.stopped` must
|
||||
come from qualified evidence. A fresh USB response with old decoded PPM does
|
||||
not meet this contract. Zero motor current/duty alone is not physical stop.
|
||||
The current FW 5.02 input API does not supply all required evidence. In
|
||||
particular, stop-first independent of Mini needs an enforcement point outside
|
||||
Mini and coordination of **all** motor controllers. No such qualified mechanism
|
||||
is claimed by these tests. Receiver failsafe is also still awaiting acceptance.
|
||||
|
||||
Input axes are semantic controls, not invented receiver channels. The mixer for
|
||||
Tank requires two Y axes; Arcade requires both axes of the selected stick. The
|
||||
authority policy separately declares all `monitoredAxes`: the demo watches all
|
||||
four axes, so the other stick also stops Core in Arcade. Missing monitored axes
|
||||
are rejected, not synthesized as zero; all must return to neutral. The current two
|
||||
separate receiver-to-VESC PWM outputs do not establish access to those Arcade
|
||||
axes. The channel map, radio-link semantics and independent mixed RC path remain
|
||||
hardware integration work. Profile revision or binding changes require a fresh
|
||||
model initialized in hold, not an in-place live change.
|
||||
|
||||
## Preview and validation
|
||||
|
||||
Use the already installed Control Station toolchain; no new dependencies:
|
||||
|
||||
```sh
|
||||
cd apps/control-station
|
||||
node --test test/roverControl.test.mjs
|
||||
./node_modules/.bin/tsc --project tools/rover-control-preview/tsconfig.json
|
||||
node tools/rover-control-preview/build.mjs /absolute/artifact/directory
|
||||
```
|
||||
|
||||
The self-contained HTML uses canonical Design Guideline components. Its CSP
|
||||
disables all network connections, and no transport/serial code exists in the
|
||||
bundle. It is an owner-review artifact, outside production navigation. Browser
|
||||
storage and JSON export contain a **draft**, never confirmed applied state.
|
||||
It does not add USB controls, device-specific phantom entities or a runtime
|
||||
source-selection switch to the product. The synthetic takeover trace is
|
||||
engineering review content, not a proposed operator control panel.
|
||||
|
||||
Intended product placement remains the existing shared «Настройки борта» section
|
||||
on Core and Node, between computer details and devices. Alternatives (a new
|
||||
workspace or separate per-VESC control-mode selectors) would fragment a single
|
||||
vehicle-wide profile and are not used. Existing `Inspector`, `SettingsCard`,
|
||||
`InspectorSelectField`, `RangeControl`, `Button`, `StatusBadge` cover the review;
|
||||
no Design Guideline extensions or new visual primitives were needed.
|
||||
|
||||
Before production integration: verified input mapping and radio failsafe,
|
||||
independent stop-first actuator mechanism, desired/applied profile storage on
|
||||
Node with optimistic revision checking, all-member application receipts and
|
||||
failure recovery, then shared UI and supervised unloaded tests. Do not expose
|
||||
an enabled Apply button based only on successful model tests.
|
||||
Reference in New Issue
Block a user