Skip to content

Add OTOS calibration tool - #203

Open
gdoffe wants to merge 5 commits into
masterfrom
202-add-otos-calibration-tool
Open

Add OTOS calibration tool#203
gdoffe wants to merge 5 commits into
masterfrom
202-add-otos-calibration-tool

Conversation

@gdoffe

@gdoffe gdoffe commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

New cogip-otos-calibration CLI under cogip/tools/firmware_otos_calibration/ that mirrors the structure of firmware_odometry_calibration but drives the two OTOS scalars exposed by the firmware (cogip/mcu-firmware#243).

Two calibration phases driven through the /calibration SocketIO namespace:

  1. Linear scalar: reset OTOS pose to (0, 0, 0), command a straight line of N mm, prompt the operator for the physically measured distance, new = current * measured / commanded, clamp to [0.872, 1.127], write back.
  2. Angular scalar: reset to (0, 0, 0), command N full in-place turns (four 90° sub-moves per turn so the control loop takes the short path), prompt for the actually rotated angle, same ratio, write back.

Reuses the existing FirmwareParameterManager, ConsoleUI, and the pose_start / pose_order / pose_reached motion pattern. No change to server, copilot or planner apart from the MotionDirection re-export below.

Also in this PR

  • models: export MotionDirection from cogip.modelscopilot/sio_events.py:on_pose_order was referencing models.MotionDirection.FORWARD_ONLY without importing it directly, so every pose_order sent on SocketIO crashed silently with AttributeError (systemd StandardOutput=null on the robot hid the traceback). test_squares kept working because it goes through the shared-memory path in copilot.py, which uses the C++ import directly. Re-exporting the enum fixes the SocketIO pose_order flow without touching copilot.
  • tools: firmware_otos_calibration: shorten straight-line timeout to 10s — 60 s masked silent stalls; a 1000 mm straight-line completes in ~3 s.

Depends on

Closes

Closes #202.

ecourtois and others added 5 commits April 18, 2026 09:43
…nsumers

Replace the global `consumer_count_` and single `sem_update_` semaphore
with a shared memory array of up to 32 consumer PIDs (`consumer_pids_`)
and dedicated per-PID semaphores (e.g., `/<name>_update_<PID>`).

This prevents ghost processes (e.g., consumers that crashed or were
killed abruptly) from desynchronizing the update signals for other
active consumers.

Key changes:
- Implement ghost process cleanup in `registerConsumer()`
  using `kill(pid, 0)` to detect dead processes, reclaim their slots,
  and unlink orphaned semaphores.
- Update `postUpdate()` to signal each registered PID individually.
- Add an `unordered_map` cache (`update_sems_cache_`) in `postUpdate()`
  to store opened semaphores, ensuring the hot path remains extremely fast
  without syscall overhead.
- Ensure graceful cleanup of semaphores and PID slots in the destructor.

Signed-off-by: Eric Courtois <eric.courtois@gmail.com>
Pydantic OTOSParameters / OTOSCalibrationResult pair and the
OTOS_SCALAR_MIN / OTOS_SCALAR_MAX bounds (0.872 / 1.127, per the OTOS
spec). Used by the upcoming firmware_otos_calibration tool to read the
current sensor scalars from firmware, clamp computed values to the
allowed range, and write the corrected ones back.

Signed-off-by: Gilles DOFFE <g.doffe@gmail.com>
Host-side calibration tool for the SparkFun OTOS sensor, published as
the cogip-otos-calibration entrypoint. Two phases:

- Linear scalar: drive a commanded straight line, ask the operator
  for the physically measured distance, derive the corrected
  linear_scalar and write it back.
- Angular scalar: rotate N full turns, ask the operator for the
  physically measured rotation, derive the corrected angular_scalar
  and write it back.

Motion is sent via the existing /calibration SocketIO namespace
(pose_start + pose_order + pose_reached). Parameters are read and
written through FirmwareParameterManager against the new OTOS
parameter keys exposed by the firmware. Computed scalars are clamped
to the OTOS allowed range [0.872, 1.127]; out-of-range results raise
a console warning pointing at a mechanical issue.

Signed-off-by: Gilles DOFFE <g.doffe@gmail.com>
copilot.sio_events.on_pose_order references models.MotionDirection.FORWARD_ONLY
without importing it directly, so the handler raised AttributeError and crashed
silently the moment any tool sent a pose_order on SocketIO (systemd StandardOutput=null
hid the traceback). test_squares kept working only because it goes through the
shared-memory path in copilot.py, which uses the C++ import explicitly.

Re-exporting the enum from the models package fixes the calibration tools
pose_order flow without touching the copilot code.

Signed-off-by: Gilles DOFFE <g.doffe@gmail.com>
A 1000 mm straight-line calibration move completes in ~3 s at the default
speed ratio. A 60 s timeout masked the silent pose_order failure for a full
minute each time, and added nothing once the move is actually wired through.
10 s leaves comfortable margin without hiding stalls.

Signed-off-by: Gilles DOFFE <g.doffe@gmail.com>
@gdoffe gdoffe linked an issue Apr 20, 2026 that may be closed by this pull request
@gdoffe
gdoffe force-pushed the 202-add-otos-calibration-tool branch from 74431eb to 9706b5d Compare April 20, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add OTOS calibration tool

2 participants