Compare commits
8 Commits
140ad0d3ba
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b52a7dcedb | |||
| 4cbac36fbe | |||
| 5d186bfd5d | |||
| 229d796cfd | |||
| 5feba8b354 | |||
| 0eab0e660e | |||
| 34140cc666 | |||
| 77d6b79c6b |
@@ -17,11 +17,14 @@ definitions from here.
|
||||
|---|---|
|
||||
| [`schema/topics.json`](schema/topics.json) | Topic namespace: payload kind, retention, rate, publisher |
|
||||
| [`schema/envelope.json`](schema/envelope.json) | JSON Schema for the decoded-signal envelope |
|
||||
| [`schema/signals.json`](schema/signals.json) | Signal registry — the single source for name, unit, type and range |
|
||||
| [`schema/signals.json`](schema/signals.json) | Signal registry — the single source for name, unit, type and range, and for where each decoded Z27AG signal sits in its CAN frame (`can` block) |
|
||||
| [`docs/BOUNDARY.md`](docs/BOUNDARY.md) | Display boundary protocol: what crosses between `svc-gw` and the app |
|
||||
| [`checklists/`](checklists/) | Recording checklists as data; the app bundles exact copies (its **Captures** page) |
|
||||
|
||||
The Z27AG DBC lands here too, once Phase 2 produces one.
|
||||
Decoded Z27AG signals (source `z27ag`) carry their frame layout in `signals.json` itself,
|
||||
so name, unit and bits cannot drift apart. A DBC for tools like SavvyCAN or cantools,
|
||||
if one is wanted, is generated from it, never edited by hand. Findings behind each
|
||||
layout: [`docs/impl/reports/`](docs/impl/reports/).
|
||||
|
||||
- For implementation practice guidelines, refer to the [guidelines](docs/GUIDELINES.md);
|
||||
- For implementation plans and history, refer to [them](docs/impl/);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "z27ag-captures",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
"title": "Z27AG decoding captures",
|
||||
"about": "docs/impl/plans/Z27AG-CAPTURES.md",
|
||||
"mark_format": "<step> <action>[ #<n>] start|end for a span, <step> <action>[ #<n>] for a point",
|
||||
@@ -447,6 +447,59 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "IMU calibration (module fixed in its final place)",
|
||||
"steps": [
|
||||
{
|
||||
"id": "27",
|
||||
"title": "IMU level, facing one way",
|
||||
"do": "Parked on the flattest ground at hand, engine off or idling, nobody moving inside. Start, keep still 15 s, end.",
|
||||
"finds": "which way is down for the IMU (with step 28, cancelling the ground's slope)",
|
||||
"actions": [
|
||||
{
|
||||
"label": "imu level A",
|
||||
"hold_s": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "28",
|
||||
"title": "IMU level, turned round",
|
||||
"do": "The same spot, nose the other way: a rough 180° will do. Still again, 15 s.",
|
||||
"finds": "the second half of the level: the slope's tilt reverses, the mounting's does not",
|
||||
"actions": [
|
||||
{
|
||||
"label": "imu level B",
|
||||
"hold_s": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "29",
|
||||
"title": "IMU pull-away, straight",
|
||||
"do": "A straight, flat section. From standstill, a firm pull-away in 1st to about 30. Start as the clutch bites, end as you lift.",
|
||||
"finds": "which way is forward for the IMU",
|
||||
"actions": [
|
||||
{
|
||||
"label": "imu pull away",
|
||||
"repeat": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "30",
|
||||
"title": "IMU braking, straight",
|
||||
"do": "The same section. From about 40, a firm (not emergency) stop. Start as you brake, end when stopped.",
|
||||
"finds": "forward again, from the other side; also braking g",
|
||||
"actions": [
|
||||
{
|
||||
"label": "imu brake",
|
||||
"repeat": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+9
-7
@@ -37,7 +37,7 @@ The two channels from decision 24 share the socket but keep different guarantees
|
||||
| `ack` | reply to a `cmd` | `id`, `ok`, `detail`, `dup` (true when answered from the cache) |
|
||||
|
||||
With `source: bus`, `signals` is the newest envelope of every signal svc-gw has
|
||||
seen on `yukart/vehicle/+` and `yukart/host/+`. svc-gw marks one
|
||||
seen on `yukart/vehicle/+`, `yukart/host/+`, `yukart/gnss/+` and `yukart/imu/+`. svc-gw marks one
|
||||
`quality: "stale"` when it has not been refreshed for 5 s, or is known only from
|
||||
the broker's retained copy (which may predate a reboot). A signal once seen is
|
||||
never removed.
|
||||
@@ -66,18 +66,20 @@ tablet, or an Orin behind a replugged hub, looks connected at the link layer.
|
||||
|---|---|---|
|
||||
| `ping` | — | `ack` with `detail: "pong"` |
|
||||
| `mark` | `text`, `delay_ms` (optional: how long the command waited before this send) | stamped into the open recording; fails with no session open |
|
||||
| `poweroff` | `confirm: "poweroff"`, `boot_id` (from this connection's `hello`) | acks, then shuts the host down cleanly (`systemctl poweroff`) about 2 s later. Refused unless svc-gw runs with `--allow-poweroff` (the Orin's unit only), and when `boot_id` is not the current boot's |
|
||||
| `poweroff` | `confirm: "poweroff"`, `boot_id` (from this connection's `hello`) | acks, then shuts the host down cleanly (`systemctl poweroff`) about 2 s later. Refused unless svc-gw runs with `--allow-power` (the Orin's unit only), and when `boot_id` is not the current boot's |
|
||||
| `reboot` | `confirm: "reboot"`, `boot_id` | the same, with `systemctl reboot`; the same flag and refusals |
|
||||
|
||||
A repeated `id` returns the original `ack` (last 256 kept, shared across
|
||||
connections) and never re-runs the command.
|
||||
|
||||
`poweroff` is the exception to retry-until-acked: the ack cache does not survive
|
||||
the reboot it causes, so a resend could shut the next boot down too. The client
|
||||
sends it once and does not resend it; `boot_id` makes svc-gw refuse one from a
|
||||
previous boot regardless.
|
||||
`poweroff` and `reboot` are the exception to retry-until-acked: the ack cache does
|
||||
not survive the restart they cause, so a resend could shut the next boot down (or
|
||||
reboot it again). The client sends them once and does not resend; `boot_id` makes
|
||||
svc-gw refuse one from a previous boot regardless.
|
||||
|
||||
## Not yet
|
||||
|
||||
- TTS utterances (id, chunk sequence, terminator, expiry) — when there is a TTS.
|
||||
- `gnss`: its fix is an object, which the envelope's `value` does not allow yet.
|
||||
- `gnss/fix` as one object (navigation's input): the envelope's `value` does not allow
|
||||
one yet. Displays get the fix as single values on `yukart/gnss/<signal>` instead.
|
||||
- Any version beyond `proto: 0`. A breaking change bumps it; the client checks it.
|
||||
|
||||
+12
-2
@@ -9,7 +9,7 @@ type: guidelines
|
||||
- ⚠ **The unit appears in both the topic name and the payload, so they can
|
||||
contradict each other.** Generating both from one entry is what stops that; a
|
||||
hand-written `"unit"` reintroduces the failure it was meant to prevent.
|
||||
- Signal names carry their unit (`vehicle_speed_kph`, `coolant_temp_c`), so a unit
|
||||
- Signal names carry their unit (`gnss_speed_kph`, `obd_coolant_temp_c`), so a unit
|
||||
mismatch is visible at the call site rather than one registry lookup away.
|
||||
|
||||
## 2. Two clocks, and they answer different questions
|
||||
@@ -33,4 +33,14 @@ type: guidelines
|
||||
- There is no version in any topic or payload. A recorded session names the
|
||||
contracts tag it was captured under, which is what keeps old captures readable.
|
||||
|
||||
## 6. To be added
|
||||
## 6. A decoded signal's layout lives only in its registry entry
|
||||
- Every `source: z27ag` signal has a `can` block in `signals.json`: frame ID, byte,
|
||||
bit or length, byte order, scale and offset. The decoder reads those blocks and
|
||||
nothing else, so a correction lands in one file and every consumer sees it.
|
||||
- ⚠ **No CAN ID or bit position is written in any service's code.** A layout
|
||||
hard-coded downstream is a second source that silently disagrees the day the
|
||||
registry is corrected.
|
||||
- Each block names the report with its evidence (`evidence`). A layout without
|
||||
evidence is a guess and does not go in.
|
||||
|
||||
## 7. To be added
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: plan
|
||||
status: ready
|
||||
updated: 2026-10-13
|
||||
updated: 2026-10-14
|
||||
---
|
||||
# Z27AG decoding captures: what to do in the car
|
||||
|
||||
@@ -13,10 +13,11 @@ ground truth. Prior art and first candidates: [the prior-art report](../reports/
|
||||
|
||||
| In the session directory | From | Use |
|
||||
|---|---|---|
|
||||
| `can-*.log(.zst)` | the PEAK, every frame, kernel timestamps | what gets decoded; also holds every OBD request (`7DF`) and reply (`7E8`) |
|
||||
| `vehicle.ndjson` | `obd-poller` via the bus | the same OBD replies as values (rpm, speed, throttle, load, MAP, MAF ~10 Hz; coolant, intake air, fuel 1 Hz); `env.timestamp` equals the reply frame's timestamp |
|
||||
| `can-*.log(.zst)` | the PEAK, every frame, kernel timestamps | what gets decoded (nothing transmits on CAN: OBD-II is on the K-line) |
|
||||
| `vehicle.ndjson` | `decoder` and `obd-poller` via the bus | decoded CAN signals, and the `obd_*` references from the K-line through the ELM327 (rpm, speed, throttle, load, MAF, timing, O2 every round; coolant, intake air, trims every 5 s); `env.timestamp` is the reply's arrival at the Orin |
|
||||
| `events.ndjson` | marks from the app | when each step happened |
|
||||
| `gnss.ndjson` | gpsd (SIM7600) | speed and position for the drive |
|
||||
| `imu.ndjson` | `imu` via the bus (`yukart/raw/imu`) | every IMU sample, raw module axes, Orin receive time: calibration (27–30) and, once calibrated, motion for the drive |
|
||||
|
||||
## Operating it from the app
|
||||
|
||||
@@ -33,8 +34,9 @@ ground truth. Prior art and first candidates: [the prior-art report](../reports/
|
||||
session` when there is no traffic yet (ignition on, PEAK plugged). A mark sent with
|
||||
the link down waits (`unacked`) and goes when it is back, with its delay noted.
|
||||
- The **Mark** button on the main screen is still there for anything off-plan.
|
||||
- **OBD is working** when `engine_rpm`, `vehicle_speed_kph` and the rest appear in
|
||||
the signal list and move. If they never appear, see *If OBD stays silent*.
|
||||
- **OBD is working** when `obd_engine_rpm`, `obd_coolant_temp_c` and the rest appear
|
||||
in the signal list and move (the ELM on the OBD port, through the Y harness beside
|
||||
the PEAK). If they never appear, see *If OBD stays silent*.
|
||||
|
||||
## The steps
|
||||
|
||||
@@ -52,14 +54,20 @@ recorder refuses marks with "no session" otherwise); engine off, doors shut.
|
||||
- **Engine running, parked** (14–18): start and idle, held revs in neutral (no OBD
|
||||
on this car's CAN: the revs are approximate, read off the tacho), blips, A/C load, radiator fan.
|
||||
- **Driving** (19–22): steady speeds, stops, corners, each gear. A passenger presses,
|
||||
or skip the marks: GNSS speed is recorded continuously, and gear comes from
|
||||
rpm ÷ speed.
|
||||
or skip the marks: GNSS speed is recorded continuously. The gear is not on CAN and
|
||||
is not inferred (decode report).
|
||||
- **On jack stands** (23–26, since v2): front wheels up, rears chocked, handbrake
|
||||
off. Unpowered steering; speedometer readings held in 2nd and 3rd (fronts turn,
|
||||
rears stay still, which tells the wheels apart); braking from speed with vacuum
|
||||
assist; reverse. Stands replace the driving speeds where a drive is not practical.
|
||||
- **IMU calibration** (27–30, since v3): once the IMU is fixed in its final place. Level
|
||||
twice on the same spot, facing one way and then turned round (a rough 180° is fine:
|
||||
the ground's slope reverses and cancels, the mounting's tilt does not); then three
|
||||
firm pull-aways and three firm stops on a straight, flat section (forward, signed by
|
||||
which kind of stretch it is). Any session holds raw IMU samples (`imu.ndjson`), so
|
||||
these can go in their own short session or with anything else.
|
||||
|
||||
Version 2 (2026-10-13) adds the stands section and writes down the conditions the
|
||||
Version 3 (2026-10-14) adds the IMU calibration section. Version 2 (2026-10-13) adds the stands section and writes down the conditions the
|
||||
first run showed matter: engine off and handbrake on for 1–13, foot brake held for
|
||||
the handbrake step, neutral with the clutch up for the revs.
|
||||
|
||||
@@ -80,18 +88,33 @@ The parked steps can be split over several sessions; the drive is the important
|
||||
## If OBD stays silent
|
||||
|
||||
`yukart/system/obd-poller` says why (visible in `mosquitto_sub -v -t 'yukart/system/#'`
|
||||
on the Orin):
|
||||
on the Orin), and the signal list's `elm_connected` shows the Bluetooth link:
|
||||
|
||||
- `bus idle: not polling`: no traffic: ignition off or PEAK unplugged.
|
||||
- `no ECU answers 01 00`: the engine ECU does not do standard mode 01 on this bus.
|
||||
Then OBDb's MUT-III (`21 xx`) requests are the next thing to try.
|
||||
- `ELM …: … (unplugged, asleep or out of range)`: no Bluetooth link. The ELM in the
|
||||
port? Its light on? A phone app holding it (it takes one connection)? Retried
|
||||
every minute.
|
||||
- `ECU not answering (…): ignition off?`: the ELM is there, the car is not. The
|
||||
adapter's own words are in the brackets (`BUS INIT: ...ERROR`, `NO DATA`).
|
||||
- `ECU silent for 60 s: adapter released`: ignition off for a minute; the poller let
|
||||
go so the ELM can sleep, and tries again every minute.
|
||||
- To see what answers, on the Orin: `sudo systemctl stop yukart-obd-poller`,
|
||||
`yukart-obd-poller --once` (supported PIDs and one value each, with reply times),
|
||||
`sudo systemctl start yukart-obd-poller`. Never two pollers at once: their
|
||||
replies would cross.
|
||||
`yukart-obd-poller --elm $(. /etc/default/yukart-elm; echo $ELM_ADDR) --once`
|
||||
(adapter, protocol, supported PIDs and one value each, with reply times), then
|
||||
`sudo systemctl start yukart-obd-poller`.
|
||||
|
||||
## Afterwards
|
||||
|
||||
**IMU calibration**, on the car Orin, from the session that holds steps 27–30:
|
||||
|
||||
```bash
|
||||
yukart-imu --calibrate /var/lib/yukart/recordings/<session> # print: down, forward, slope, spread
|
||||
yukart-imu --calibrate /var/lib/yukart/recordings/<session> --write # and save /var/lib/yukart/imu/mount.json
|
||||
```
|
||||
|
||||
The service picks the new mounting up within seconds; roll and pitch should then read
|
||||
about 0 parked on level ground. Steps 27–28 alone also work: forward then stays the
|
||||
`--forward` axis, laid flat, until a session with 29–30 is calibrated.
|
||||
|
||||
Sessions are in `/var/lib/yukart/recordings/` on the car Orin. Copy one off with
|
||||
`rsync -a mikkeli-orin-nano:/var/lib/yukart/recordings/<session>/ …` into
|
||||
`yukart-data`, with a line in its README of what was done.
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
type: report
|
||||
date: 2026-10-13
|
||||
---
|
||||
# Z27AG CAN: first decoding pass
|
||||
|
||||
Session `z27ag-20261013-170050-checklist` (yukart-data `can-captures/`), checklist v1,
|
||||
117 marks. Method: list every transition of every rarely-changing bit and read it
|
||||
against the marks; for blinking signals, count toggles inside each marked range
|
||||
against the seconds before it; for values, dump bytes across the marked range; for
|
||||
speed, correlate every 16-bit word with GNSS speed over the crawls. Marks lag the
|
||||
action by a fraction of a second to a few seconds (the operator presses after doing),
|
||||
so a change shortly *before* a start mark is normal.
|
||||
|
||||
Bit numbering: `ID.byte.bit`, byte 0 first, bit 7 the MSB.
|
||||
|
||||
## Found
|
||||
|
||||
| Signal | Where | Evidence | Confidence |
|
||||
|---|---|---|---|
|
||||
| Engine speed | `210` bytes 4–5, BE, 1 rpm | idle 740–870; holds at ~1410 and ~1900 for "1500" / "2000" (operator: revs not exact); blip peak 2887 | High |
|
||||
| Engine speed, finer | `13D` bytes 0–1, LE, ≈ rpm × 2.048 | moves in lockstep with `210` | High |
|
||||
| Accelerator pedal | `210` byte 0, 0x00 released … 0xFA full (÷2.5 → %) | engine-off sweep: 0 → 0xFA → 0 | High |
|
||||
| Accelerator sensors 1 and 2 | `139` bytes 0 and 1 (raw, 0x33 rest … 0xEE full, track each other) | same sweep | High |
|
||||
| Throttle-related | `139` byte 2 (0x21 … 0xD5) | same sweep; plate or target | Medium |
|
||||
| Pedal-pressed flag | `210` byte 3 bit 7 | set exactly while the pedal is off rest | Medium |
|
||||
| Brake pedal switch | `231.4.1` (1 = pressed) | 3/3 presses, plus the foot-brake holds around the handbrake step and the crawls | High |
|
||||
| Handbrake | `239.0.2` (1 = applied) | set through every engaged stretch, clear during the crawls and the handbrake releases | High |
|
||||
| Left indicator | `423.2.6` blinking | 2/2 | High |
|
||||
| Right indicator | `423.2.5` blinking | 2/2 | High |
|
||||
| Hazards | `423.2.6` only blinks, 2/2 | odd: `2.5` stays still. Maybe `2.6` is "left or hazard", maybe the hazard has its own bit elsewhere at a rate this method missed | Low |
|
||||
| Side lights | `423.2.2` and `570.7.3` (1 = on) | on/off and during dipped | High |
|
||||
| Dipped beam | `423.3.1` (1 = on) | 1/1 | Medium (one sample) |
|
||||
| Any door open | `423.2.1` | driver and passenger | Medium |
|
||||
| Driver door | `423.0.4` | driver only, not passenger | Medium |
|
||||
| Driver belt unbuckled | `573.5.7` (1 = unbuckled) | set at ignition on, cleared at buckle; no release seen | Low |
|
||||
| A/C request / blower | `443` bytes 1–2 and `711` bytes 5–6, multi-bit | change with A/C and blower; not separated yet | Low |
|
||||
| A/C compressor engaged | `13D.6.7` | engine running, A/C on; set ~0.5 s after the request, cleared with A/C off | Medium |
|
||||
| Four wheel speeds | `235` four 16-bit words (bytes 0–1, 2–3, 4–5, 6–7) | zero parked, all four move together in the crawls | High (signal), **scale open** |
|
||||
| Vehicle speed | `231` byte 6 (and probably byte 7) | tracks the wheel words | Medium |
|
||||
|
||||
**Wheel-speed scale.** Crawls topped out at ~6 km/h, and so far only the first byte of each word moved
|
||||
(0x4C at GNSS 3.5 km/h). Read as little-endian ×0.05 km/h (the forfour's `200`
|
||||
scale), that is 3.8 km/h, which is plausible given GNSS lag. Big-endian is not ruled out. The
|
||||
jack-stands session and a GNSS-matched drive settle both the byte order and the scale.
|
||||
|
||||
## Not on this bus (or not seen)
|
||||
|
||||
- **Clutch and transmission are not on this bus.** Nothing changed for the clutch
|
||||
(3 presses), any of the 5 gears, neutral or reverse: nothing on the car consumes
|
||||
them, so no frame carries them. Reverse was rechecked against both reverse
|
||||
stretches (engine off and engine on) versus every other position: no bit
|
||||
separates them.
|
||||
- **Gear is not inferred from rpm ÷ wheel speed** (owner's call, 2026-10-13): the
|
||||
clutch is invisible, so the ratio lies whenever it is down or slipping, and the
|
||||
gear matters most at a standstill, where the ratio says nothing. A *recommended*
|
||||
gear from speed and rpm is the useful form, if any.
|
||||
- **Steering angle:** not analysed yet (step 5 was done with the engine on, at the end).
|
||||
|
||||
## Not analysed yet
|
||||
|
||||
- `312` (four noisy 16-bit words that follow the throttle: MAP/load/air candidates)
|
||||
- `449` temperatures (coolant candidate), `710`–`713` slow body/meter frames
|
||||
- `0C0`, `119`, `149`, `156` (counters/checksums; `149` inertial candidate)
|
||||
|
||||
## Scripts
|
||||
|
||||
Scratch analysis for now: a session loader, a transition timeline, a blink counter and a
|
||||
GNSS correlator, in Python with numpy. They become a tool once a DBC exists to check
|
||||
against.
|
||||
+335
-19
@@ -1,17 +1,7 @@
|
||||
{
|
||||
"$comment": "Single source for signal identity. Topic name and envelope unit are both derived from these entries and are never authored separately. source=obd2 is standardised; source=z27ag is reverse-engineered and lives in the DBC. source=host is the Orin itself (orin-status), not the car.",
|
||||
"$comment": "Single source for signal identity. Topic name and envelope unit are both derived from these entries and are never authored separately. source=obd2 is standardised (OBD-II mode 01 over the K-line, through the ELM327): calibration references, every name prefixed obd_ (project-yukart decision 30); source=host is the Orin itself (orin-status), not the car. source=gnss is the receiver (svc-core gnss), on yukart/gnss/<signal>. source=imu is the WT61 IMU, already turned into the car's frame (mounting and gravity handled by its publisher), on yukart/imu/<signal>. source=z27ag is reverse-engineered from the car's own broadcast frames, and its 'can' block is the only place its layout is written down: id (11-bit, hex string), byte (first data byte, 0-7), length in bits (1, 8 or 16), bit (length 1 only: 0 = LSB of that byte), order (length 16: big = byte first is most significant, little = the reverse), scale and offset (value = raw * scale + offset; booleans are raw != 0). 'evidence' names the contracts report that found it.",
|
||||
"signals": {
|
||||
"engine_rpm": {
|
||||
"unit": "rpm",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Engine speed",
|
||||
"range": [
|
||||
0,
|
||||
8000
|
||||
]
|
||||
},
|
||||
"vehicle_speed_kph": {
|
||||
"obd_vehicle_speed_kph": {
|
||||
"unit": "kph",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -21,7 +11,7 @@
|
||||
255
|
||||
]
|
||||
},
|
||||
"coolant_temp_c": {
|
||||
"obd_coolant_temp_c": {
|
||||
"unit": "celsius",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -31,7 +21,7 @@
|
||||
215
|
||||
]
|
||||
},
|
||||
"intake_air_temp_c": {
|
||||
"obd_intake_air_temp_c": {
|
||||
"unit": "celsius",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -41,7 +31,7 @@
|
||||
215
|
||||
]
|
||||
},
|
||||
"throttle_pct": {
|
||||
"obd_throttle_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -51,7 +41,7 @@
|
||||
100
|
||||
]
|
||||
},
|
||||
"engine_load_pct": {
|
||||
"obd_engine_load_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -61,7 +51,7 @@
|
||||
100
|
||||
]
|
||||
},
|
||||
"fuel_level_pct": {
|
||||
"obd_fuel_level_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -71,7 +61,7 @@
|
||||
100
|
||||
]
|
||||
},
|
||||
"intake_pressure_kpa": {
|
||||
"obd_intake_pressure_kpa": {
|
||||
"unit": "kpa",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -81,7 +71,7 @@
|
||||
255
|
||||
]
|
||||
},
|
||||
"maf_gps": {
|
||||
"obd_maf_gps": {
|
||||
"unit": "g/s",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
@@ -91,6 +81,210 @@
|
||||
656
|
||||
]
|
||||
},
|
||||
"obd_engine_rpm": {
|
||||
"unit": "rpm",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Engine speed (OBD-II 0C): the reference for the decoded engine_rpm",
|
||||
"range": [
|
||||
0,
|
||||
8000
|
||||
]
|
||||
},
|
||||
"obd_timing_advance_deg": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Ignition timing advance before TDC, cylinder 1",
|
||||
"range": [
|
||||
-64,
|
||||
64
|
||||
]
|
||||
},
|
||||
"obd_stft_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Short-term fuel trim, bank 1: positive adds fuel",
|
||||
"range": [
|
||||
-100,
|
||||
100
|
||||
]
|
||||
},
|
||||
"obd_ltft_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Long-term fuel trim, bank 1: positive adds fuel",
|
||||
"range": [
|
||||
-100,
|
||||
100
|
||||
]
|
||||
},
|
||||
"obd_o2_b1s1_v": {
|
||||
"unit": "V",
|
||||
"type": "number",
|
||||
"source": "obd2",
|
||||
"description": "Upstream oxygen sensor voltage (narrowband: ~0.1 lean … ~0.9 rich)",
|
||||
"range": [
|
||||
0,
|
||||
1.275
|
||||
]
|
||||
},
|
||||
"engine_rpm": {
|
||||
"unit": "rpm",
|
||||
"type": "number",
|
||||
"source": "z27ag",
|
||||
"description": "Engine speed",
|
||||
"range": [
|
||||
0,
|
||||
8000
|
||||
],
|
||||
"can": {
|
||||
"id": "0x210",
|
||||
"byte": 4,
|
||||
"length": 16,
|
||||
"order": "big",
|
||||
"scale": 1,
|
||||
"offset": 0,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"accel_pedal_pct": {
|
||||
"unit": "percent",
|
||||
"type": "number",
|
||||
"source": "z27ag",
|
||||
"description": "Accelerator pedal position (0x00 at rest, 0xFA flat)",
|
||||
"range": [
|
||||
0,
|
||||
100
|
||||
],
|
||||
"can": {
|
||||
"id": "0x210",
|
||||
"byte": 0,
|
||||
"length": 8,
|
||||
"scale": 0.4,
|
||||
"offset": 0,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"brake_pedal": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Brake pedal switch: pressed",
|
||||
"can": {
|
||||
"id": "0x231",
|
||||
"byte": 4,
|
||||
"bit": 1,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"handbrake": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Handbrake applied",
|
||||
"can": {
|
||||
"id": "0x239",
|
||||
"byte": 0,
|
||||
"bit": 2,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"indicator_left": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Left indicator lamp, as it flashes (on and off at the flasher's rate)",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 2,
|
||||
"bit": 6,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"indicator_right": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Right indicator lamp, as it flashes. Hazards were seen on the left bit only: open",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 2,
|
||||
"bit": 5,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"side_lights": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Side (position) lights on; also on with dipped beam",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 2,
|
||||
"bit": 2,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"dipped_beam": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Dipped headlights on",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 3,
|
||||
"bit": 1,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"door_open": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Any door open",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 2,
|
||||
"bit": 1,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"driver_door_open": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "Driver's door open",
|
||||
"can": {
|
||||
"id": "0x423",
|
||||
"byte": 0,
|
||||
"bit": 4,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"ac_compressor": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "z27ag",
|
||||
"description": "A/C compressor engaged (engine running)",
|
||||
"can": {
|
||||
"id": "0x13D",
|
||||
"byte": 6,
|
||||
"bit": 7,
|
||||
"length": 1,
|
||||
"evidence": "Z27AG-DECODE-1"
|
||||
}
|
||||
},
|
||||
"orin_cpu_temp_c": {
|
||||
"unit": "celsius",
|
||||
"type": "number",
|
||||
@@ -333,6 +527,12 @@
|
||||
10000
|
||||
]
|
||||
},
|
||||
"elm_connected": {
|
||||
"unit": "",
|
||||
"type": "boolean",
|
||||
"source": "host",
|
||||
"description": "Bluetooth link to the OBD-II adapter (the ELM327 on the K-line) is up: obd-poller holds it while the ECU answers"
|
||||
},
|
||||
"ups_battery_v": {
|
||||
"unit": "V",
|
||||
"type": "number",
|
||||
@@ -368,6 +568,122 @@
|
||||
"type": "string",
|
||||
"source": "host",
|
||||
"description": "charging, discharging (running on battery) or idle (on input power, not charging)"
|
||||
},
|
||||
"gnss_fix": {
|
||||
"unit": "",
|
||||
"type": "string",
|
||||
"source": "gnss",
|
||||
"description": "Fix quality: none, 2d or 3d (gpsd TPV mode)"
|
||||
},
|
||||
"gnss_speed_kph": {
|
||||
"unit": "kph",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Speed over ground; null without a fix",
|
||||
"range": [
|
||||
0,
|
||||
300
|
||||
]
|
||||
},
|
||||
"gnss_heading_deg": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Course over ground, true north; null without a fix or at a standstill",
|
||||
"range": [
|
||||
0,
|
||||
360
|
||||
]
|
||||
},
|
||||
"gnss_lat": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Latitude, WGS84",
|
||||
"range": [
|
||||
-90,
|
||||
90
|
||||
]
|
||||
},
|
||||
"gnss_lon": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Longitude, WGS84",
|
||||
"range": [
|
||||
-180,
|
||||
180
|
||||
]
|
||||
},
|
||||
"gnss_alt_m": {
|
||||
"unit": "m",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Altitude above mean sea level; null without a 3D fix",
|
||||
"range": [
|
||||
-500,
|
||||
9000
|
||||
]
|
||||
},
|
||||
"gnss_satellites": {
|
||||
"unit": "",
|
||||
"type": "number",
|
||||
"source": "gnss",
|
||||
"description": "Satellites used in the fix",
|
||||
"range": [
|
||||
0,
|
||||
64
|
||||
]
|
||||
},
|
||||
"imu_roll_deg": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "imu",
|
||||
"description": "Body roll in the car's frame: positive leaning right (right side down)",
|
||||
"range": [
|
||||
-180,
|
||||
180
|
||||
]
|
||||
},
|
||||
"imu_pitch_deg": {
|
||||
"unit": "degree",
|
||||
"type": "number",
|
||||
"source": "imu",
|
||||
"description": "Body pitch in the car's frame: positive nose up",
|
||||
"range": [
|
||||
-90,
|
||||
90
|
||||
]
|
||||
},
|
||||
"imu_accel_lon_g": {
|
||||
"unit": "g",
|
||||
"type": "number",
|
||||
"source": "imu",
|
||||
"description": "Longitudinal acceleration in the car's frame, gravity removed: positive forward (speeding up), negative braking",
|
||||
"range": [
|
||||
-4,
|
||||
4
|
||||
]
|
||||
},
|
||||
"imu_accel_lat_g": {
|
||||
"unit": "g",
|
||||
"type": "number",
|
||||
"source": "imu",
|
||||
"description": "Lateral acceleration in the car's frame, gravity removed: positive to the right (a right turn reads positive)",
|
||||
"range": [
|
||||
-4,
|
||||
4
|
||||
]
|
||||
},
|
||||
"imu_yaw_rate_dps": {
|
||||
"unit": "degree/s",
|
||||
"type": "number",
|
||||
"source": "imu",
|
||||
"description": "Yaw rate: positive turning left (counter-clockwise from above)",
|
||||
"range": [
|
||||
-500,
|
||||
500
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -12,7 +12,7 @@
|
||||
"payload": "envelope",
|
||||
"retained": true,
|
||||
"rate": "1-50/s",
|
||||
"publisher": "decoder, obd-poller",
|
||||
"publisher": "decoder (source z27ag), obd-poller (source obd2)",
|
||||
"description": "One topic per signal, named exactly as in signals.json."
|
||||
},
|
||||
"yukart/gnss/fix": {
|
||||
@@ -22,6 +22,27 @@
|
||||
"publisher": "gnss",
|
||||
"description": "value is an object: lat, lon, alt_m, speed_kph, heading_deg, fix, satellites."
|
||||
},
|
||||
"yukart/gnss/<signal>": {
|
||||
"payload": "envelope",
|
||||
"retained": true,
|
||||
"rate": "1-10/s",
|
||||
"publisher": "gnss",
|
||||
"description": "The receiver's fix as single values, one topic per signal, named exactly as in signals.json (source=gnss). For displays; yukart/gnss/fix stays the composite for navigation."
|
||||
},
|
||||
"yukart/imu/<signal>": {
|
||||
"payload": "envelope",
|
||||
"retained": true,
|
||||
"rate": "10-50/s",
|
||||
"publisher": "imu",
|
||||
"description": "The IMU (WT61) in the car's frame: attitude, gravity-free acceleration, yaw rate; one topic per signal, named exactly as in signals.json (source=imu)."
|
||||
},
|
||||
"yukart/raw/imu": {
|
||||
"payload": "json",
|
||||
"retained": false,
|
||||
"rate": "10-100/s",
|
||||
"publisher": "imu",
|
||||
"description": "Every IMU sample, raw: module axes, not calibrated. {mono (ns, CLOCK_MONOTONIC), t (µs, realtime), accel [x,y,z] g, gyro [x,y,z] deg/s, angle [roll,pitch,yaw] deg (the module's own)}. Not an envelope; for the recorder (imu.ndjson), so a later calibration can reprocess a session. Displays use yukart/imu/<signal>."
|
||||
},
|
||||
"yukart/host/<signal>": {
|
||||
"payload": "envelope",
|
||||
"retained": true,
|
||||
|
||||
Reference in New Issue
Block a user