Architecture Overview¶
The stack is built around a single sim-to-real switch (use_sim). The same
application nodes and topic names run in both modes; the hardware plugin,
optional controllers, and tension data source change.
This page is the navigation hub. For exhaustive detail, follow the links below.
Start here¶
I want to… |
Go to |
|---|---|
Understand each Python package in depth |
|
See all ROS 2 nodes & topics (sim vs HW) |
|
Download diagrams for my report |
|
Look up launch args / YAML params |
|
Read Python class/function docs |
|
Build and run the stack |
System context¶
flowchart LR
classDef cmake fill:#fff8e1,stroke:#f57f17,stroke-width:1.5px
classDef python fill:#e3f2fd,stroke:#1565c0,stroke-width:1.5px
classDef external fill:#eceff1,stroke:#607d8b,stroke-width:1.5px
DESC["description<br/>URDF · MJCF"]:::cmake
BR["bringup<br/>robot.launch.py"]:::cmake
IFACE["interfaces<br/>FishingTension"]:::cmake
CTRL["control"]:::python
SENS["sensors"]:::python
PLAN["planning"]:::python
DIAG["diagnostics"]:::python
CM["ros2_control host"]:::external
RSP["robot_state_publisher"]:::external
DESC --> BR
BR --> CTRL & SENS & PLAN & DIAG
BR --> CM & RSP
CTRL & SENS & DIAG --> IFACE
SENS -->|tension| CTRL
PLAN -->|fish effort| CM
CTRL -->|trajectory| CM
The sim-to-real switch¶
The use_sim launch argument is resolved at xacro preprocess time, which
swaps the <hardware> plugin in the URDF before the controller manager loads
it:
Concern |
|
|
|---|---|---|
Hardware plugin |
|
|
Controller host |
MuJoCo’s bundled |
Standalone |
Extra ros2_control |
|
(none beyond arm controllers) |
Tension source |
MuJoCo line stretch model (+ FTS fallback) |
HX711 load cell |
Disturbance |
|
Real fish / manual load |
Sim-only URDF |
|
Omitted from HW URDF |
Full branching logic: bringup — Launch Orchestration.
Closed-loop control¶
Both modes implement the same ROS-level tension regulation loop:
flowchart LR
classDef sense fill:#e3f2fd,stroke:#1565c0,stroke-width:1.5px
classDef decide fill:#e8f5e9,stroke:#2e7d32,stroke-width:1.5px
classDef act fill:#fce4ec,stroke:#c62828,stroke-width:1.5px
DIST["disturbance"]:::act
ARM["2-DOF arm"]:::act
LC["load_cell_node"]:::sense
CTRL["tension ctrl<br/>MONITOR→HOOK→REG"]:::decide
PTC["pos_traj_controller"]:::act
DIST --> ARM
ARM --> LC
LC -->|/fishing_arm/tension| CTRL
CTRL -->|/joint_trajectory| PTC --> ARM
ARM -.->|/joint_states| CTRL
Controller internals (state machine, admittance vs force-feedback): control — Tension Controllers.
ROS 2 graphs at a glance¶
Simulation¶
flowchart TB
classDef node fill:#e8f4fc,stroke:#0b6e99,stroke-width:1.5px
classDef sim fill:#fff3e0,stroke:#e65100,stroke-width:1.5px
classDef ctrl fill:#e8f5e9,stroke:#2e7d32,stroke-width:1.5px
classDef infra fill:#f3e5f5,stroke:#6a1b9a,stroke-width:1.5px
classDef topic fill:#fafafa,stroke:#757575,stroke-width:1px,font-size:11px
subgraph lane1["Lane 1 · Disturbance (sim only)"]
direction LR
FISH["fish_agent<br/><i>planning</i>"]:::sim
T_FISH["/fish_effort_controller/commands"]:::topic
FEC["fish_effort_controller"]:::sim
MJ1["mujoco_ros2_control"]:::sim
FISH --> T_FISH --> FEC --> MJ1
end
subgraph lane2["Lane 2 · Arm control loop"]
direction LR
CTRL["admittance / force_feedback<br/><i>control</i>"]:::ctrl
T_TRAJ["/position_trajectory_controller/joint_trajectory"]:::topic
PTC["position_trajectory_controller"]:::ctrl
MJ2["mujoco_ros2_control"]:::sim
JSB["joint_state_broadcaster"]:::infra
T_JS["/joint_states"]:::topic
CTRL --> T_TRAJ --> PTC --> MJ2 --> JSB --> T_JS --> CTRL
end
subgraph lane3["Lane 3 · Tension sensing"]
direction LR
MJ3["mujoco_ros2_control"]:::sim
TSB["tension_sensor_broadcaster"]:::sim
T_WRENCH["/tension_sensor_broadcaster/wrench"]:::topic
LC["load_cell_node<br/><i>sim_fts</i>"]:::node
T_TEN["/fishing_arm/tension"]:::topic
MJ3 --> TSB --> T_WRENCH --> LC --> T_TEN --> CTRL
end
subgraph lane4["Lane 4 · TF & logging (optional)"]
direction LR
RSP["robot_state_publisher"]:::infra
T_TF["/tf · /tf_static"]:::topic
REC["recorder<br/><i>record:=true</i>"]:::node
RSP --> T_TF -.-> LC
T_JS -.-> REC
T_TEN -.-> REC
end
MJ1 ~~~ MJ2
MJ2 ~~~ MJ3
Detailed node/topic tables: Simulation ROS 2 Graph.
Hardware¶
flowchart TB
classDef node fill:#e8f4fc,stroke:#0b6e99,stroke-width:1.5px
classDef hw fill:#fce4ec,stroke:#c62828,stroke-width:1.5px
classDef ctrl fill:#e8f5e9,stroke:#2e7d32,stroke-width:1.5px
classDef infra fill:#f3e5f5,stroke:#6a1b9a,stroke-width:1.5px
classDef topic fill:#fafafa,stroke:#757575,stroke-width:1px,font-size:11px
classDef absent fill:#f5f5f5,stroke:#bdbdbd,stroke-width:1px,stroke-dasharray:4 4
subgraph lane1["Lane 1 · Arm control loop"]
direction LR
CTRL["admittance / force_feedback<br/><i>control</i>"]:::ctrl
T_TRAJ["/position_trajectory_controller/joint_trajectory"]:::topic
PTC["position_trajectory_controller"]:::ctrl
CM["controller_manager<br/><i>dynamixel_hardware</i>"]:::hw
DX["Dynamixel XL430<br/>Joint_1 · Joint_2"]:::hw
JSB["joint_state_broadcaster"]:::infra
T_JS["/joint_states"]:::topic
CTRL --> T_TRAJ --> PTC --> CM <-->|pos / fbk| DX
CM --> JSB --> T_JS --> CTRL
end
subgraph lane2["Lane 2 · Tension sensing"]
direction LR
HX["HX711 load cell"]:::hw
LC["load_cell_node<br/><i>hardware</i>"]:::node
T_TEN["/fishing_arm/tension"]:::topic
HX -->|"ADC"| LC --> T_TEN --> CTRL
end
subgraph lane3["Lane 3 · TF & bring-up test"]
direction LR
RSP["robot_state_publisher"]:::infra
T_TF["/tf · /tf_static"]:::topic
HWC["hardware_check<br/><i>optional</i>"]:::node
RSP --> T_TF
HWC -.-> T_TRAJ
T_JS -.-> HWC
T_TEN -.-> HWC
end
subgraph lane4["Sim-only (absent on hardware)"]
direction LR
X1["fish_agent"]:::absent
X2["fish_effort_controller"]:::absent
X3["tension_sensor_broadcaster"]:::absent
X4["MuJoCo / recorder"]:::absent
end
Detailed node/topic tables: Hardware ROS 2 Graph.
Packages at a glance¶
Package |
Build type |
Role |
|---|---|---|
ament_cmake |
Top-level launch orchestration, controller config. |
|
ament_python |
Admittance & force-feedback tension controllers. |
|
ament_python |
|
|
ament_python |
Virtual fish disturbance (sim only). |
|
ament_python |
Run recorder + hardware bring-up self-test. |
|
ament_cmake |
URDF/xacro, MuJoCo MJCF, STL meshes. |
|
ament_cmake |
|
Layered architecture¶
flowchart TB
subgraph L0["Layer 0 — Physical"]
SIM["MuJoCo physics + tendon"]
HW["Dynamixel + HX711"]
end
subgraph L1["Layer 1 — ros2_control"]
CM["controller_manager / mujoco_ros2_control"]
CTRL["joint_state_broadcaster · position_trajectory_controller"]
SIMCTRL["fish_effort · tension_sensor (sim)"]
end
subgraph L2["Layer 2 — Application (Python)"]
APP["control · sensors · planning · diagnostics"]
end
subgraph L3["Layer 3 — Orchestration"]
BR["bringup/robot.launch.py"]
end
L0 --> L1
L1 --> L2
L3 --> L1
L3 --> L2
Data-flow summary¶
Signal |
Sim origin |
HW origin |
Consumer(s) |
|---|---|---|---|
Joint positions |
MuJoCo → |
Dynamixel encoders |
|
Line tension |
Stretch model / FTS → |
HX711 → |
|
Joint commands |
|
same |
MuJoCo / Dynamixel |
Fish force |
|
N/A |
MuJoCo only |
Auto-generated topic index: ROS 2 Topic & Node Reference.