Subsystem Control
What the Control subsystem does
The Control layer is responsible for turning high-level goals from the Brain into precise actuator commands and streaming sensor feedback for closed-loop correction. Its workflow is:
Base motion Control Movement receives a nav_msgs/Path goal, applies a proportional controller to drive the base toward the first waypoint, and reports success or failure via ActionLib.
Arm positioning Control Arm listens for ArmControlAction goals, runs a 10 Hz proportional joint‐space controller until the target angle is reached (or times out/preempts), and publishes zero velocity on completion.
Gripper actuation Control Gripper exposes a binary open/close ActionLib server that publishes a std_msgs/Bool command and waits a fixed delay for mechanical settling.
Feedback streams Encoder & Force nodes continuously publish wheel ticks, joint angles and end-effector force so that controllers and higher layers can run in simulation or CI without real hardware.

Design Patterns
Command
Each controller—Wheel, Arm and Gripper—exposes an ActionLib server where goals are commands (MovementControlGoal, ArmControlGoal, GripperControlGoal). This allows the Brain to queue, pre-empt or retry actions uniformly, without needing to know the details of the underlying motion or actuator interface.
Observer
All controllers and the Force sensor subscribe to encoder and force topics; as soon as new sensor data arrives, control loops use that feedback immediately for error computation or state reporting. This push-based design avoids polling and ensures tight closed-loop latency.
Template Method
All ActionLib servers share a common execution flow—initialize, loop until goal reached/pre-empted/timeout, publish feedback, set result—while each controller overrides just the core compute_command() or handle_completion() hooks. This enforces a consistent server structure and simplifies adding new controllers.
Singleton
Each controller node uses a single ROS node handle and shared publisher/subscriber objects; by treating the ROS handle as a singleton, we can avoid accidental re-initialization and ensure consistent QoS and parameters across callbacks.
Component roles
control_wheel.py - Proportional base controller (MovementControlAction) that steers toward the first waypoint, publishes feedback and sets result on completion.
control_arm.py - ActionLib server (ArmControlAction) implementing a 10 Hz proportional joint controller with configurable tolerance and timeout. Publishes geometry_msgs/Twist on /cmd_vel/arm.
control_gripper.py - Binary actuator server (GripperControlAction) that sends a std_msgs/Bool grip/release command and confirms completion after a delay.
encoder_wheel.py, encoder_arm.py, encoder_gripper.py - Synthetic encoders publishing std_msgs/Int32 at 10 Hz for base, arm and gripper joints.
force.py - Fake force sensor publishing std_msgs/Float32 at 10 Hz for end-effector contact force.
ROS interfaces & KPIs
Topic / Action / Service |
Type |
KPI / Note |
---|---|---|
|
|
10 Hz, max |v| 0.7 m/s, latency < 50 ms |
|
|
|ω| < 0.4 rad/s, settles within ± 5° |
|
|
Open/close < 2 s, confirmed feedback |
|
|
10 Hz, lost < 0.1 % |
|
|
10 Hz, jitter < ±10 ms |
|
|
10 Hz, range 0–100 mm |
|
|
0–50 N, noise < 0.5 N RMS |
|
|
Goal latency < 100 ms, success ≥ 99 % |
|
|
Goal latency < 100 ms, success ≥ 99 % |
|
|
Path repro < 5 cm RMSE |
Implementation modules
Click a component for its full API documentation.
Control Components