This document explains how the simulation and real robot workflows are separated in the GEN72 system.
The system has two completely independent workflows that share common planning logic but use different robot control implementations:
- Simulation Workflow - Uses MuJoCo physics simulator
- Real Robot Workflow - Uses Realman SDK to control physical GEN72 robot
./run_mujoco.bat- Launches:
config/dataflow_gen72_mujoco.yml - Robot control:
dora-mujoco(MuJoCo simulator) - No physical robot required
- Safe for testing and development
./run_real_robot.bat- Launches:
config/dataflow_gen72_real.yml - Robot control:
robot_control/gen72_robot_node.py(Realman SDK) - Requires physical robot at 192.168.1.18
- Safety warnings displayed before execution
These files are only used when running run_mujoco.bat:
dora-mujoco/
├── dora_mujoco/
│ ├── __init__.py
│ ├── __main__.py
│ └── main.py # MuJoCo simulator node
utils/
├── visualize_scene.py # MuJoCo visualization tool
└── create_scene_with_obstacles.py # URDF to MuJoCo converter
Dependencies:
mujocoPython packagemujoco.viewerfor visualization- MuJoCo model file:
config/GEN72_base.xml
These files are only used when running run_real_robot.bat:
robot_control/
├── __init__.py
├── gen72_robot_node.py # Real robot control node
├── rm_robot_interface.py # Realman SDK Python interface
├── rm_ctypes_wrap.py # Realman SDK C wrapper
└── api_c.dll # Realman SDK library (Windows)
Dependencies:
- Realman SDK (api_c.dll)
- Physical GEN72 robot connected to network
- Robot IP: 192.168.1.18:8080
These files are used by both workflows:
workflow/
├── multi_view_capture_node.py # Main workflow controller
└── motion_commander.py # Motion command interface
ik_solver/
├── ik_op.py # TracIK inverse kinematics
└── advanced_ik_solver.py # Advanced IK implementations
motion_planner/
├── planner_ompl_with_collision_op.py # RRT-Connect planner
└── planning_scene_op.py # Scene management
trajectory_execution/
└── trajectory_executor.py # Trajectory interpolation
collision_detection/
├── collision_lib.py # Core collision checking
├── collision_check_op.py # Collision check operator
└── pointcloud_collision.py # Point cloud integration
config/
├── robot_config.py # GEN72 parameters
└── GEN72_base.xml # Robot model (MuJoCo format)
Key Point: These shared files are robot-agnostic. They work with joint positions and commands regardless of whether the robot is simulated or real.
nodes:
- id: mujoco_sim
path: dora-mujoco # MuJoCo simulator
inputs:
tick: dora/timer/millis/10 # 100 Hz simulation
control_input: trajectory_executor/joint_commands
outputs:
- joint_positions
- joint_velocities
env:
MODEL_NAME: "F:/2-DORA/.../GEN72_base.xml"
- id: planning_scene
inputs:
robot_state: mujoco_sim/joint_positions # From simulator
- id: trajectory_executor
inputs:
joint_positions: mujoco_sim/joint_positions # From simulator
tick: dora/timer/millis/50 # 20 Hz executionnodes:
- id: gen72_robot
path: ../robot_control/gen72_robot_node.py # Real robot control
inputs:
tick: dora/timer/millis/200 # 5 Hz update
control_input: trajectory_executor/joint_commands
outputs:
- joint_positions
- joint_velocities
- id: planning_scene
inputs:
robot_state: gen72_robot/joint_positions # From real robot
- id: trajectory_executor
inputs:
joint_positions: gen72_robot/joint_positions # From real robot
tick: dora/timer/millis/200 # 5 Hz executionKey Differences:
- Robot control node:
mujoco_simvsgen72_robot - Update frequency: 100 Hz (simulation) vs 5 Hz (real robot)
- Data source: All other nodes receive
joint_positionsfrom different sources but process them identically
- Each workflow uses a different YAML configuration file
- The YAML files specify which robot control node to use
- All other nodes are identical in both configurations
- No
if simulation:checks in code - No environment variables to switch modes
- Mode is determined purely by which dataflow YAML is loaded
- Simulation workflow never imports
rm_robot_interface - Real robot workflow never imports
mujoco - Shared nodes import neither - they only work with numpy arrays
Both robot control nodes provide the same interface:
Inputs:
tick: Timer signal for updatescontrol_input: Joint commands from trajectory executor
Outputs:
joint_positions: Current joint angles (7D array)joint_velocities: Current joint velocities (7D array)
This interface compatibility allows all downstream nodes to work identically with both modes.
# This should work even if:
# - Robot is not connected
# - Realman SDK is not installed
# - api_c.dll is missing
./run_mujoco.bat# This should work even if:
# - MuJoCo is not installed
# - GEN72_base.xml is missing
# - dora-mujoco package is not installed
./run_real_robot.bat- Modify
dora-mujoco/dora_mujoco/main.py - Update
config/dataflow_gen72_mujoco.ymlif needed - No changes to shared files
- Modify
robot_control/gen72_robot_node.py - Update
config/dataflow_gen72_real.ymlif needed - No changes to shared files
- Modify shared files (workflow, IK, planning, etc.)
- Ensure changes work with generic joint position arrays
- Test with both
run_mujoco.batandrun_real_robot.bat
The collision detection system (collision_detection/collision_check_op.py) has a flag:
USE_REALMAN_API = False # Set to True to use Realman official collision detectionCurrent behavior:
False(default): Uses built-in geometric collision checker (works for both modes)True: Uses Realman SDK collision API (only works in real robot mode)
Recommendation: Keep as False to maintain independence. The built-in checker works well for both workflows.
✅ Simulation and real robot workflows are fully separated
- Different entry points:
run_mujoco.batvsrun_real_robot.bat - Different dataflow configs:
dataflow_gen72_mujoco.ymlvsdataflow_gen72_real.yml - Different robot control nodes:
dora-mujocovsgen72_robot_node.py - No shared dependencies between simulation-only and real-robot-only code
- Shared planning/IK/trajectory code is robot-agnostic
✅ No modifications needed to existing code
- Separation already exists through dataflow architecture
- No runtime conditionals or mode switches required
- Both workflows tested and working independently