open-deploy-ws Setup

Detailed setup guide for the public open-deploy-ws workspace.

Repository Overview

URL: https://github.com/fiveages-sim/open-deploy-ws

open-deploy-ws is the public entry point for the FiveAges Sim ecosystem. It provides:

  • Pre-configured submodule structure

  • Public-only visibility by default

  • Lean branches for minimal builds

  • GitHub Release .deb integration for OCS2 (and optionally common / arms)

Finish Install Environment first (ROS apt source → Jazzy + rosdep). Then use ./init_repo.sh. After colcon build, source install/setup.bash in the launch terminal.

Cloning

git clone https://github.com/fiveages-sim/open-deploy-ws.git
cd open-deploy-ws

The top-level clone can use HTTPS. Nested remotes in .gitmodules are still git@github.com:… (same for nested .gitmodules in arms_ros2_control and robot_descriptions).

SSH remotes vs HTTPS / gh

Machines without an ssh binary or GitHub SSH keys fail submodule fetch with error: cannot run ssh: No such file or directory.

git config url.https://github.com/.insteadOf git@github.com: alone is not enough for git submodule update. Nested repos read their own .gitmodules and invoke ssh directly.

On current open-deploy-ws main, ./init_repo.sh rewrites GitHub git@ URLs in .gitmodules to HTTPS, runs submodule sync / update, then restores .gitmodules (so the working tree is not left dirty). That path runs when ssh is missing, when public mode has no usable key, or when you pass --https / OPEN_DEPLOY_GIT_HTTPS=1. Prefer:

./init_repo.sh --public --ocs2=deb --arms=source --common=source
# force HTTPS even if ssh exists:
./init_repo.sh --public --https --ocs2=deb --arms=source --common=source

./init_repo.sh --help lists the rest (see also the open-deploy-ws README). Hosts that already have SSH keys (especially for private nested modules) keep the original SSH URLs unless --https is set.

If your checkout predates these flags (no --https in ./init_repo.sh --help), pull main or clone a fresh open-deploy-ws. For Taku, switch descriptions to feature/agilex after init (see Taku / feature/agilex).

Initialization

./init_repo.sh

With no arguments the menu is interactive (read prompts: public/private, then per-module d/s). What the script does (open-deploy-ws README):

Menu

Role

1) 初始化工作空间(推荐)

Nested visibility (public / private), then per-module d (GitHub Release .deb) or s (source). Then submodule sync, rosdep install on source paths, and install chosen debs.

2) 切换模块安装方式

Switch source ↔ deb for a module (OCS2, arms, common). Cleans conflicting source or uninstalls the matching deb, then re-syncs.

3) 仅安装/更新核心 deb

Skip Git. ./scripts/install_core_debs.sh --only ocs2 (or common, arms, comma-separated).

4) 卸载核心 deb

./scripts/uninstall_core_debs.sh --only ocs2

5) 仅运行 rosdep

rosdep install --from-paths src --ignore-src -r -y — no Git, no debs

You still colcon-build after init. Do not start with git submodule update --init --recursive; the script already initializes the modules you selected.

Core module options (OCS2, arms, common)

When prompted (d=deb, s=source; Enter accepts the default):

Option

Description

When to Use

d

GitHub Release .deb

Quick start; no need to build that module from source

s

Source build

Development, debugging, or contributing

Defaults in open-deploy-ws: OCS2=d, arms=s, common=s. Deb mode does not install from packages.ros.org.

CI / non-interactive init

A container or CI job with no TTY can run:

./init_repo.sh --public --ocs2=deb --arms=source --common=source

Defaults match the interactive menu: public, ocs2=deb, arms=source, common=source. Passing --public, --private, or any module flag skips keyboard prompts. ./init_repo.sh --help lists flow switches (--init, --switch, --deb-only, --rosdep, …).

Flag

Environment variable

Meaning

--public / --private

OPEN_DEPLOY_VISIBILITY

Nested visibility

--ocs2=deb|source

OPEN_DEPLOY_OCS2

ocs2 install mode

--arms=deb|source

OPEN_DEPLOY_ARMS

arms install mode

--common=deb|source

OPEN_DEPLOY_COMMON

common install mode

--https

OPEN_DEPLOY_GIT_HTTPS=1

Force HTTPS for GitHub submodules

-y / --yes

OPEN_DEPLOY_YES=1

Auto-confirm source-tree cleanup

Command-line flags override the matching env vars. If ./init_repo.sh --help does not list --public, pull main.

Lean Branches

For a single product, clone the matching branch (README directory names). Use a lean branch when you only need that robot’s packages (smaller clone). Taku has no lean open-deploy-ws branch — stay on main and switch descriptions to feature/agilex.

# Dobot CR5
git clone -b dobot-cr5 git@github.com:fiveages-sim/open-deploy-ws.git dobot_cr5_ws
# ARX Lift 2S (full-body). Acone (dual-arm) is co-debug in this workspace, not a separate platform.
git clone -b arx-lift2s git@github.com:fiveages-sim/open-deploy-ws.git lift2s-ws
# HighTorque Panthera HT
git clone -b panthera-ht git@github.com:fiveages-sim/open-deploy-ws.git ht-deploy-ws

The open-deploy-ws README also lists arx-acone. Then ./init_repo.sh and ./quick_start.sh as in that branch’s README. See ARX Lift 2S and HighTorque Panthera HT.

Directory Structure

After initialization:

From the open-deploy-ws README (hyphen, not robot_descriptions):

open-deploy-ws/
├── src/
│   ├── arms_ros2_control/     # controllers / commands / hardware interfaces / shared libs
│   ├── robot-descriptions/    # common / manipulator / humanoid
│   └── ocs2_ros2/             # only if that module is installed as source
├── init_repo.sh
├── submodules_visibility.conf
├── deb_versions.conf
└── scripts/

Taku / feature/agilex

open-deploy-ws .gitmodules pins src/robot-descriptions to main. Taku is not on main.

The in-tree package lives at humanoid/Dyna/taku_description on feature/agilex (package README). After a normal init (or the HTTPS clone of robot_descriptions on main):

cd src/robot-descriptions
git fetch origin
git checkout feature/agilex
# common is required (sensor_models / robot_common_launch)
git clone https://github.com/fiveages-sim/robot-descriptions-common.git common
# or, if SSH works: git submodule update --init common

If you are starting from a clean HTTPS tree, clone descriptions on that branch in one step: git clone -b feature/agilex https://github.com/fiveages-sim/robot_descriptions.git src/robot-descriptions.

Verified launch keys from that package README (robot:=taku → taku_description):

colcon build --packages-up-to taku_description sensor_models --symlink-install
source install/setup.bash
ros2 launch robot_common_launch humanoid.launch.py robot:=taku

Control launches from that package README §3.1 / §3.2 (after descriptions on feature/agilex). Default hardware:=mock_components. Layout has no chassis or per-arm basic controllers. Dynaclaw uses adaptive_gripper_controller (left/right_gripper_controller; joints *_gripper_joint with a mimic jaw in URDF). Meshes live under meshes/{chassis,body,head,arm,dynaclaw}/.

colcon build --packages-up-to ocs2_arm_controller taku_description
source install/setup.bash
# 分体 — public mock path (arm MPC + body/head basic + grippers)
ros2 launch ocs2_arm_controller split_body.launch.py robot:=taku
# 全身 — needs the private ocs2_wbc_controller submodule
ros2 launch ocs2_arm_controller full_body.launch.py robot:=taku

Public mock vs private WBC

Shipping config/ocs2/fixed_base_tcp.info in the public description does not mean public mock can run ocs2_wbc_controller. Public mock uses split_body.launch.py. full_body.launch.py needs the private WBC submodule.

Launch

Controllers

split_body.launch.py

ocs2_arm_controller (dual-arm MPC, info_file_name: task) + body_joint_controller (folding_low/high + waist_pitch/yaw) + head_joint_controller (head_yaw/pitch/roll) + grippers

full_body.launch.py

ocs2_wbc_controller (body + dual arms + head, info_file_name: fixed_base_tcp) + grippers

When that config and the private module are present, full-body default headMode is HEAD_GAZE (gaze on head_camera_mid_optical_frame). target_manager.yaml has enable_head_control: false, so the head follows OCS2 rather than a joint-space marker. Split-body still teleops the head through head_joint_controller (RViz joint panel). Taku body-relative rest is around x≈−0.21, not Bot2 [0, 0.25].

In RViz, set Fixed Frame to base_link (or the coincident base_footprint). OCS2 baseFrame / markers use base_link. There is no hardware:=mock — the default key is mock_components. hardware:=gz may need a GPU; mock + RViz is the default verify path. The package README also lists hardware:=isaac on the same split / full launches.

ocs2_arm_controller split_body.launch.py / full_body.launch.py use the same robot:=<key> → {key}_description lookup. Taku ships config/ocs2/ (task.info for split, fixed_base_tcp.info for full-body) and a ros2_control yaml that names ocs2_arm_controller / ocs2_wbc_controller, so robot:=taku is the same convention — not a special-cased flag.

The description is inferred (public Dyna kinematics; not official Dyna specs). That is stated in the package README.

Empty private directories and COLCON_IGNORE

In public mode, ./init_repo.sh skips private nested modules listed in submodules_visibility.conf. Under src/arms_ros2_control those placeholders stay empty, including:

  • controller/ocs2_wbc_controller

  • libraries/lina_planning

  • libraries/ocs2_humanoid

Empty private / uninitialized hardware dirs can make colcon build fail (colcon still walks them).

Current ./init_repo.sh writes COLCON_IGNORE on uninitialized nested paths (including hardwares/* and private visibility entries). A later private init removes that marker before clone. You do not need to touch these by hand.

If colcon still walks an empty dir (checkout predates this), pull main and re-run init, or touch <empty-dir>/COLCON_IGNORE.

Building

./init_repo.sh already runs rosdep install on source paths. You still need to colcon-build:

colcon build --symlink-install

Then source install/setup.bash in the terminal you launch from. The README does not install a workspace env script besides ./init_repo.sh.

Partial Build

Build only specific packages:

# Just descriptions
colcon build --packages-select robot-descriptions-dobot

# Up to a specific package
colcon build --packages-up-to ocs2_arm_controller

Supported Robots

Robot

Description Package

Hardware Interface

Notes

Dobot CR5

robot-descriptions-dobot

dobot-cr-ros2-control

dobot-cr5 branch

ARX X5

robot-descriptions-arx

arx-ros2-control

Co-debug in arx-lift2s

Acone / AC One

robot-descriptions-arx

arx-ros2-control

Dual-arm (not Lift 2S)

ARX Lift 2S

robot-descriptions-arx

arx-ros2-control

Full-body (arms + lift + chassis); branch arx-lift2s

Galbot

robot-descriptions-galbot

(varies)

Simulation-oriented

HighTorque Panthera HT

panthera_ht_description

ht-ros2-control

Dual-arm; branch panthera-ht; umbrella path manipulator/HighTorque/panthera_ht_description

Taku (Dyna / DVT1)

taku_description

mock / gz / isaac in package xacro

In-tree on robot_descriptions feature/agilex at humanoid/Dyna/taku_description; visualize humanoid.launch.py; control split_body.launch.py / full_body.launch.py

Quadruped

robot-descriptions-quadruped

unitree-ros2-control

Simulation-oriented

Real Hardware Deployment

ARX Lift 2S (方舟无限) is the full-body mobile manipulator. Acone / AC One is dual-arm. HighTorque Panthera HT (高擎) is a dual-arm manipulator. See ARX Lift 2S, HighTorque Panthera HT, and Go to Real Hardware.

Launch Examples

Mock Hardware Demo

source install/setup.bash
ros2 launch ocs2_arm_controller demo.launch.py

demo.launch.py defaults: robot:=cr5, hardware:=mock_components. There is no hardware:=mock.

With Specific Robot

# Acone (dual-arm, not Lift 2S). Omit hardware:= to keep mock_components.
ros2 launch ocs2_arm_controller demo.launch.py robot:=arx_acone

# Taku (descriptions on feature/agilex). RViz Fixed Frame: base_link (or base_footprint).
ros2 launch ocs2_arm_controller split_body.launch.py robot:=taku

Taku visualize path (package README): ros2 launch robot_common_launch humanoid.launch.py robot:=taku. Control is split_body.launch.py / full_body.launch.py — see Taku / feature/agilex for the build, WBC, and Fixed Frame notes.

End-effector (type)

Not gripper:=. Symmetric: type:=<eef_key>. Different L/R: left_type:= / right_type:= together (do not pass type:= then). Profile defaults.end_effectors is used when use_profile_eef:=true (default). See robot_common_launch.

ros2 launch ocs2_arm_controller demo.launch.py \
  robot:=<robot_name> \
  use_profile_eef:=false \
  left_type:=rg75 right_type:=linkerhand_o7

Adding Robot Descriptions

To add a new robot to your workspace:

Prefer ./init_repo.sh so nested modules under src/robot-descriptions/ match submodules_visibility.conf. Do not git submodule update --init --recursive. Then colcon build the packages you need.

Submodule Management

Prefer ./init_repo.sh (menu 1 or 2) over a recursive submodule init. Check status with git submodule status. To update a specific source tree you already initialized, pull that module then rebuild.

GitHub Release .deb vs Source Matrix

Component

GitHub Release .deb

Source Path

OCS2

ros-jazzy-ocs2 (releases)

src/ocs2_ros2

Common descriptions

ros-jazzy-robot-descriptions-common (releases)

src/robot-descriptions/common

arms_ros2_control

ros-jazzy-arms-ros2-control (optional; releases)

src/arms_ros2_control

Check deb_versions.conf for the GitHub repos and release tags used by scripts/install_core_debs.sh. These packages are not in the ROS apt index.

Common Issues

Submodules Empty

Re-run ./init_repo.sh (menu 1). Do not use git submodule update --init --recursive as the primary recovery path.

cannot run ssh / Access Denied to Submodule

.gitmodules URLs are SSH. insteadOf HTTPS rewrite alone does not fix git submodule update. Current ./init_repo.sh rewrites .gitmodules to HTTPS for the fetch and restores it afterwards — use --https / OPEN_DEPLOY_GIT_HTTPS=1 to force that.

Some nested modules are private. In open-deploy-ws, only public nested modules should be required. If you see access errors:

  1. Check you’re on the correct branch (not accidentally on a private branch)

  2. Verify the submodule is listed as public in submodules_visibility.conf

  3. If an empty private dir still breaks colcon, re-run ./init_repo.sh so it writes COLCON_IGNORE, or touch <empty-dir>/COLCON_IGNORE

Build Fails with numpy

pip install 'numpy<2'

CAN Interface Rename Needed

For CAN-based robots, you may need to rename the interface:

sudo ip link set can0 down
sudo ip link set can0 name <expected_name>
sudo ip link set <expected_name> up

Next Steps