Engineering Blog
micro-ROS Impedance Control ROS 2 Joint Control

Implementing Joint Impedance Control with micro-ROS

James Whitaker 11 min read
micro-ROS node architecture diagram on whiteboard in robotics lab with actuator hardware nearby

A torque-controlled joint is stiff by default. Every disturbance from the environment gets reflected back through the mechanism as a force — on a rigid environment, that's fine; on a human collaborator or a compliant surface, it's a collision waiting to happen. Joint impedance control replaces that stiffness with a programmable mechanical response: the joint behaves as if it has a defined spring and dashpot in parallel, with gains you set at runtime. This post covers the theory as we've implemented it in the TK firmware, the micro-ROS parameter interface, and the practical gain ranges that are actually stable on real hardware.

Impedance vs. Admittance: Choosing the Control Architecture

Both impedance control and admittance control produce compliant behavior, but they impose opposite causality structures on the control loop. Understanding which to use is not a stylistic choice — it's determined by the sensors you have and the mechanical plant you're controlling.

Admittance control takes a measured force or torque as input and produces a commanded motion as output. The controller is a mechanical admittance: given this force, move this much. It requires a dedicated joint torque sensor in the loop — ideally a strain-gauge-based torque transducer on the output flange. Without a direct torque measurement, admittance control degrades into a noisy velocity regulator because you're estimating force from current with all the friction and cogging disturbances that entails.

Impedance control takes a commanded position as reference and produces a torque output as a function of position error and velocity error. It does not require a torque sensor. The controller is a mechanical impedance: given this position deviation, produce this restoring torque. The TK-120 and TK-240 implement impedance control by default because the architecture works cleanly on top of the inner torque (current) loop without additional hardware.

We're not saying admittance control is inferior. For exoskeleton applications where the human pushes against the robot and the robot must yield gracefully, admittance control with a wrist-level force-torque sensor produces more nuanced compliance behavior. Impedance control as we implement it is the practical choice for the majority of manipulation and locomotion tasks where ground-truth torque sensing is not available.

The Control Law: Virtual Stiffness and Damping

The joint-space impedance control law is straightforward. The commanded torque τ_cmd is a linear function of position error and velocity error relative to a reference trajectory:

// Joint impedance control law
// θ_ref: reference joint angle [rad]
// θ:     measured joint angle [rad]  (19-bit encoder, ~2.9 µrad resolution)
// dθ_ref/dt: reference velocity [rad/s]
// dθ/dt:     measured velocity [rad/s] (encoder differentiated + filtered)
// K_s:   virtual stiffness [Nm/rad]
// K_d:   virtual damping   [Nm·s/rad]
// τ_ff:  feed-forward torque [Nm]    (optional, from dynamics model)

τ_cmd = K_s * (θ_ref - θ) + K_d * (dθ_ref/dt - dθ/dt) + τ_ff;

The full torque-controlled joint — with the inner FOC current loop closing on τ_cmd — behaves as a second-order mechanical system. The natural frequency of the closed-loop impedance is approximately ω_n = sqrt(K_s / J_total) where J_total is the reflected inertia at the joint output. The damping ratio is ζ = K_d / (2 * sqrt(K_s * J_total)).

For the TK-120 with a 100:1 harmonic drive, the reflected rotor inertia at the output is about 0.008 kg·m² for a typical forearm-mass payload. A virtual stiffness of K_s = 80 Nm/rad gives a natural frequency around 100 rad/s (~16 Hz). With K_d = 2.0 Nm·s/rad, the damping ratio is approximately 0.14 — underdamped. For contact tasks, raising K_d to 8.0 Nm·s/rad brings it to critical damping at that stiffness level.

Exposing Gains as ROS 2 Parameters via micro-ROS

The practical value of impedance control in a ROS 2 pipeline is that stiffness and damping can be updated at runtime without reflashing firmware. We expose K_s, K_d, and the feed-forward torque scale as rclcpp parameters accessible through the standard parameter server interface.

The micro-ROS node on the STM32 subscribes to a parameter update topic and applies new gain values at the next control cycle. The latency from a ros2 param set call on the host to the gain taking effect on the actuator is bounded by one EtherCAT cycle (1 ms at 1 kHz fieldbus rate) plus micro-ROS DDS processing time — typically 2–4 ms total round trip.

# Launch file snippet: set impedance gains for a wrist joint
# Low stiffness for contact exploration

ros2 param set /tk120_wrist_node impedance_stiffness_nm_per_rad 30.0
ros2 param set /tk120_wrist_node impedance_damping_nms_per_rad  3.5
ros2 param set /tk120_wrist_node ff_torque_scale               0.8

# High stiffness for position-hold
ros2 param set /tk120_wrist_node impedance_stiffness_nm_per_rad 200.0
ros2 param set /tk120_wrist_node impedance_damping_nms_per_rad  12.0

There is one critical constraint on runtime gain changes: the damping gain must track the stiffness gain to maintain stability. If an operator raises K_s without proportionally raising K_d, the effective damping ratio drops and the joint can oscillate. The micro-ROS node includes a soft constraint that enforces a minimum damping ratio of 0.07 — requests that would violate it are saturated with a diagnostic warning on the /tk120_wrist_node/diagnostics topic.

Cartesian Compliance from Joint-Space Impedance

For a multi-joint manipulator, joint-space impedance control produces Cartesian compliance through the manipulator Jacobian. The Cartesian stiffness ellipsoid is K_cartesian = (J^T)^{-1} * K_joint * J^{-1} — it's direction-dependent and changes with configuration. An isotropic Cartesian stiffness requires configuration-varying joint gains, which MoveIt 2 does not handle automatically.

For typical manipulation tasks — pick-and-place, surface wiping, peg insertion — anisotropic Cartesian compliance is acceptable and often desirable. A joint near its singularity has effectively high compliance in certain directions anyway. The practical approach is to tune joint-space gains for the task class and verify Cartesian behavior experimentally at the critical workspace configurations.

A research group at an east-coast university evaluating the TK-120 and TK-240 for a 5-DOF table-top manipulator found that setting the shoulder joint at K_s = 120 Nm/rad and the wrist joint at K_s = 40 Nm/rad produced acceptable assembly-task compliance without requiring full Jacobian-based gain scheduling. The distal joints carry less inertia, so their lower stiffness produced equivalent Cartesian compliance to the stiffer proximal joints.

Stability Limits: Why High Stiffness Isn't Always Better

There's a common instinct to treat stiffness as "more is better" — a stiffer joint tracks position more accurately, right? The reality is more constrained. As K_s increases, the closed-loop natural frequency increases and eventually approaches the bandwidth of the inner torque loop. When the desired spring frequency reaches the torque loop bandwidth, the control law demands a torque rate that the current controller cannot track. Phase lag accumulates, gain margin erodes, and the joint oscillates at the current loop crossover frequency.

For the TK-120, the practical stiffness ceiling is around 400 Nm/rad with the default 400 Hz torque loop bandwidth. Above that, we observe limit cycles at approximately 60–80 Hz output. The ceiling scales with torque loop bandwidth — if you extend bandwidth to 600 Hz via careful resonance notching, the stiffness ceiling rises proportionally.

This is not a firmware limitation that will be resolved in a future release. It's a fundamental control-bandwidth constraint. Any joint actuator — regardless of supplier — faces this ceiling if the torque loop bandwidth is finite. The correct response is to characterize your specific system and establish a maximum K_s with margin, not to assume that the ceiling can be pushed indefinitely.

Transparency Ratio and Backdriveability in Impedance Mode

Impedance control at very low stiffness (K_s near zero) approaches zero-impedance control — the joint output appears frictionless and the environment can move it with minimal restoring force. This is the "gravity compensation only" mode used in kinesthetic teaching for trajectory recording.

In practice, zero-stiffness impedance does not produce a truly transparent joint because the friction in the harmonic drive and the cogging torque of the motor appear as disturbances that the impedance law does not cancel. Achieving genuine transparency requires active friction compensation in addition to the impedance law — a topic we cover separately in our backdrivability post.

The TK-120 in gravity-compensated impedance mode (K_s = 0, K_d = 1.5, τ_ff from a pre-loaded gravity model) requires about 0.7 Nm of external torque to initiate motion from rest — compared to 4.8 Nm in unpowered mechanical backdrive. That's a transparency ratio of approximately 6.9x improvement from active compensation. Useful for teaching, not sufficient for high-fidelity force reflection in teleoperation, where additional friction and disturbance observers are needed.