Skip to content

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

4 watching

Forks

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Phase 2 Updates (Physical Deployment Phase)

  • Book spine width: Books have returned to 3cm wide to match the physical build. Please update your parameters accordingly.
  • Number markers: Markers have been added to the top shelf row of each column for better visibility from the TIAGo Pro.
  • Updated launch files: The simulation launch files have been updated to include the Round 1 and Round 2 environments:
ros2 launch erc_bringup simulation_round_1.launch.py   # Round 1 environment
ros2 launch erc_bringup simulation_round_2.launch.py   # Round 2 environment

Updates 11/09/26

  • Competition Rules Update: Book spine width reduced from 3cm to 2cm. Please update parameters accordingly.
  • Manipulation: A possible workaround to issue #2 is using the position controller and the effort interface feedback from the gripper to keep publishing position in a closed-loop. This produces the following video:
tiago_pro_book_grip_test.webm

Emirates Robotics Competition 2026

Library Assistant Robot challenge: Autonomous book retrieval using a TIAGo Pro mobile manipulator.

Prerequisites

  • x86_64 (amd64) architecture. ARM-based hosts (e.g. Apple Silicon) are not supported
  • Linux host (Ubuntu 22.04/24.04 recommended) with X11
  • Docker Engine + Docker Compose v2
  • Git
  • NVIDIA GPU + nvidia-container-toolkit for GPU-accelerated rendering # Rendering is slow but possible without NVIDIA GPU
  • ~15GB free disk space

Note: The default ROS_DOMAIN_ID is 23. If you are running multiple ROS 2 environments on the same network, ensure there are no domain ID conflicts.

Quick start

All dependencies are vendored in this repository — there is no separate dependency-fetching step, and no network access is needed after cloning.

# — Host terminal —
./docker/up.sh --build                        # Build image & start container
./docker/attach.sh                            # Open shell inside container

# — Inside container (after attach) —
colcon build --symlink-install                # Build workspace packages (first run takes several minutes)
source install/setup.bash                     # Source the workspace
ros2 launch erc_bringup simulation.launch.py  # Launch Gazebo + robot

To open additional terminals into the running container:

# — Host terminal —                           # Navigate to the repository root (where "docker/", "src/", and "docs/" are located)
./docker/attach.sh                            # Do NOT run ./docker/up.sh again as this will kill your running container

The video below is a visual guide for the above steps.

erc_code_run_trimmed_2.mp4

Robot platform

TIAGo Pro by PAL Robotics — omnidirectional mobile manipulator.

Hardware in simulation:

  • Omnidirectional mecanum base (4 mecanum wheels, full holonomic motion)
  • Two 7-DOF arms (left and right) with PAL Pro grippers
  • Pan-tilt head (2 DOF)
  • Prismatic torso lift
  • Intel RealSense D435i RGB-D camera (head-mounted)
  • Two 270° LiDARs (front and rear, base-mounted)
  • IMU (base)

ROS 2 topics and controllers

Mobile base

The base is driven by the Gazebo MecanumDrive plugin. Publish a standard Twist message to move the robot in any direction.

Topic Type Direction Description
/cmd_vel geometry_msgs/Twist Subscriber Base velocity (linear.x, linear.y, angular.z)
/odom nav_msgs/Odometry Publisher Wheel odometry

Examples:

# Drive forward
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.3, y: 0.0}, angular: {z: 0.0}}" --rate 10

# Strafe left
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0, y: 0.3}, angular: {z: 0.0}}" --rate 10

# Rotate in place
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0, y: 0.0}, angular: {z: 0.5}}" --rate 10

# Diagonal movement (forward + left)
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.3, y: 0.3}, angular: {z: 0.0}}" --rate 10

Joint controllers

All joint controllers use joint_trajectory_controller/JointTrajectoryController via ros2_control. Send trajectories using the action interface or the topic shortcut.

Controller Topic Joints
arm_left_controller /arm_left_controller/joint_trajectory arm_left_1_joint .. arm_left_7_joint
arm_right_controller /arm_right_controller/joint_trajectory arm_right_1_joint .. arm_right_7_joint
gripper_left_controller_raw /gripper_left_controller_raw/joint_trajectory gripper_left_finger_joint
gripper_right_controller_raw /gripper_right_controller_raw/joint_trajectory gripper_right_finger_joint
head_controller /head_controller/joint_trajectory head_1_joint, head_2_joint
torso_controller /torso_controller/joint_trajectory torso_lift_joint
joint_state_broadcaster /joint_states All joints (read-only)

Examples:

# — Left arm: move joint 1 to 0.5 rad —
ros2 topic pub --once /arm_left_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [arm_left_1_joint, arm_left_2_joint, arm_left_3_joint, arm_left_4_joint, \
  arm_left_5_joint, arm_left_6_joint, arm_left_7_joint], \
  points: [{positions: [0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], time_from_start: {sec: 2}}]}"

# — Right arm: move joint 1 to -0.5 rad —
ros2 topic pub --once /arm_right_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [arm_right_1_joint, arm_right_2_joint, arm_right_3_joint, arm_right_4_joint, \
  arm_right_5_joint, arm_right_6_joint, arm_right_7_joint], \
  points: [{positions: [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], time_from_start: {sec: 2}}]}"

# — Left gripper: close (0.0 = closed, 0.04 = open) —
ros2 topic pub --once /gripper_left_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [gripper_left_finger_joint], \
  points: [{positions: [0.0], time_from_start: {sec: 1}}]}"

# — Left gripper: open —
ros2 topic pub --once /gripper_left_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [gripper_left_finger_joint], \
  points: [{positions: [0.04], time_from_start: {sec: 1}}]}"

# — Right gripper: close —
ros2 topic pub --once /gripper_right_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [gripper_right_finger_joint], \
  points: [{positions: [0.0], time_from_start: {sec: 1}}]}"

# — Right gripper: open —
ros2 topic pub --once /gripper_right_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [gripper_right_finger_joint], \
  points: [{positions: [0.04], time_from_start: {sec: 1}}]}"

# — Head: pan left 0.5 rad, tilt down 0.3 rad —
ros2 topic pub --once /head_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [head_1_joint, head_2_joint], \
  points: [{positions: [0.5, -0.3], time_from_start: {sec: 1}}]}"

# — Torso: raise to 0.3 m —
ros2 topic pub --once /torso_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory \
  "{joint_names: [torso_lift_joint], \
  points: [{positions: [0.3], time_from_start: {sec: 2}}]}"

Sensors

Topic Type Description
/scan_front_raw sensor_msgs/msg/LaserScan Front LiDAR
/scan_rear_raw sensor_msgs/msg/LaserScan Rear LiDAR
/head_front_camera/head_front_camera/color/image_raw sensor_msgs/msg/Image Head RGB camera
/head_front_camera/head_front_camera/color/camera_info sensor_msgs/msg/CameraInfo Head RGB camera info
/head_front_camera/head_front_camera/depth/image_rect_raw sensor_msgs/msg/Image Head depth camera (float32)
/head_front_camera/head_front_camera/depth/camera_info sensor_msgs/msg/CameraInfo Head depth camera info
/head_front_camera/head_front_camera/depth/color/points sensor_msgs/msg/PointCloud2
/base_imu sensor_msgs/msg/Imu Base IMU
/contacts ros_gz_interfaces/msg/Contacts Contact sensor
/bin_contacts ros_gz_interfaces/msg/Contacts

Sensor specifications

Sensor Parameter Value
Head RGB camera Resolution 640 × 360 px
Horizontal FOV 1.518 rad (87°)
Vertical FOV 0.977 rad (56°)
Update rate 30 Hz
Head depth camera Resolution 640 × 360 px
Depth range 0.2 – 8.0 m
Update rate 30 Hz
Front / Rear LiDAR Model SICK TIM551 (gpu_lidar)
FOV ~270°
Range 0.05 – 25.0 m
Samples 818 (0.33°/step)
Update rate 10 Hz
Base IMU Update rate 100 Hz

Software stack

Component Version
ROS 2 Humble
Gazebo Harmonic
Physics engine DART
DDS CycloneDDS
Robot description PAL Robotics (vendored, see above)
Controller framework ros2_control + gz_ros2_control

Vendored dependencies

Package Upstream Branch
launch_pal https://github.com/pal-robotics/launch_pal master
pal_urdf_utils https://github.com/pal-robotics/pal_urdf_utils humble-devel
pal_gripper https://github.com/pal-robotics/pal_gripper humble-devel
pal_pro_gripper https://github.com/pal-robotics/pal_pro_gripper humble-devel
tiago_pro_robot https://github.com/pal-robotics/tiago_pro_robot humble-devel
pal_sea_arm https://github.com/pal-robotics/pal_sea_arm humble-devel
tiago_pro_head_robot https://github.com/pal-robotics/tiago_pro_head_robot humble-devel
omni_base_robot https://github.com/pal-robotics/omni_base_robot humble-devel
gz_ros2_control https://github.com/ros-controls/gz_ros2_control humble

URDF generation

The robot URDF is generated from PAL's xacro sources with Gazebo Harmonic patches applied and saved to src/erc_description/urdf/tiago_pro.urdf which is accessible on the host for inspection. Because the workspace is built with --symlink-install, the URDF is picked up immediately when created with no rebuild required.

Reporting issues

If you notice a bug, an error in the documentation, or anything in the code that needs changing, please submit an issue on the repository rather than reporting it elsewhere. This keeps all known issues visible and traceable for both participants and organisers.

  1. In the "Title" field, type a title for your issue.
  2. In the comment body field, type a description of your issue. To cross-reference a related discussion, paste the discussion's URL into the issue description.

Before opening a new issue, search existing issues to check whether it has already been reported. When describing your issue, include:

  • Steps to reproduce the problem
  • Expected vs. actual behaviour
  • Relevant terminal output or logs
  • Your host environment (OS, GPU, ROS_DOMAIN_ID if changed from default)

Troubleshooting

CycloneDDS serialization warnings (serdata.cpp errors about null-terminated strings) — these are harmless noise from large message serialization. They don't affect functionality.

Robot not spawning — wait at least 5 seconds after Gazebo starts. The spawn is on a 3-second timer, books on a 5-second timer, and controllers on an 8-second timer.

Controllers not activating — check that erc_bringup was built: colcon build --symlink-install --packages-select erc_bringup && source install/setup.bash

Base not strafing (lateral movement) — ensure you're publishing to /cmd_vel with linear.y set. The mecanum drive requires the anisotropic friction parameters injected into the URDF by generate_urdf.py.

Build errors after mixing build flags — always build with --symlink-install. Mixing symlink and non-symlink builds leaves stale artifacts; recover with rm -rf build/ install/ log/ and rebuild.

Rebuild after Dockerfile changes — run ./docker/up.sh --build to rebuild the image.

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages