Phase 06 · Week 22 · 105 minutes

Day 151: Implement a ros2_control hardware plugin and lifecycle bring-up

Real hardware bring-up · Treat the physical robot as an unreliable distributed system.

Chapter 22 · Bring up real robot hardware through bounded, evidence-led gates

Today in the field story

One problem, then the next

The dossier becomes executable through a mock ros2_control component. It declares command and state interfaces, validates parameters, enters lifecycle states deliberately, bounds read and write work, reports faults, and produces safe application outputs without touching hardware. You plant wrong interface names, unavailable state, and failed activation while observing controller-manager behavior. This proves software ownership and failure handling only; a successful mock plugin says nothing about the real driver, electrical path, actuator, or machine.

Why now

Mock-first lifecycle tests expose integration defects before powered equipment exists.

Ignore today

Do not connect a device or call a mock result hardware validation.

Unlocks next

A tested software boundary ready for later qualified bring-up.

Understand

Build the physical picture first

A ros2_control hardware component is a typed lifecycle adapter between controller-owned interfaces and measured device I/O, not a safety controller or vendor-protocol dumping ground.

Choose the hardware component type from ownership. A Sensor exposes state but no command interface; an Actuator models a simple one-degree-of-freedom device; a System commonly owns a multi-joint robot or a group sharing one communication channel. The robot description declares the hardware plugin and named command and state interfaces. Fully qualified interface names couple a joint or component name to a type such as position, velocity, or effort. Those names, units, joint order, limits, and control mode must match the physical device contract exactly.

Use lifecycle callbacks to separate construction, configuration, readiness, active I/O, deactivation, cleanup, shutdown, and error handling. Initialization parses and validates the supplied hardware information. Configuration can create a communication object and verify an expected manifest while keeping application commands disabled. Activation verifies fresh state and prepares bounded command handling. Deactivation stops accepting active controller authority and moves application outputs to the documented non-hazardous state for the mock. None of these ordinary callbacks is an E-stop, STO, electrical isolation, brake, or certified protective function.

Keep the update path bounded and observable. read() obtains current measured device values and updates state interfaces; write() translates current command-interface values into the versioned device protocol. Validate finite values, mode, units, range, command age, device state, and communication outcome at the appropriate owner. Avoid dynamic allocation, blocking diagnostics, unbounded retry, long logging, or network discovery inside time-critical work. Publish slower diagnostics from a separate non-real-time path and measure read-update-write latency and missed cycles.

Treat failure as loss of evidence, not a reason to reuse stale success. A malformed configuration blocks initialization or configuration. Repeated or severe read failure means current state is no longer trustworthy; a write failure means command delivery or outcome may be unknown. Return an explicit error according to the framework and application design, invalidate or age state visibly, stop conflicting command progression, and enter the documented lifecycle or supervisor response. Independent safety functions remain responsible for hazards that ordinary host software cannot be trusted to control.

Words you need

Name each idea precisely

Hardware component

A dynamically loaded ros2_control plugin that represents a Sensor, Actuator, or System and mediates its state and command interfaces.

Physical example:

One differential-drive System plugin owns a shared CAN channel and exposes both wheel velocity commands plus wheel position and velocity states.

State interface

A named value populated from measured or device-reported state for controllers and broadcasters to consume.

Physical example:

left_wheel/position is updated from a validated encoder count converted to radians, with communication age tracked separately.

Command interface

A named value written by an active controller and consumed by the hardware component for a declared control mode.

Physical example:

right_wheel/velocity carries a rad/s request that the plugin bounds and encodes for the matching drive identity.

Lifecycle callback

A transition hook that gives configuration, activation, deactivation, cleanup, shutdown, and error work distinct entry and exit contracts.

Physical example:

Configuration verifies the mock device manifest; activation requires fresh state; deactivation zeros the mock application command and releases its simulated lease.

Resource Manager

The ros2_control owner that loads hardware plugins, manages their lifecycle and interfaces, and provides those resources to eligible controllers.

Physical example:

A controller cannot claim left_wheel/velocity if the loaded plugin did not export that exact command resource or another active controller already owns it.

Math, one line at a time

Work through today’s relationship

Prerequisite rescue · optionalZero-power electricity bridge: voltage, current, resistance, and power

Before buying, wiring, or energizing hardware, use paper calculations and manufacturer documentation to detect impossible loads, overheated conductors, and incompatible supplies.

V = IR
voltage equals current multiplied by resistanceUnit: volts (V)
P = VI
electrical powerUnit: watts (W)
I
charge flow through one declared pathUnit: amperes (A)
  1. On paper, a documented 12 Ω test load across 24 V would draw I = V/R = 24/12 = 2 A.

  2. Its electrical power would be P = VI = 24×2 = 48 W, so an ordinary low-power resistor would be unsuitable even though the arithmetic is simple.

  3. Stop at the calculation: do not assemble or energize the circuit. Verify ratings, protection, isolation, polarity, grounding, wiring, thermal limits, and a supervised low-voltage commissioning plan with qualified guidance.

Programmer analogy

Types and range checks catch bad values in software; electrical ratings are physical contracts whose violation can create heat, fire, shock, or loss of braking.

On paper, what current would an ideal 10 Ω load draw from 5 V?

I = V/R = 5/10 = 0.5 A; this calculation is not permission to build or energize a circuit.

At 200 Hz200\ \mathrm{Hz},

T=1200=5 ms.T=\frac{1}{200}=5\ \mathrm{ms}.

The p99 path is 1.2+2.1+1.0=4.3 ms1.2+2.1+1.0=4.3\ \mathrm{ms}, leaving

mp99=5.04.3=0.7 ms.m_{p99}=5.0-4.3=0.7\ \mathrm{ms}.

Design a fault-aware mock differential-drive plugin

A disconnected test package represents two wheel drives. The exact resources are left and right velocity commands in rad/s and left and right position and velocity state in radians and rad/s. No real transport or motor is present.

  1. Choose a System component because one simulated communication owner serves both joints, then declare the exact joint names, allowed state and command interfaces, units, bounds, update period, and expected mock manifest.

  2. In initialization, call the parent contract and reject missing joints, duplicate names, unsupported interfaces, non-finite parameters, wrong units, invalid limits, or an unexpected component type before creating communication state.

  3. In configuration, instantiate only the mock transport, compare its identity and protocol manifest, initialize state to a declared unavailable or known fixture condition, and keep command authority disabled.

  4. In activation, require a configured transport and a fresh successful mock read, initialize command buffers from a non-hazardous application default, and begin the simulated command lease without describing the transition as a safety enable.

  5. Implement bounded read() conversion from mock encoder values to the four state interfaces and bounded write() conversion from two finite, current, in-range rad/s commands to one versioned message; collect timing outside the hot path.

  6. Implement deactivation, cleanup, shutdown, and error behavior; inject stale read, malformed state, rejected write, and delayed cycle cases, ensuring no stale value is silently relabelled current and no infinite retry occurs.

  7. Export the class through pluginlib metadata and write load, interface, lifecycle, conversion, fault, and timing tests using only the mock Resource Manager path; record which hardware and safety claims remain entirely unverified.

Result

The mock component can be loaded, exports only the declared resources, follows lifecycle transitions, converts typed values, exposes injected failures, and leaves all powered and safety behavior outside the evidence claim.

What this proves

A hardware plugin succeeds when ownership, interfaces, lifecycle, I/O timing, and error semantics are inspectable; loading the library or moving a mock is only the beginning.

Physical examples

Where this appears in real life

Two-wheel mock System

A single simulated transport owns left and right drive state. The plugin exports wheel velocity commands and position and velocity states, then injects delay, dropped reads, and rejected writes.

Look for:

Joint names, order, units, lifecycle, timestamps, error returns, and command defaults remain explicit; mirrored state is identified as a mock model rather than encoder evidence.

Read-only force sensor

A wrist force-torque device provides six measured channels and diagnostics but receives no physical command from ros2_control.

Look for:

A Sensor component fits the ownership better than inventing writable interfaces; state freshness and calibration identity accompany the values.

Hands-on exercise

Make the idea observable

Use the existing ROS 2 workspace or a paper class-and-state model plus a mock transport. Do not connect a USB adapter, field bus, drive, encoder, E-stop circuit, or actuator.

  1. Write the exact Sensor, Actuator, or System choice and justify it from physical communication ownership rather than from which template is shortest.

  2. Define hardware information for two mock joints with names, command and state types, units, ranges, component identity, protocol version, and update period.

  3. Implement or pseudocode initialization and every lifecycle callback with entry conditions, success state, failure state, resources acquired, and resources released.

  4. Implement a deterministic mock read() and write() with finite-value, name, unit, range, freshness, and protocol checks; keep diagnostics and deliberate delay outside the nominal hot path.

  5. Test load, exported resources, configure, activate, deactivate, cleanup, shutdown, and error transitions, then inject missing interface, stale read, rejected write, and period overrun.

  6. Create an evidence table separating plugin behavior verified in mock, device protocol not verified, powered motion not verified, and safety functions not verified.

Observe

Most plugin defects are contract defects—wrong names, units, ordering, lifecycle assumptions, stale state, blocking I/O, or ambiguous faults—before they become vendor-protocol defects.

Done when

The mock plugin's resource and lifecycle tests pass, each injected fault produces a bounded explicit result, and the report makes no real-device, real-time, motion, or safety claim.

Build today

Bring up a LeRobot-supported arm or mobile robot with calibration, limits, teleoperation, and emergency stop.

Evidence to save

DONE when the integrated “Implement a ros2_control hardware plugin and lifecycle bring-up” path is observable, cancelable, and leaves the prior baseline reproducible.

Common mistakes

Catch the wrong mental model

Wrong

Calling on_deactivate() or a zero command an emergency stop.

Better

Describe it as ordinary application and framework behavior; separately identify the risk-derived, independently implemented and validated protective and emergency functions.

Wrong

Running discovery, unbounded retry, or verbose logging inside read() and write().

Better

Keep the control path bounded, move diagnostics to a non-real-time owner, count failures and latency, and enter an explicit supervisor or lifecycle response.

Wrong

Keeping the last state value without exposing that reads have failed.

Better

Track age and validity, report the error, stop treating stale state as current evidence, and follow the application's designed degraded or disabled transition.

Job connection

How this becomes employable evidence

Build and review ros2_control hardware plugins that map exact robot resources to vendor or simulated transports, keep lifecycle and update timing bounded, expose diagnostics, and produce a mock-to-HIL-to-restricted-hardware evidence ladder for field commissioning.

Relevant target roles

  • Robotics Application / ROS 2 Integration Engineer
  • Robotics Software Engineer — ROS 2 / AMR
  • Robotics Deployment, Integration & Validation Engineer

Chapter 22 interview drill

Interview questions: Implement a ros2_control hardware plugin and lifecycle bring-up

Practise a 60–90 second answer: define the idea, connect it to a physical robot, state assumptions, frames, and units when relevant, then finish with the failure signal or evidence you would inspect.

Primary interview scenario

Design a ros2_control plugin for a two-wheel base sharing one CAN interface. Choose the component type, name resources, explain lifecycle and read/write behavior, handle stale reads and uncertain writes, and separate deactivation from E-stop or STO.

Answer shape: clarify the situation → trace the physical and software path → test the most likely boundaries → name the evidence that would confirm the result.

Technical follow-up questions

Q1When does a ros2_control System component usually fit better than two Actuator components?
Model interview answer

When multiple joints form one logical device or share communication, lifecycle, transmission, or state ownership that should be managed coherently.

Q2What are the distinct jobs of `read()` and `write()`?
Model interview answer

read() obtains and validates measured device state for state interfaces; write() validates and translates current command-interface values into the device protocol.

Q3What does a successful plugin load prove?
Model interview answer

Only that metadata and library loading reached that test point; it does not prove correct interfaces, timing, protocol, physical motion, fault containment, or any safety function.