robot_context.hpp¶
RobotContext — the composition root / DI container: "the one object that differs across robot / sim / test".
This header declares 2 types (17 members).
Extracted from include/shulib/chassis/robot_context.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.
Contents¶
struct RobotContextConfigclockdriveMotorsimugpsbatterytelemetrytagsvisionclass RobotContextRobotContextclockdriveMotorsimugpsbatterytelemetrytagsvision
struct RobotContextConfig¶
The HAL handles a robot is built from. Pointers so fields are NAMED at the call site (designated initializers) and so the RobotContext can validate them non-null.
struct, declared at include/shulib/chassis/robot_context.hpp:32.
RobotContextConfig::clock¶
the single source of now; seconds, monotonic
field, declared at include/shulib/chassis/robot_context.hpp:33.
RobotContextConfig::driveMotors¶
The drive motors, in kinematic wheel order: element i is commanded with wheel speed i of the installed IKinematics, so a wrong order drives the robot the wrong way in silence. The caller must supply at least as many motors as that kinematics has wheels — nothing checks the count. This is a non-owning VIEW: the pointer ARRAY must outlive the context.
field, declared at include/shulib/chassis/robot_context.hpp:38.
RobotContextConfig::imu¶
heading and yaw rate, canonical CCW radians
field, declared at include/shulib/chassis/robot_context.hpp:39.
RobotContextConfig::gps¶
absolute fix; off-strip its hasFix() reads false
field, declared at include/shulib/chassis/robot_context.hpp:40.
RobotContextConfig::battery¶
volts: the pipeline's ceiling, and the run bookends
field, declared at include/shulib/chassis/robot_context.hpp:41.
RobotContextConfig::telemetry¶
every log line and DebugRecord; NullSink = off
field, declared at include/shulib/chassis/robot_context.hpp:42.
RobotContextConfig::tags¶
AprilTags as body-frame poses (the M3 corrector)
field, declared at include/shulib/chassis/robot_context.hpp:43.
RobotContextConfig::vision¶
object bearings for M4 manipulation targeting
field, declared at include/shulib/chassis/robot_context.hpp:44.
class RobotContext¶
The composition root: the ONE object that differs between the real robot, the simulator and a host test. Every layer above the HAL reaches hardware only through it, so exchanging the HAL implementations exchanges the whole robot without touching a line of motion code. NON-OWNING throughout. It copies the config's pointers and span; it never adopts, allocates or destroys anything, so every pointee — and the array the driveMotors span views — must outlive the context. It also caches nothing: each accessor hands back the live handle, so a reading is only ever as fresh as the caller's own call.
class, declared at include/shulib/chassis/robot_context.hpp:55.
RobotContext::RobotContext¶
Validates the whole config up front — every handle non-null and driveMotors non-empty — through SHULIB_PRECONDITION, so a mis-wired robot fails at construction naming the handle it is missing, instead of dereferencing null halfway through an auton. The count of drive motors is checked only for emptiness, never against the kinematics' wheel count.
function, declared at include/shulib/chassis/robot_context.hpp:61.
RobotContext::clock¶
The run's clock. A reference, never null — the constructor already proved that, which is why consumers write ctx.clock().now() and never test a pointer.
function, declared at include/shulib/chassis/robot_context.hpp:77.
RobotContext::driveMotors¶
The drive motors, in kinematic wheel order. A VIEW of the caller's array, so it is only as alive as that array; guaranteed non-empty, but NOT guaranteed to match the wheel count of the installed kinematics — that pairing is the caller's to get right.
function, declared at include/shulib/chassis/robot_context.hpp:81.
RobotContext::imu¶
The IMU, already canonical: CCW-positive radians, +X = 0. Nothing above this call converts an angle. Gate trust on isReady() at boot — a calibrating IMU reports garbage that moves.
function, declared at include/shulib/chassis/robot_context.hpp:84.
RobotContext::gps¶
The GPS. Check hasFix() before believing pose(): off-strip the pose is unspecified (still finite), and Driving Skills has no strip at all, so this seam is silent for a whole run.
function, declared at include/shulib/chassis/robot_context.hpp:87.
RobotContext::battery¶
The battery. Read live at each use — the command pipeline takes its voltage ceiling from it every tick and the run summary samples it at both ends; nothing here caches a volt.
function, declared at include/shulib/chassis/robot_context.hpp:90.
RobotContext::telemetry¶
The one diagnostics sink for this robot. Which sink is installed is what decides whether tracing costs anything: with NullSink the per-tick record is never even populated.
function, declared at include/shulib/chassis/robot_context.hpp:93.
RobotContext::tags¶
The AprilTag source — V5 AI Vision or a coprocessor, indistinguishable from here. Tags arrive as body-frame poses with no timestamp; staleness is the corrector's problem.
function, declared at include/shulib/chassis/robot_context.hpp:96.
RobotContext::vision¶
The object/colour detection source. A separate seam from tags() so one adapter can serve both, or either alone, without a consumer of one depending on the other.
function, declared at include/shulib/chassis/robot_context.hpp:99.
Design commentary, from the header¶
The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.
The header’s own reasoning — 14 lines
RobotContext — the composition root / DI container: "the one object that differs across
robot / sim / test" (master plan §5). Every layer above L0 (Chassis, Localizer, motion,
skills) reads hardware ONLY through here, so swapping the HAL implementations
(hal/fake ↔ hal/pros ↔ hal/sim) swaps the whole robot without touching a line of motion
code — which is exactly the M1 Definition of Done.
L3, PROS-free: it sees only the L0 interfaces. NOT part of the F4 freeze — it grows
additively as M3/M4 consumers need more sensors (distance / optical / tracking-wheel
arrays), so adding fields here later is safe.
Built from a RobotContextConfig of NAMED pointers (designated initializers at the call
site); the constructor validates them all non-null, then the accessors hand out
references so consumers write `ctx.clock().now()` rather than juggling pointers.
Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.