Getting started

Build

In a ROS 2 Humble workspace containing this repo and kontrolem_example_robots:

colcon build --packages-up-to kontrolem_controllers
source install/setup.bash

Run the LQR demo (mock hardware)

ros2 launch lqr_controller lqr_demo.launch.py

The controller manager comes up on mock_components/GenericSystem, spawns the joint-state broadcaster, then activates lqr_controller, which loads the exported artifact and starts writing effort commands. This is a plumbing proof — mock hardware has no dynamics, so nothing is stabilized here. For real physics see Gazebo Fortress physics validation (headless, runs in CI) or Isaac Sim physics validation (local GPU).

How a controller finds its artifact

Every controller takes an artifact_path parameter. It accepts a plain filesystem path or a package://<pkg>/<relative/path> URI resolved against the ament index at configure time — prefer the latter in installed configs so the YAML is independent of the install prefix:

lqr_controller:
  ros__parameters:
    artifact_path: package://lqr_controller/config/lqr_cart_double_pendulum_ros2_control.yaml

Standalone vs chained

Each controller is a ChainableControllerInterface:

  • Standalone — it reads its setpoint from the ~/reference topic (std_msgs/Float64MultiArray, one value per reference interface, absolute units) and writes effort commands to hardware. Defaults regulate to the operating point.

  • Chained — an upstream controller writes the exported per-output reference interfaces (<controller>/<joint>/position, .../velocity). The cascade is declared entirely in the controller manager YAML with a stock upstream controller; no custom code. See Chaining.

Validity guard

The linearized gains are only trusted near the operating point. Each controller enforces a per-joint bound on |q q_eq| (and optionally |q̇|); leaving the region triggers a configurable safe action (hold_u_eq, zero_command, or deactivate). Bound precedence: per-joint parameter > artifact validity_region

global validity.q_dev_max_default.

Tests

colcon test --packages-select \
  kontrolem_controllers_base lqr_controller lqg_controller hinf_controller
colcon test-result --verbose

The suite covers the artifact loader, the numeric cores (incl. Python↔C++ equivalence traces), the validity guard, an allocation-free realtime check, and per-controller load + functional + mock-hardware launch tests (plus an LQR cascade launch test).