diff --git a/Dockerfile b/Dockerfile index 14ad3fc..4dfd39e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,26 @@ ARG base_image="robotnik/ros" ARG ros_distro="jazzy" ARG image_base_version="0.6.2" -ARG ros_mirror="ros.mirror.robotnik.ws" FROM ${base_image}:${ros_distro}-builder-${image_base_version} AS builder +ARG ros_distro + ENV DEBIAN_FRONTEND=noninteractive +ENV GZ_VERSION=harmonic USER root -# Install compiled packages +# Install compiled packages and dependencies +RUN curl https://packages.osrfoundation.org/gazebo.gpg --output /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/gazebo-stable.list + RUN --mount=type=bind,\ target=/tmp/requirements.txt,\ source=dependencies/requirements/builder/packages.txt \ - true \ - && if \ - timeout 2 curl -IsS http://${ros_mirror} &>/dev/null; \ - then \ - sed -i \ - "s#packages.ros.org#${ros_mirror}#" \ - /etc/apt/sources.list.d/ros-latest.list ;\ - fi \ - && apt-fast update \ + apt-fast update \ + && apt-get remove -y ros-${ROS_DISTRO}-ros-gz* \ + && apt-get upgrade -y \ && apt-fast install -q -y \ --no-install-recommends \ $(eval "echo $(cat /tmp/requirements.txt | xargs)") \ @@ -33,17 +32,23 @@ source=dependencies/requirements/builder/packages.txt \ USER ${USER_NAME} RUN --mount=type=bind,\ -source=./dependencies/repos/common.repo.yml,\ +source=./robotnik_simulation.${ros_distro}.repos,\ target=/tmp/common.repo.yml,ro \ - vcs import \ + vcs import \ --input /tmp/common.repo.yml \ - --shallow + --shallow src + +RUN wget -O ${USER_HOME}/.ros/gazebo_rosdep.yaml \ + https://raw.githubusercontent.com/osrf/osrf-rosdep/refs/heads/master/gz/gazebo.yaml \ + && echo "yaml file://${USER_HOME}/.ros/gazebo_rosdep.yaml" | sudo tee -a /etc/ros/rosdep/sources.list.d/50-gazebo-latest.list +# remove ros_gz* exec_depend, depends and build_depend from package.xml files +RUN find src/ -type f -name 'package.xml' -exec sed -i 's/ros_gz.*<\/depend>//g; s/ros_gz.*<\/exec_depend>//g; s/ros_gz.*<\/build_depend>//g' {} + # Generate deb packages RUN generate_debs.sh -RUN cp /home/robot/robot_ws/src/robotnik_simulation/debs/ros-${ROS_DISTRO}-*.deb /home/robot/robot_ws/debs +RUN cp /home/robot/robot_ws/src/robotnik/robotnik_simulation/debs/ros-${ROS_DISTRO}-*.deb /home/robot/robot_ws/debs WORKDIR /home/robot/robot_ws/debs # Generate Packages.gz RUN dpkg-scanpackages . | gzip -9c > Packages.gz @@ -52,11 +57,14 @@ RUN dpkg-scanpackages . | gzip -9c > Packages.gz # BASE FROM ${base_image}:${ros_distro}-base-${image_base_version} AS base +USER root + # Add Gazebo GPG key -RUN sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list'\ - && wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add - +RUN curl https://packages.osrfoundation.org/gazebo.gpg --output /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/gazebo-stable.list + +ENV GZ_VERSION=harmonic -USER root # Install compiled packages and dependencies RUN \ --mount=\ @@ -69,33 +77,30 @@ type=bind,\ target=/tmp/requirements.txt,\ source=dependencies/requirements/base/packages.txt \ true \ - && if \ - timeout 2 curl -IsS http://${ros_mirror} &>/dev/null; \ - then \ - sed -i \ - "s#packages.ros.org#${ros_mirror}#" \ - /etc/apt/sources.list.d/ros-latest.list ;\ - fi \ && echo "deb [trusted=yes] file:///tmp/debs/ ./" | tee /etc/apt/sources.list.d/debs.list \ - #&& cp /etc/apt/sources.list.d/debs.list /home/robot/robot_ws/ && cp -r /tmp/debs /home/robot/robot_ws/ \ && apt-get update \ + && apt-get upgrade -y \ + && apt-get remove -y ros-${ROS_DISTRO}-ros-gz* \ && apt-fast install -q -y \ --no-install-recommends \ $(eval "echo $(cat /tmp/requirements.txt | xargs)") \ - #&& sed -i "s#${ros_mirror}#packages.ros.org#" /etc/apt/sources.list.d/ros-latest.list \ - && dpkg -i $(find /tmp/debs -name "*.deb" | xargs) \ - #&& cp -r /tmp/debs /home/robot/robot_ws/ \ + /tmp/debs/ros-${ROS_DISTRO}-*.deb \ && apt-get clean -q -y \ && apt-get autoremove -q -y \ && rm -rf /var/lib/apt/lists/* \ && rm /etc/apt/sources.list.d/debs.list \ && true +RUN apt-get update && apt-get upgrade -y \ + && apt-get clean -y \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* + USER ${USER_NAME} -# The image is built to run gazebo ignition by default if no other setup is provided. -ENV STARTUP_TYPE="launch" -ENV ROS_BU_PKG="robotnik_gazebo_ignition" -ENV ROS_BU_LAUNCH="spawn_world.launch.py" +# # # The image is built to run gazebo ignition by default if no other setup is provided. +# # ENV STARTUP_TYPE="launch" +# # ENV ROS_BU_PKG="robotnik_gazebo_ignition" +# # ENV ROS_BU_LAUNCH="spawn_world.launch.py" -ENV QT_X11_NO_MITSHM=1 +# # ENV QT_X11_NO_MITSHM=1 diff --git a/dependencies/requirements/base/packages.txt b/dependencies/requirements/base/packages.txt index 4addd75..3a61ad3 100644 --- a/dependencies/requirements/base/packages.txt +++ b/dependencies/requirements/base/packages.txt @@ -1,12 +1,10 @@ -libgz-sim8-dev -ros-jazzy-ros-gz-sim -ros-jazzy-ros-gz -ros-jazzy-controller-manager -ros-jazzy-gz-ros2-control -ros-jazzy-joint-state-broadcaster -ros-jazzy-teleop-twist-keyboard -ros-jazzy-joint-trajectory-controller -ros-jazzy-rqt-joint-trajectory-controller -ros-jazzy-joint-state-publisher -ros-jazzy-joint-state-publisher-gui -ros-jazzy-plotjuggler-ros +ros-${ROS_DISTRO}-controller-manager +ros-${ROS_DISTRO}-joint-state-broadcaster +ros-${ROS_DISTRO}-teleop-twist-keyboard +ros-${ROS_DISTRO}-joint-trajectory-controller +ros-${ROS_DISTRO}-rqt-joint-trajectory-controller +ros-${ROS_DISTRO}-joint-state-publisher +ros-${ROS_DISTRO}-joint-state-publisher-gui +ros-${ROS_DISTRO}-plotjuggler-ros +gz-harmonic +ros-${ROS_DISTRO}-ros-gzharmonic diff --git a/dependencies/requirements/builder/packages.txt b/dependencies/requirements/builder/packages.txt index d1a1d0c..4f30a05 100644 --- a/dependencies/requirements/builder/packages.txt +++ b/dependencies/requirements/builder/packages.txt @@ -2,3 +2,5 @@ build-essential git python3-vcstool python3-colcon-common-extensions +gz-harmonic +ros-${ROS_DISTRO}-ros-gzharmonic diff --git a/docker-compose.yaml b/docker-compose.yaml index c6e8ab4..490fd09 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,48 +1,31 @@ -services: - robotnik_simulator: - container_name: robotnik_simulator - image: robotnik_simulation-robotnik_simulation:latest - build: - context: . - dockerfile: ./Dockerfile - args: - base_image: robotnik/ros - ros_distro: jazzy - image_base_version: 0.6.2 - ros_mirror: ros.mirror.robotnik.ws - network_mode: host - privileged: true - runtime: nvidia - environment: - ROS_DOMAIN_ID: 0 - DISPLAY: ${DISPLAY} # Forward X11 display - NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics # Allow GPU access - NVIDIA_VISIBLE_DEVICES: all # Expose all GPUs - devices: - - "/dev/dri:/dev/dri" # Allow OpenGL rendering - - /tmp/.X11-unix:/tmp/.X11-unix - robotnik_robot_spawner: - container_name: robotnik_robot_spawner - image: robotnik_simulation-robotnik_simulation:latest - network_mode: host - privileged: true - runtime: nvidia - env_file: - - env/robot.env - environment: - ROS_DOMAIN_ID: 0 - DISPLAY: ${DISPLAY} # Forward X11 display - NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics # Allow GPU access - NVIDIA_VISIBLE_DEVICES: all # Expose all GPUs - ROS_BU_LAUNCH: spawn_robot.launch.py robot:=$${ROBOT} robot_model:=$${ROBOT_MODEL} has_arm:=$${HAS_ARM} - devices: - - "/dev/dri:/dev/dri" # Allow OpenGL rendering - - /tmp/.X11-unix:/tmp/.X11-unix - depends_on: - robotnik_simulator: - condition: service_healthy +x-gazebo-simulation: &simulation + image: test + build: + context: . + args: + ros_distro: jazzy + network_mode: host + privileged: true + runtime: nvidia + environment: + ROS_DOMAIN_ID: 0 + DISPLAY: ${DISPLAY} # Forward X11 display + NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics # Allow GPU access + NVIDIA_VISIBLE_DEVICES: all # Expose all GPUs + GZ_VERSION: harmonic + devices: + - "/dev/dri:/dev/dri" + - /tmp/.X11-unix:/tmp/.X11-unix + volumes: + - tmp:/tmp # shared tmp directory - volumes: - - ./entrypoint.sh:/usr/local/bin/ros_entrypoint.sh - +services: + world: + <<: *simulation + command: ros2 launch robotnik_gazebo_ignition spawn_world.launch.py + spawn: + <<: *simulation + command: ros2 launch robotnik_gazebo_ignition spawn_robot.launch.py robot_id:=robot_a robot:=rbwatcher +volumes: + tmp: diff --git a/entrypoint.sh b/entrypoint.sh deleted file mode 100755 index 0ba0116..0000000 --- a/entrypoint.sh +++ /dev/null @@ -1,240 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2024, Robotnik Automation S.L. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Robotnik Automation S.L. nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL Robotnik Automation S.L. BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Entrypoint script, loads other scripts and executes the command - -set -e - -function entrypoint_log() { - if [ -z "${ROS_ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "$@" - fi -} - -function source_ros_entrypoint_dir() { - if find /ros_entrypoint.d/ -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - entrypoint_log "$0: /ros_entrypoint.d/ is not empty, will attempt to execute scripts" - find "/ros_entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.sh) - if [ -x "$f" ]; then - entrypoint_log "$0: running $f" - "$f" - else - entrypoint_log "$0: ignoring $f, not executable" - fi - ;; - *) entrypoint_log "$0: ignoring $f" ;; - esac - done - entrypoint_log "$0: /ros_entrypoint.d/ has been processed successfully" - else - entrypoint_log "$0: No files found /ros_entrypoint.d/, skipping" - fi -} - -function use_generic() { - exec_cmd="${*}" - if [[ "${exec_cmd}" == "__default_cmd__" ]]; then - exec_cmd="${GEN_COMMAND}" - fi - return 0 -} - -function use_rosmon() { - if [[ ${ROS_VERSION} == "2" ]]; then - entrypoint_log "$0: ros mon is not supported on ros2" - return 1 - fi - rosmon_name="${ROBOT_ID}_rosmon_${ROS_BU_DESC}" - exec_cmd="rosrun rosmon_core rosmon" - exec_cmd="${exec_cmd} --flush-stdout" - exec_cmd="${exec_cmd} --disable-ui" - exec_cmd="${exec_cmd} --name=${rosmon_name}" - exec_cmd="${exec_cmd} ${ROS_BU_PKG}" - exec_cmd="${exec_cmd} ${ROS_BU_LAUNCH}" - return 0 -} - -function use_ros_run() { - if [[ ${ROS_VERSION} == "1" ]]; then - exec_cmd="rosrun" - fi - if [[ ${ROS_VERSION} == "2" ]]; then - exec_cmd="ros2 run" - fi - exec_cmd="${exec_cmd} ${ROS_BU_PKG}" - exec_cmd="${exec_cmd} ${ROS_BU_LAUNCH}" - return 0 -} - -function use_ros_launch() { - if [[ ${ROS_VERSION} == "1" ]]; then - exec_cmd="roslaunch" - fi - if [[ ${ROS_VERSION} == "2" ]]; then - exec_cmd="ros2 launch" - fi - exec_cmd="${exec_cmd} ${ROS_BU_PKG}" - exec_cmd="${exec_cmd} ${ROS_BU_LAUNCH}" - return 0 -} - -function fake_screen_startup() { - if ! is_graphical; then - return 1 - fi - # if the graphical start is selected do nothing - if ! [[ "${GRAPHICAL_START}" == true ]]; then - return 0 - fi - export GUI_COMMAND="${exec_cmd}" - exec_cmd="/usr/local/bin/vnc_launcher.sh" -} - -function is_graphical() { - if ! [[ -r "/usr/local/bin/vnc_launcher.sh" ]]; then - entrypoint_log "$0: VNC base graphical execution is not allowed on this version" - return 1 - fi - GRAPHICAL_START="true" - return 0 -} - -function use_graphical() { - if ! is_graphical; then - return 1 - fi - exec_cmd="/usr/local/bin/vnc_launcher.sh" - return 0 -} - -function select_ros_launcher() { - local startup_func="use_generic" - if [[ "${*}" == "__default_cmd__" ]]; then - case "${STARTUP_TYPE}" in - generic) - startup_func="use_generic" - ;; - rosmon) - startup_func="use_rosmon" - ;; - launch) - startup_func="use_ros_launch" - ;; - run) - startup_func="use_ros_run" - ;; - graphical) - startup_func="use_graphical" - ;; - *) - entrypoint_log "$0: not valid" - return 1 - ;; - esac - else - entrypoint_log "$0: custom command detected, ignoring STARTUP_TYPE" - fi - if ! eval "${startup_func} ${@}"; then - return 1 - fi - if [[ ${FAKE_SCREEN} == "true" ]]; then - fake_screen_startup - return $? - fi - return 0 -} - -function check_nodes() { - # Check if enabled and nodes are set - if ! [[ ${CHECK_NODES} == "true" ]]; then - return 0 - fi - if [[ -z ${NODES_TO_CHECK} ]]; then - return 0 - fi - - # Wait for nodes to be available - entrypoint_log "$0: env variable CHECK_NODES is set to true, waiting for nodes to be available: \"${NODES_TO_CHECK}\"" - entrypoint_log "$0: ---" - i=0 - while true; do - i=$((i + 1)) - if eval "${HEALTHCHECK_EXEC} ${NODES_TO_CHECK} > /tmp/healthcheck.log"; then - return 0 - fi - if [[ $(( i%5 )) -eq 0 ]] - then - i=0 - cat /tmp/healthcheck.log - entrypoint_log "$0: ---" - fi - sleep 0.25 - done - entrypoint_log "$0: error: at least one of follwing nodes is not available: \"${NODES_TO_CHECK}\"" - return 1 -} - -function _trap_handler() { - entrypoint_log "$0: caught signal \"$1\" before starting main process, exiting" - exit 0 -} - -function main() { - # Trap SIGTERM and SIGINT to stop the container gracefully - # it only works before the exec command - trap '_trap_handler SIGTERM' SIGTERM - trap '_trap_handler SIGINT' SIGINT - - # Source all scripts in /ros_entrypoint.d/ - source_ros_entrypoint_dir - - # Set up ROS environment - if ! source env_loader.sh - then - entrypoint_log "$0: error loading ROS environment, check logs" - fi - - # Fill exec_cmd - if ! select_ros_launcher "${@}" - then - return 1 - fi - - # substitute the environment variables - exec_cmd=$(eval echo "${exec_cmd}") - entrypoint_log "$0: executing ${exec_cmd}" - if ! check_nodes - then - return 1 - fi - entrypoint_log "$0: all nodes are available, executing ${exec_cmd}" - exec /usr/bin/tini -- ${exec_cmd} -} - -main "${@}" diff --git a/robotnik_simulation.humble.repos b/robotnik_simulation.humble.repos index 155e803..5766169 100644 --- a/robotnik_simulation.humble.repos +++ b/robotnik_simulation.humble.repos @@ -29,4 +29,4 @@ repositories: robotnik/robotnik_simulation: type: git url: https://github.com/RobotnikAutomation/robotnik_simulation.git - version: humble-devel + version: jazzy-devel