Skip to report
Technical Project Archive
Robotic manipulation · Project reports

Home Robotics

Dual Franka Manipulation on a Shared Rail

ROS 2 · MuJoCo · MoveIt 2 · ros2_control

Project links: Repository | Validation | README | Demo


Abstract

Home Robotics is a simulation platform for manipulation with two Franka Panda robots on independent carriers of a shared linear rail. MuJoCo supplies physics and authoritative object state; ROS 2 Jazzy and ros2_control integrate the runtime and controllers; MoveIt 2 provides motion planning and collision checking. The current validated baseline is Panda1 grasping, lifting, transporting, placing, and releasing a cube with grasp and placement verification. Phase 5 exposes this sequence through a single-task PickAndPlace ROS Action. All reported manipulation results are from simulation.


1. Project Scope

The platform establishes a reproducible path from simulated physics to controller execution, collision-aware planning, and a task interface. A shared rail gives two manipulators access to an extended workspace while introducing explicit carriage-separation constraints.

Current implementation: Phases 0–5 are complete within the documented scope. Panda1 is the primary manipulation baseline; cube placement at surface_left_2 is an example validated task. Panda2 has its own control and planning chain, but coordinated manipulation is not implemented.

Future direction: demonstration-based task reproduction and broader sensing and coordination remain future work. Phase 6 and later are on hold.

2. System Architecture

ROS 2 Runtime Graph

Task and execution path

  1. Task ClientPickAndPlace Action goal
  2. task_executorROS node → Phase 4 launch subprocess
  3. cube_pick_place_demoManipulation executable; node name below
  4. move_groupMoveIt node / trajectory execution
  5. controller_managerros2_control node hosting controllers
  6. MujocoTopicSystemHardware plugin → /mujoco/command
  7. mujoco_runtimeROS node → MuJoCo simulator and joint actuators

State feedback path

  1. MuJoCo / mujoco_runtimeAuthoritative state / ROS publisher
  2. /mujoco/objects/cube/posePoseStamped topic; example object
  3. dynamic_object_scene_syncROS node using ObjectRegistry metadata
  4. /apply_planning_sceneService → MoveIt PlanningScene

Joint feedback: /mujoco/joint_states → hardware plugin → ros2_control state interfaces → joint_state_broadcaster → /joint_states → MoveIt / monitoring.

Contact feedback: /mujoco/objects/cube/contact → manipulation verification. The manipulation process sends gripper goals directly to the gripper controller, outside the MoveIt arm-trajectory path.

Figure 1. Main ROS 2 execution and feedback paths. Controllers and the hardware plugin run within the ros2_control stack; MuJoCo is owned by the runtime node. Boxes are labeled by role and do not each represent a separate ROS node.

MuJoCo owns physics, contact, and authoritative object state. MoveIt owns planning and collision reasoning. ros2_control is the execution boundary. The Task Executor provides the high-level ROS Action interface without owning MuJoCo or MoveIt internals. Static environment geometry and synchronized object poses supply the planning scene.

Architecture notes describe these boundaries in more detail.

Main ROS 2 Nodes and Runtime Components

Table 1. Main components in the documented launch path.
NameTypeResponsibility
task_executorROS NodeAction server, request validation and single-task ownership; package home_robotics_task_executor.
cube_pick_lift_return_demoROS NodePhase 4 manipulation; launched by executable cube_pick_place_demo in home_robotics_manipulation.
move_groupMoveIt NodePlanning, collision reasoning and trajectory execution; package moveit_ros_move_group.
planning_scene_environmentROS NodeLoads fixed scene geometry; package home_robotics_moveit_config.
dynamic_object_scene_syncROS NodeUpdates world objects from poses and registry geometry; package home_robotics_manipulation.
controller_managerROS NodeHosts controllers and hardware read/update/write cycle; executable ros2_control_node in package controller_manager.
home_robotics_mujoco_hardware/MujocoTopicSystemHardware InterfaceExchanges joint commands and state with the runtime; enforces rail separation at the hardware boundary.
mujoco_runtimeROS Node / Simulation ComponentOwns MuJoCo model/data, advances physics, publishes state and clock; package home_robotics_bringup.

Names describe the normal launch configuration. The runtime reuses the bridge implementation from home_robotics_control; this does not require a second simulator or a separate legacy bridge node. Controllers are listed in Section 5.

3. Simulation Environment

The MuJoCo environment contains the shared rail, two robot carriers, six work surfaces, a floor and arena boundary, and configured objects. Scene geometry, robot setup, and physics parameters are maintained centrally in config/.

Table 2. Selected environment properties from repository configuration.
PropertyConfiguration
Reference frame / unitsworld / SI
Rail and carriersOne 3.4 m rail; two independently controlled carriers
Work surfacesSix tables, three on each side; top height 0.68 m
Dynamic objectscube, apple, purple_ball
Static scene objectsbowl, pan
Physics step / gravity0.002 s / −9.81 m/s² along Z
Central filesscene.yaml, robots.yaml, objects.yaml, physics.yaml; location and grasp-profile metadata in locations.yaml and grasp_profiles.yaml

An object's presence in the scene or registry does not establish manipulation support. The cube is the validated end-to-end object; apple, bowl, and pan manipulation are not supported.

4. Dual Panda and Shared Rail

Each Franka Panda combines seven arm joints with one independently controlled prismatic rail joint: 8 DOF per manipulator planning group. Each robot has a separate Franka Hand gripper, outside the eight-joint chain. The carriers share a physical rail and must maintain at least 0.70 m separation; crossing is prohibited.

Shared-rail separation safety at the hardware/control boundary and MoveIt geometric collision checking are separate layers. Rail separation alone does not establish collision-free arm motion. Panda2 remains available as a second robot; coordinated dual-arm manipulation has not been validated or implemented.

5. ROS 2 Control Stack

The ROS 2 Jazzy runtime exposes a custom MuJoCo hardware interface, home_robotics_mujoco_hardware/MujocoTopicSystem, to ros2_control. Standard trajectory controllers command each rail-and-arm chain, while separate gripper controllers command the Franka Hands. The joint_state_broadcaster publishes measured joint state.

Controller actions pass through the hardware interface to the authoritative MuJoCo runtime. Simulation time and reset belong to that runtime; MoveIt does not write directly to the physics state. The demo instructions start the Phase 2 stack, MoveIt, static scene loader, and dynamic object synchronizer in separate terminals.

Command and State Flow

Command: MoveIt trajectory → panda1_trajectory_controller → ros2_control position command interfaces → MujocoTopicSystem.write() → /mujoco/command → mujoco_runtime → simulated joint actuators. Panda2 has an equivalent independent controller path.

Feedback: MuJoCo joint state → /mujoco/joint_states → MujocoTopicSystem.read() → ros2_control position/velocity state interfaces → joint_state_broadcaster → /joint_states → MoveIt and monitoring. The private transport uses sensor_msgs/msg/JointState in both directions. Controller manager is configured for 100 Hz; ROS consumers use use_sim_time=true.

Configured Controllers

Table 3. Controllers configured in home_robotics_bringup/config/controllers.yaml.
Controller nameResponsibility
joint_state_broadcasterPublishes measured state on /joint_states.
panda1_trajectory_controllerPanda1 rail + seven arm joints; position commands, position/velocity feedback.
panda2_trajectory_controllerPanda2 rail + seven arm joints; independent trajectory execution.
panda1_gripper_controllerSeparate Franka Hand control via panda1_finger_joint1.
panda2_gripper_controllerSeparate Franka Hand control via panda2_finger_joint1.

Key ROS 2 Interfaces

Table 4. Selected interfaces; arrows identify request or data direction. Action feedback/results return to the client.
InterfaceKindDirection / ProducerConsumerPurpose
/home_robotics/pick_and_placeActionTask client →task_executorCube named-placement goal; structured feedback/result.
/joint_statesTopicjoint_state_broadcaster →MoveIt / manipulation / robot state publishingMeasured robot state.
/clockTopicmujoco_runtime →Nodes using simulation timeTime derived from MuJoCo.
/mujoco/commandTopicMujocoTopicSystem →mujoco_runtimePrivate joint position command transport.
/mujoco/joint_statesTopicmujoco_runtime →MujocoTopicSystemPrivate measured joint-state transport; launch remapping of the bridge publisher.
/mujoco/objects/cube/poseTopicmujoco_runtime →dynamic_object_scene_sync / manipulationTimestamped ground-truth cube pose.
/mujoco/objects/cube/contactTopicmujoco_runtime →Manipulation verificationContact / grasp state encoded as JSON in std_msgs/msg/String.
/panda1_trajectory_controller/follow_joint_trajectory
/panda2_trajectory_controller/follow_joint_trajectory
ActionMoveIt execution →Corresponding trajectory controllerFollowJointTrajectory for each rail-and-arm chain.
/panda1_gripper_controller/gripper_cmd
/panda2_gripper_controller/gripper_cmd
ActionGripper client →Corresponding gripper controllerGripperCommand; Phase 4 directly uses Panda1.
/apply_planning_sceneServiceScene loaders / synchronization / manipulation →MoveItApply static geometry, dynamic objects and attachment diffs.

Controller Action paths combine the configured controller names with action_ns in home_robotics_moveit_config/config/moveit_controllers.yaml. Both robots' endpoints are configured; the validated manipulation task uses Panda1.

6. Motion Planning with MoveIt 2

The two manipulator groups are panda1_manipulator (shared_rail → panda1_tcp) and panda2_manipulator (shared_rail → panda2_tcp). Each uses KDL inverse kinematics and OMPL planning with collision checks against the PlanningScene.

The static PlanningScene represents fixed environment geometry; synchronized CollisionObjects represent configured objects. There is currently no coordinated 16-DOF dual-arm planning group.

7. Dynamic Object Synchronization

mujoco_runtime publishes geometry_msgs/msg/PoseStamped on /mujoco/objects/{object_id}/pose for configured planning-scene objects, including /mujoco/objects/cube/pose. The dynamic_object_scene_sync node combines these poses with ObjectRegistry geometry to construct MoveIt CollisionObjects and apply PlanningScene diffs. Its launch sets sync_rate=20.0; MuJoCo remains the authority and MoveIt receives a planning representation.

The planning-object lifecycle is WORLD → ATTACHED → WORLD. The synchronizer queries /get_planning_scene for attached IDs and excludes them from world updates. Manipulation pauses/drains synchronization around ownership changes: verified grasp and stabilization precede attachment, and supported placement/release restores one WORLD object with no stale attachment. Contact state is consumed separately by manipulation verification.

8. Manipulation Pipeline

  1. Object selection
  2. Pre-grasp
  3. Approach
  4. Gripper close
  5. Contact verification
  6. Stabilization
  7. Lift
  8. Transport
  9. Place
  10. Stabilization release
  11. Gripper open
  12. Placement verification
Figure 2. Panda1 cube manipulation sequence. Contact and gripper closure are verified before temporary stabilization is activated.

The pipeline combines a physical simulated grasp with temporary MuJoCo stabilization during handling. Stabilization is conditional on successful grasp verification. MoveIt attachment separately represents the held object for collision reasoning. After placement support checks, stabilization is removed, the gripper opens, and final pose, support, and scene ownership are verified.

The cube baseline includes transfer from its configured source to a named surface such as surface_left_2. A separate purple_ball trial demonstrated grasp, lift, and return; it does not establish named-target sphere placement or reliability and is outside the Phase 5 Action scope.

9. Task Executor API

Endpoint: /home_robotics/pick_and_place
Interface: home_robotics_interfaces/action/PickAndPlace.action

Table 5. Implemented PickAndPlace Action fields.
PartFields and types
Goalobject_id, target_id — string
Feedbacktask_id, current_state, message — string; progress — float32
Resultsuccess — bool; task_id, final_state, failure_reason, manipulation_failure_reason, message — string; final_object_pose — geometry_msgs/Pose

Only one task can be active; a concurrent goal is rejected. Requests are checked for empty or unknown IDs, supported manipulation scope, and valid named targets. The current Action accepts only cube with Panda1; the target must differ from the source surface. Structured results preserve both task-level and manipulation failure reasons. An unavailable final pose is represented by an all-zero pose, including quaternion W.

execute=false is the default node/launch safety setting, not a Goal field. Planning-only preflight issues no physical motion commands; its success does not mean that a placement occurred. execute=true enables simulated execution.

The executor currently delegates Phase 4 through a ros2 launch subprocess. Planning-only cancellation is supported at safe boundaries; execution-mode cancellation requests are rejected because arbitrary interruption is not supported. A direct reusable manipulation API remains a possible future refactor.

Full implemented API contract.

End-to-End Task Execution

For the validated cube → surface_left_2 task with execute=true:

  1. The client sends a PickAndPlace goal; the executor admits it only if no task is active.
  2. task_executor validates the cube capability and named target against the registry and scene configuration.
  3. The adapter starts cube_pick_place_demo.launch.py as a ros2 launch subprocess, passing the object, target, execution flag and result-file path.
  4. The manipulation process obtains fresh joint/object state and checks controllers, scene synchronization, rail separation and collision preconditions.
  5. MoveIt and the manipulation layer plan/check pre-grasp and Cartesian stages, including hypothetical attached transport. Planning-only mode would finish here without motion.
  6. The gripper opens; pre-grasp is replanned from measured state. Pre-grasp and approach execute through MoveIt, the Panda1 trajectory controller and the hardware bridge while MuJoCo publishes state feedback.
  7. The grasp observer starts, the gripper closes via /panda1_gripper_controller/gripper_cmd, and physical grasp verification must pass.
  8. Temporary MuJoCo stabilization activates; after settling checks, the PlanningScene object changes from WORLD to ATTACHED.
  9. The arm lifts and transports the cube to the target, checking lift and placement support/region conditions.
  10. Stabilization is removed, WORLD ownership is restored, the gripper opens, and the arm retreats.
  11. Final pose, support, open width, ownership and Panda2 drift checks determine the Phase 4 result.
  12. The adapter reads the process report and exit status; the executor returns the Action result, preserving manipulation failure details when present.

10. Validation and Results

These are recorded repository results. The test layers check different properties and should not be combined into a single score.

Table 6. Validation evidence and its scope.
EvidenceRecorded resultScope
Deterministic simulation tests92 passedConfiguration, scene, control, reset, contact, rail constraints, and utilities
ROS package tests56 total; 0 errors; 0 failures; 1 existing skippedPackage contracts and component behavior after workspace build
Phase 5 focused tests10 passedTask Executor contract and fake-adapter Action tests; part of the ROS suite
Phase 4 full-stack cube benchmark9 / 10 successfulIndependent simulated manipulation trials to surface_left_2

Retained failure: benchmark trial 2 failed before motion during planning/retiming. MoveIt TOTG reported negative path velocity on a hypothetical transport trajectory. The failed trial remains in the evidence; it was not replaced by a later successful run. Successful trials recorded final position errors of 1.416–1.923 mm, with a mean of 1.598 mm.

Runtime integration checks compose the control stack, planning, scene synchronization, and manipulation or Action entry point. Manual RViz checks inspect geometry and state visually; they are not automated tests. The focused Action suite uses a fake adapter and does not substitute for a full-stack run.

Validation summary | Benchmark interpretation | Per-trial benchmark data (JSON) | Phase 5 acceptance

11. Development Environment

Primary development used an Apple MacBook with an Apple M4 chip, 16 GB unified memory, and a 512 GB SSD. The robotics runtime was developed primarily in an Ubuntu 24.04 ARM64 virtual machine, using ROS 2 Jazzy, MuJoCo, MoveIt 2, and ros2_control.

This describes development hardware, not a performance benchmark. Local compute and memory constraints have influenced scope; VLA/LLM-heavy work is deferred.

12. Limitations

  • Simulation only; no real-robot deployment or hardware validation.
  • Panda1 is the primary validated manipulation baseline. The cube is the validated named-placement object; other scene objects do not establish generic manipulation.
  • Object poses and contacts come from ground-truth simulation state. No perception pipeline or semantic vision is implemented.
  • No coordinated dual-arm manipulation, generic task scheduler, or autonomous robot allocation.
  • Task Executor execution uses process-level Phase 4 delegation. Execution-mode cancellation is rejected; planning-only cancellation has supported safe boundaries.
  • No VLA/LLM runtime. The retained planning/retiming failure limits any claim of repeatable success.

13. Future Work

Not implemented; Phase 6+ is on hold. Directions include Logitech F710 teleoperation of Panda2, human demonstration recording, semantic/task extraction from demonstrations, and Panda1 autonomous reproduction of demonstrated tasks. Later work may address perception, coordinated dual-arm manipulation, VLA/LLM integration, and sim-to-real transfer.

14. Repository Structure

Home-Robotics/
├── config/
├── simulation/
├── tests/
├── ros2_ws/src/
│   ├── home_robotics_control/
│   ├── home_robotics_description/
│   ├── home_robotics_mujoco_hardware/
│   ├── home_robotics_bringup/
│   ├── home_robotics_moveit_config/
│   ├── home_robotics_manipulation/
│   ├── home_robotics_interfaces/
│   └── home_robotics_task_executor/
└── docs/

Configuration and simulation are separate from the ROS packages. Technical documentation is in docs/; historical phase notes and measured evidence are preserved under docs/archive/.