This package is for operating the SOBITS custom mobile manipulator, which combines a four-wheel independent steering drive mechanism, a lift mechanism, dual arms, and a pan-tilt mechanism.
Caution
If you have no previous experience controlling this robot, please have a senior colleague accompany you while you want to use this robot.
This section describes how to set up this repository.
First, please set up the following environment before proceeding to the next installation stage.
| System | Version |
|---|---|
| Ubuntu | 24.04 (Noble Numbat) |
| ROS | Jazzy Jalisco |
| Python | 3.12 |
| Docker | latest |
Note
If you need to install Ubuntu or ROS, please check our SOBITS Manual.
-
Go to the
srcfolder of ROS.$ cd ~/colcon_ws/src/
-
Clone this repository.
$ git clone https://github.com/TeamSOBITS/sobit_home
-
Navigate into the repository.
$ cd sobit_home/ -
Install the dependent packages.
$ bash install.sh
-
Setup Rust for
rm_motors_rosbefore compiliing.source $HOME/.bashrc cd ~/colcon_ws/src/rm_motors_ros/rm_motors_hw/rm_motors_can cargo install cargo-expand cargo build --release
-
Compile the package.
$ cd ~/colcon_ws/ $ colcon build --symlink-install $ source ~/colcon_ws/install/setup.sh
-
Select features with launch arguments and execute real_minimal.launch.py in your development environment.
$ ros2 launch sobit_home_bringup real_minimal.launch.py
-
You can enable/disable modules directly from CLI (recommended).
$ ros2 launch sobit_home_bringup real_minimal.launch.py \ enable_mobile_base:=true \ enable_body:=true \ enable_arm_left:=true \ enable_arm_right:=false \ enable_head:=true \ enable_lidar:=true \ use_rviz:=true
-
For real hardware mode, load
.bashrcand set SOBIT HOME domain before launch.$ source ~/.bashrc $ sobit_home_mode
If you did not succeed in connecting to the real robot, check the following points:
- Ensure the emergency stop button is not pressed.
- Verify the battery is sufficiently charged.
- Confirm the USB hub is connected to the computer.
- Verify that required environment variables are set in your shell (
DXL_X_LOWER_PORT,DXL_X_UPPER_PORT,DXL_P_UPPER_PORT,UM_PORT,HOME_CAM_LEFT_PORT,HOME_CAM_RIGHT_PORT). - Verify CAN is available (
can0) whenenable_mobile_base:=true.
move_wheel_linear drives the robot straight by a target distance (metres). move_wheel_rotate turns in place by a target angle (radians). Both actions use closed-loop PID feedback from odometry and clamp velocity near the goal for smooth stopping. Gains can be tuned at runtime via ROS parameters — no recompile needed.
The four-wheel independent steering controller computes per-wheel steer angle and drive velocity from any combination of cmd_vel components (x, y, θ). It automatically picks the shortest steering path for each wheel, reversing the drive direction when that is faster than a full rotation.
plan_to_pose plans a trajectory for the given planning group (arm_left, arm_right, arm_left_body, arm_right_body) and caches it. execute_plan replays the cached trajectory. For whole-body groups (arm_left_body, arm_right_body), the base is moved in parallel with the arm via the MoveItWholeBodyBridge, which tracks the planned base waypoints using odometry feedback.
All MoveIt interfaces work correctly in both real-hardware and Gazebo simulation modes, including when the simulator is paused.
As a preliminary step to running the actual machine, SOBIT HOME can be visualized on Rviz to display the robot's configuration.
$ ros2 launch sobit_home_description display.launch.pySOBIT HOME has a simulation environment with Gazebo Harmonic, allowing you to verify operations even without the actual machine.
$ ros2 launch sobit_home_bringup gz_minimal.launch.pyAt present, the following virtual environments are available.
| World Name | Description |
|---|---|
empty |
Spawns an environment without furniture or obstacles. |
wrs |
Spawns the Tidy Up environment used in WRS2020. |
small_house |
Spawns a small house layout developed by AWS. |
rcjo2025_arena |
Spawns the RCJ Open 2025 arena world. |
rcjo2026_arena |
Spawns the RCJ Open 2026 arena world (default). |
To change the environment, modify the world_model parameter in gz_minimal.launch.py.
$ ros2 launch sobit_home_bringup gz_minimal.launch.py world_model:=emptyTip
Since it is equipped with sensors similar to the actual machine, the processing may become heavy depending on the computer. Please select only the necessary sensors in gz_minimal.launch.py.
'enable_head_cam_color' : 'true',
'enable_head_cam_depth' : 'true',
'enable_hand_left_cam_color' : 'true',
'enable_hand_right_cam_color' : 'true',
'enable_lidar' : 'true',Additionally, multiple SOBIT HOMEs can be spawned in the same simulation environment by launching additional instances with different robot_id and spawn coordinates.
# Robot 1
$ ros2 launch sobit_home_bringup gz_minimal.launch.py \
robot_name:=sobit_home robot_id:=1 robot_coords_x:=0.0 robot_coords_y:=0.0 robot_coords_Y:=0.0
# Robot 2
$ ros2 launch sobit_home_bringup gz_minimal.launch.py \
robot_name:=sobit_home robot_id:=2 robot_coords_x:=0.0 robot_coords_y:=2.0 robot_coords_Y:=0.0| Package | Role | Main Entry Points |
|---|---|---|
sobit_home_bringup |
Integrated startup for real robot and Gazebo | launch/real_minimal.launch.py, launch/gz_minimal.launch.py, launch/robot.launch.py |
sobit_home_control |
Swerve base control and MoveIt whole-body bridge | swerve_controller_node, moveit_whole_body_bridge_node |
sobit_home_library |
High-level action/service servers (joint, wheel, MoveIt) | launch/action_server.launch.py, joint_action_server, wheel_action_server, moveit_action_server |
sobit_home_description |
URDF/Xacro model, RViz config, and base world file | launch/display.launch.py, robots/sobit_home_robot.urdf.xacro |
sobit_home_moveit_config |
MoveIt planning configuration and launch | launch/move_group.launch.py |
sobit_home_kinematics_plugin |
MoveIt kinematics plugin for SOBIT HOME | sobit_home_kinematics_plugin_description.xml |
Summary of information on SOBIT HOME and related software
This is a summary of information for moving the joints (pan-tilt mechanism, linear mechanism and manipulator) of SOBIT HOME.
Implemented interfaces in sobit_home_library:
-
Actions
move_jointmove_to_posemove_right_hand_to_posemove_left_hand_to_pose
-
Services
get_hand_to_coord/left— Analytical IK for the left arm. Accepts a target pose in any TF frame and returns joint angles, a success flag, and reachability hints.get_hand_to_coord/right— Analytical IK for the right arm. Same interface as left.get_hand_to_tf/leftget_hand_to_tf/rightget_head_to_coordget_head_to_tfget_finger_angle
Reachability hints (
move_pose): When the target is outside the arm workspace, the service returnssuccess=falsebut still populatesmove_posewith the minimum robot adjustments needed to bring the target into reach:Field Meaning position.xBase forward/backward shift (m); positive = drive forward position.yReserved for future lateral base movement (always 0.0) position.zBody lift delta (m); positive = lift up, negative = lift down orientationYaw to face the target -
MoveIt interfaces (launched from
action_server.launch.py)- Service:
plan_to_pose - Action:
execute_plan
- Service:
The joint names of SOBIT HOME and their constants are listed below.
| Joint Number | Joint Name | Joint Constant Name |
|---|---|---|
| 0 | head_pan_joint | - |
| 1 | head_tilt_joint | - |
| 2 | arm_left_shoulder_tilt_joint | - |
| 3 | arm_left_upper_roll_joint | - |
| 4 | arm_left_upper_flex_joint | - |
| 5 | arm_left_elbow_joint | - |
| 6 | arm_left_lower_flex_joint | - |
| 7 | arm_left_wrist_tilt_joint | - |
| 8 | arm_left_wrist_roll_joint | - |
| 9 | arm_right_shoulder_tilt_joint | - |
| 10 | arm_right_upper_roll_joint | - |
| 11 | arm_right_upper_flex_joint | - |
| 12 | arm_right_elbow_joint | - |
| 13 | arm_right_lower_flex_joint | - |
| 14 | arm_right_wrist_tilt_joint | - |
| 15 | arm_right_wrist_roll_joint | - |
| 16 | hand_left_finger_l_mcp_joint | - |
| 17 | hand_left_finger_l_pip_joint | - |
| 18 | hand_left_finger_l_dip_joint | - |
| 19 | hand_left_finger_c_mcp_joint | - |
| 20 | hand_left_finger_c_ip_joint | - |
| 21 | hand_left_finger_r_pip_joint | - |
| 22 | hand_left_finger_r_dip_joint | - |
| 23 | hand_right_finger_l_mcp_joint | - |
| 24 | hand_right_finger_l_pip_joint | - |
| 25 | hand_right_finger_l_dip_joint | - |
| 26 | hand_right_finger_c_mcp_joint | - |
| 27 | hand_right_finger_c_ip_joint | - |
| 28 | hand_right_finger_r_pip_joint | - |
| 29 | hand_right_finger_r_dip_joint | - |
| 30 | body_lift_joint | - |
| 31 | wheel_steer_f_l_joint | - |
| 32 | wheel_steer_f_r_joint | - |
| 33 | wheel_steer_b_l_joint | - |
| 34 | wheel_steer_b_r_joint | - |
| 35 | wheel_drive_f_l_joint | - |
| 36 | wheel_drive_f_r_joint | - |
| 37 | wheel_drive_b_l_joint | - |
| 38 | wheel_drive_b_r_joint | - |
Poses can be added and edited in the file pose_list.yaml. The format is as follows:
/**:
ros__parameters:
poses:
- initial_pose
- detecting_pose
initial_pose:
body_lift : 0.5
head_pan : 0.0
head_tilt : 0.0
arm_left_shoulder_tilt : 0.0
arm_left_upper_roll : 0.0
arm_left_upper_flex : 0.0
arm_left_elbow : 0.0
arm_left_lower_flex : 0.0
arm_left_wrist_tilt : 0.0
arm_left_wrist_roll : 0.0
arm_right_shoulder_tilt : 0.0
arm_right_upper_roll : 0.0
arm_right_upper_flex : 0.0
arm_right_elbow : 0.0
arm_right_lower_flex : 0.0
arm_right_wrist_tilt : 0.0
arm_right_wrist_roll : 0.0
...Add the desired pose name to poses, and then set the angles for each joint under the pose name.
[!NOTE] A named-pose move (
move_to_pose) always commands all arm, body, and head joints — not only the ones you changed. Any joint you omit from a pose block defaults to0.0and is actively driven there, so always specify the full joint set for each pose. (Use themove_jointaction if you want to command a single joint and leave the rest holding position.)
action_server.launch.py exposes the pose YAML paths as launch arguments, so another package or machine can supply its own poses without editing sobit_home_library. The defaults point at the library's own config/.
| Launch argument | Default |
|---|---|
pose_config |
sobit_home_library/config/pose_list.yaml |
right_hand_pose_config |
sobit_home_library/config/right_hand_pose_list.yaml |
left_hand_pose_config |
sobit_home_library/config/left_hand_pose_list.yaml |
$ ros2 launch sobit_home_library action_server.launch.py \
pose_config:=/path/to/my_pose_list.yamlrobot.launch.py forwards the same arguments, so the override can also be applied from the full bringup. The robot bringup can additionally skip starting the action server entirely (so it can be run on another machine) via enable_action_server:=false.
Poses are held as ROS parameters, so they can be set live and reloaded without restarting the node. After changing parameters, call the reload_poses service to rebuild the in-memory pose set.
# Set a single value, or load a whole YAML at once
$ ros2 param set /sobit_home/joint_action_server initial_pose.body_lift 0.42
$ ros2 param load /sobit_home/joint_action_server /path/to/new_pose_list.yaml
# Apply the changes
$ ros2 service call /sobit_home/reload_poses std_srvs/srv/Trigger {}The service reply lists the names of all whole-body poses now loaded — use it to confirm your edit registered.
[!IMPORTANT]
reload_posesrebuilds the active pose set entirely from theposesarray. Updating an existing pose's values takes effect immediately, but to add a new pose you must add its name to theposesarray as well (e.g.ros2 param set /sobit_home/joint_action_server poses "[initial_pose, ..., my_new_pose]") — otherwise its values are ignored andmove_to_posewill abort with "pose not found". A pose name dropped from the array is removed from the active set on the next reload.Runtime changes are not written back to the YAML file. Once a value is tuned, copy it into
pose_list.yamlso it persists across restarts.
This is a summary of information for moving the SOBIT HOME moving mechanism.
Implemented action interfaces in sobit_home_library:
move_wheel_linearmove_wheel_rotate
The wheel action server publishes velocity commands to cmd_vel and uses odom for feedback.
SOBIT HOME is available as open hardware at OnShape.
For more information on hardware, please click here.
- Access Onshape.
[!NOTE] You do not need to create an
OnShapeaccount to download files. However, if you wish to copy the entire document, we recommend that you create an account.
- Select the part in
Instancesby right-clicking on it. - A list will be displayed, press the
Exportbutton. - In the window that appears, there is a
Formatitem. SelectSTEP. - Finally, press the blue
Exportbutton to start the download.
TBD
TBD


