Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .ci/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
# Exit immediately if a command exits with a non-zero status.
set -e

source "/opt/ros/humble/setup.bash"


if [ -f "/ros2_ws/install/setup.bash" ]; then
source "/ros2_ws/install/setup.bash"
# Optional: Log that the workspace was found
# echo "✅ Workspace sourced."
fi

exec "$@"
79 changes: 79 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# --- Configuration ---
# Load variables from .env if it exists
ifneq ("$(wildcard .env)","")
include .env
export $(shell sed 's/=.*//' .env)
endif

# Default shell
SHELL := /bin/bash

# --- Help ---
.PHONY: help
help:
@echo "Vive Controller Docker Management"
@echo "Usage: make <target>"
@echo ""
@echo "Robot Missions:"
@echo " make franka - Start Franka (Single Right Controller)"
@echo " make tiago - Start Tiago Dual Arm"
@echo " make g1 - Start G1 Dual Arm"
@echo ""
@echo "Utility:"
@echo " make build - Build the 'app' image (cached)"
@echo " make build-force - Build from scratch (no cache)"
@echo " make calibrate - Run workspace calibration"
@echo " make identify - Vibrate controllers to check IDs"
@echo " make stop - Stop all running vive containers"
@echo " make clean - Remove all vive containers and networks"

# --- GUI Permissions ---
.PHONY: gui-perms
gui-perms:
@echo "Setting X11 permissions for Docker..."
@xhost + > /dev/null

# --- Build Targets ---
.PHONY: build
build:
docker compose build

.PHONY: build-force
build-force:
docker compose build --no-cache

# --- Robot Missions ---
.PHONY: franka
franka: gui-perms
docker compose --profile franka up

.PHONY: tiago
tiago: gui-perms
docker compose --profile tiago up

.PHONY: g1
g1: gui-perms
docker compose --profile g1 up

# --- Utilities ---
.PHONY: calibrate
calibrate: gui-perms
# Runs calibration inside the franka container context
docker compose --profile franka run --rm franka ros2 launch ros2_vive_controller calibration.launch.py

.PHONY: identify
identify:
@echo "Vibrating RIGHT controller..."
-docker exec -it ros2_vive_franka /entrypoint.sh ros2 service call /vive/right/identify std_srvs/srv/Trigger || \
docker exec -it ros2_vive_tiago /entrypoint.sh ros2 service call /vive/right/identify std_srvs/srv/Trigger || \
docker exec -it ros2_vive_g1 /entrypoint.sh ros2 service call /vive/right/identify std_srvs/srv/Trigger
@echo "Vibrating LEFT controller..."
-docker exec -it ros2_vive_tiago /entrypoint.sh ros2 service call /vive/left/identify std_srvs/srv/Trigger || \
docker exec -it ros2_vive_g1 /entrypoint.sh ros2 service call /vive/left/identify std_srvs/srv/Trigger
.PHONY: stop
stop:
docker compose down

.PHONY: clean
clean:
docker compose down --remove-orphans --volumes
33 changes: 13 additions & 20 deletions config/cyclonedds.xml
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
<CycloneDDS>
<Domain>
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
<Domain id="any">
<General>
<AllowMulticast>false</AllowMulticast>
<MaxMessageSize>1400B</MaxMessageSize>
<Interfaces>
<NetworkInterface name="enx607d09178f25" priority="1" />
<NetworkInterface name="lo" priority="0" />
<NetworkInterface name="enx607d09178f25" />
</Interfaces>
<AllowMulticast>true</AllowMulticast>
</General>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<Peers>
<Peer Address="10.68.0.132" />
<Peer Address="10.68.0.1" />
<Peer Address="localhost" />
<Peer address="176.16.0.1"/>
<Peer address="192.168.1.2"/>
<Peer address="192.168.1.1"/>
<Peer address="192.168.1.42"/>
</Peers>
<MaxAutoParticipantIndex>500</MaxAutoParticipantIndex>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>200</MaxAutoParticipantIndex>
</Discovery>
<Internal>
<Watermarks>
<WhcHigh>2000kB</WhcHigh>
</Watermarks>
</Internal>
<Tracing>
<Verbosity>config</Verbosity>
<OutputFile>${HOME}/.ros/log/cdds.log</OutputFile>
</Tracing>
</Domain>
</CycloneDDS>
23 changes: 23 additions & 0 deletions config/franka_cyclonedds.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
<Domain id="any">
<General>
<Interfaces>
<NetworkInterface name="enx607d09178f25" />
</Interfaces>
<AllowMulticast>true</AllowMulticast>
</General>
<Discovery>
<Peers>
<Peer address="176.16.0.1"/>
<Peer address="192.168.1.2"/>
<Peer address="192.168.1.1"/>
<Peer address="192.168.1.42"/>
</Peers>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>200</MaxAutoParticipantIndex>
</Discovery>
</Domain>
</CycloneDDS>
23 changes: 23 additions & 0 deletions config/tiago_cyclonedds.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
<Domain id="any">
<General>
<Interfaces>
<NetworkInterface name="enx607d09178f25" />
</Interfaces>
<AllowMulticast>true</AllowMulticast>
</General>
<Discovery>
<Peers>
<Peer address="176.16.0.1"/>
<Peer address="192.168.1.2"/>
<Peer address="192.168.1.1"/>
<Peer address="192.168.1.42"/>
</Peers>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>200</MaxAutoParticipantIndex>
</Discovery>
</Domain>
</CycloneDDS>
119 changes: 103 additions & 16 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
services:
# ── RULE: Common Environment Variables ─────────────────────────────────────
x-common-env: &common_env
DISPLAY: ${DISPLAY}
NVIDIA_DRIVER_CAPABILITIES: all
XDG_RUNTIME_DIR: ${XDG_RUNTIME_DIR}
QT_X11_NO_MITSHM: 1

# ── RULE: ROS Environment Variables ────────────────────────────────────────
x-ros-env: &ros_env
ROS_DOMAIN_ID: ${ROS_DOMAIN_ID:-1}
RMW_IMPLEMENTATION: rmw_cyclonedds_cpp

services:
# ── bimanual: bimanual tracker (left + right) ─────────────────────────────
bimanual_vive_tracker:
profiles: [bimanual]
Expand All @@ -17,14 +28,9 @@ services:
pid: host
privileged: true
environment:
- DISPLAY=${DISPLAY}
- NVIDIA_DRIVER_CAPABILITIES=all
- XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}
- QT_X11_NO_MITSHM=1
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-1}
- RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
- HAND_OFFSET_LEFT=${HAND_OFFSET_LEFT:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
- HAND_OFFSET_RIGHT=${HAND_OFFSET_RIGHT:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
<<: [*common_env, *ros_env]
HAND_OFFSET_LEFT: ${HAND_OFFSET_LEFT:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
HAND_OFFSET_RIGHT: ${HAND_OFFSET_RIGHT:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- /dev:/dev
Expand Down Expand Up @@ -73,13 +79,8 @@ services:
pid: host
privileged: true
environment:
- DISPLAY=${DISPLAY}
- NVIDIA_DRIVER_CAPABILITIES=all
- XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}
- QT_X11_NO_MITSHM=1
- ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-1}
- RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
- HAND_OFFSET=${HAND_OFFSET:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
<<: [*common_env, *ros_env]
HAND_OFFSET: ${HAND_OFFSET:-[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- /dev:/dev
Expand Down Expand Up @@ -109,3 +110,89 @@ services:
- driver: nvidia
count: all
capabilities: [gpu]

# ── COMMON BASE: for controllers ──────────────────────────────────────────
base_robot: &base_robot
image: ${REGISTRY:-registry.gitlab.inria.fr/eurobin-horizon/code/vive_controller_tiago}/vive-controller:${TAG:-latest}
build:
context: .
dockerfile: .ci/Dockerfile
target: app
args:
STEAM_USER: ${STEAM_USER}
STEAM_PASSWORD: ${STEAM_PASSWORD}
network_mode: host
ipc: host
pid: host
privileged: true
environment:
<<: [*common_env, *ros_env]
CYCLONEDDS_URI: file:///ros2_ws/src/ros2_vive_controller/config/cyclonedds.xml
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- /dev:/dev
- /run/udev:/run/udev
- ./config/steamvr_config/openvrpaths.vrpath:/root/.config/openvr/openvrpaths.vrpath
- ./config/steamvr_config/default_driver_null:/home/steam/Steam/steamapps/common/SteamVR/drivers/null/resources/settings/default.vrsettings
- ./config/steamvr_config/default_resources:/home/steam/Steam/steamapps/common/SteamVR/resources/settings/default.vrsettings
- ./ros2_vive_controller:/ros2_ws/src/ros2_vive_controller/ros2_vive_controller
- ./launch:/ros2_ws/src/ros2_vive_controller/launch
- ./config:/ros2_ws/src/ros2_vive_controller/config
- ./rviz:/ros2_ws/src/ros2_vive_controller/rviz
- ./assets:/ros2_ws/src/ros2_vive_controller/assets
- ./setup.py:/ros2_ws/src/ros2_vive_controller/setup.py
working_dir: /ros2_ws
entrypoint: ["/entrypoint.sh"]
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

# ── FRANKA: (Single Arm) ────────────────────────────────────────────────
franka:
<<: *base_robot
profiles: [franka]
container_name: ros2_vive_franka
env_file:
- .env
environment:
<<: [*common_env, *ros_env]
CYCLONEDDS_URI: file:///ros2_ws/src/ros2_vive_controller/config/franka_cyclonedds.xml
command: >
ros2 launch ros2_vive_controller franka_single.launch.py
serial_right:=${SERIAL_RIGHT:-LHR-9ABF6D66}
reference_lighthouse_serial:=${REFERENCE_LIGHTHOUSE_SERIAL:-}
only_right:=true
linear_scale:=${LINEAR_SCALE:-2.0}

# ── TIAGO (Dual Arm) ─────────────────────────────────────────────────────
tiago:
<<: *base_robot
profiles: [tiago]
container_name: ros2_vive_tiago
env_file: .env
environment:
<<: [*common_env, *ros_env]
CYCLONEDDS_URI: file:///ros2_ws/src/ros2_vive_controller/config/tiago_cyclonedds.xml
command: >
ros2 launch ros2_vive_controller tiago_dual.launch.py
serial_left:=${SERIAL_LEFT:-LHR-97752221}
serial_right:=${SERIAL_RIGHT:-LHR-9ABF6D66}
linear_scale:=${LINEAR_SCALE:-1.0}

# ── G1 (Dual Arm) ────────────────────────────────────────────────────────
g1:
<<: *base_robot
profiles: [g1]
container_name: ros2_vive_g1
environment:
<<: [*common_env, *ros_env]
CYCLONEDDS_URI: file:///ros2_ws/src/ros2_vive_controller/config/cyclonedds.xml
command: >
ros2 launch ros2_vive_controller g1_dual.launch.py
serial_left:=${SERIAL_LEFT:-LHR-97752221}
serial_right:=${SERIAL_RIGHT:-LHR-9ABF6D66}
linear_scale:=${LINEAR_SCALE:-1.0}
Loading