diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9847eb2f..627c951b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,5 @@ # More info: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners -* @chapulina +* @adityapande-1995 +* @ahcorde diff --git a/.github/workflows/build-and-test.sh b/.github/workflows/build-and-test.sh index 86b2fd8b..8909db55 100755 --- a/.github/workflows/build-and-test.sh +++ b/.github/workflows/build-and-test.sh @@ -10,31 +10,15 @@ export ROS_PYTHON_VERSION=3 apt update -qq apt install -qq -y lsb-release wget curl build-essential -if [ "$GZ_VERSION" == "garden" ]; then - echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list - wget https://packages.osrfoundation.org/gazebo.key -O - | apt-key add - - - GZ_DEPS="libgz-sim7-dev" - - ROSDEP_ARGS="--skip-keys='sdformat-urdf'" -elif [ "$GZ_VERSION" == "harmonic" ]; then - echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list - wget https://packages.osrfoundation.org/gazebo.key -O - | apt-key add - - - GZ_DEPS="libgz-sim8-dev" - - ROSDEP_ARGS="--skip-keys='sdformat-urdf'" -fi - -# Fortress comes through rosdep for Focal and Jammy +echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list +wget https://packages.osrfoundation.org/gazebo.key -O - | apt-key add - # Dependencies. echo "deb http://packages.ros.org/ros2-testing/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-testing.list curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - apt-get update -qq -apt-get install -y $GZ_DEPS \ - python3-colcon-common-extensions \ - python3-rosdep +apt-get install -y python3-colcon-common-extensions \ + python3-rosdep rosdep init rosdep update diff --git a/.github/workflows/ros2-ci.yml b/.github/workflows/ros2-ci.yml index fb806edb..bf1cbd4e 100644 --- a/.github/workflows/ros2-ci.yml +++ b/.github/workflows/ros2-ci.yml @@ -10,38 +10,17 @@ jobs: fail-fast: false matrix: include: - - docker-image: "ubuntu:22.04" - gz-version: "fortress" - ros-distro: "humble" - - docker-image: "ubuntu:22.04" - gz-version: "garden" - ros-distro: "humble" - - docker-image: "ubuntu:22.04" - gz-version: "harmonic" - ros-distro: "humble" - - docker-image: "ubuntu:22.04" - gz-version: "fortress" - ros-distro: "rolling" - - docker-image: "ubuntu:22.04" - gz-version: "garden" - ros-distro: "rolling" - - docker-image: "ubuntu:22.04" + - docker-image: "ubuntu:24.04" gz-version: "harmonic" ros-distro: "rolling" container: image: ${{ matrix.docker-image }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Build and Test run: .github/workflows/build-and-test.sh env: DOCKER_IMAGE: ${{ matrix.docker-image }} GZ_VERSION: ${{ matrix.gz-version }} ROS_DISTRO: ${{ matrix.ros-distro }} - - name: Build sdformat_urdf from source - uses: actions/checkout@v2 - if: ${{ matrix.gz-version }} == "garden" - with: - repository: ros/sdformat_urdf - ref: ros2 diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 736670e0..2c94852d 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -10,10 +10,8 @@ jobs: runs-on: ubuntu-latest steps: - name: Add ticket to inbox - uses: technote-space/create-project-card-action@v1 + uses: actions/add-to-project@v0.5.0 with: - PROJECT: Core development - COLUMN: Inbox - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} - CHECK_ORG_PROJECT: true + project-url: https://github.com/orgs/gazebosim/projects/7 + github-token: ${{ secrets.TRIAGE_TOKEN }} diff --git a/README.md b/README.md index 53755a5d..1445dacf 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,21 @@ Galactic | Edifice | [galactic](https://github.com/gazebosim/ros_gz/tree/galacti Galactic | Fortress | [galactic](https://github.com/gazebosim/ros_gz/tree/galactic) | only from source Humble | Fortress | [humble](https://github.com/gazebosim/ros_gz/tree/humble) | https://packages.ros.org Humble | Garden | [humble](https://github.com/gazebosim/ros_gz/tree/humble) | [gazebo packages](https://gazebosim.org/docs/latest/ros_installation#gazebo-garden-with-ros-2-humble-iron-or-rolling-use-with-caution-)[^1] -Humble | Harmonic | [humble](https://github.com/gazebosim/ros_gz/tree/humble) | only from source -Rolling | Edifice | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | only from source -Rolling | Fortress | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | https://packages.ros.org +Humble | Harmonic | [humble](https://github.com/gazebosim/ros_gz/tree/humble) | [gazebo packages](https://gazebosim.org/docs/harmonic/ros_installation#-gazebo-harmonic-with-ros-2-humble-iron-or-rolling-use-with-caution-)[^1] +Iron | Fortress | [humble](https://github.com/gazebosim/ros_gz/tree/iron) | https://packages.ros.org +Iron | Garden | [humble](https://github.com/gazebosim/ros_gz/tree/iron) | only from source +Iron | Harmonic | [humble](https://github.com/gazebosim/ros_gz/tree/iron) | only from source +Jazzy* | Garden | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | only from source +Jazzy* | Harmonic | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | https://packages.ros.org +Rolling | Fortress | [humble](https://github.com/gazebosim/ros_gz/tree/humble) | https://packages.ros.org Rolling | Garden | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | only from source Rolling | Harmonic | [ros2](https://github.com/gazebosim/ros_gz/tree/ros2) | only from source [^1]: Binaries for these pairings are provided from a the packages.osrfoundation.org repository. Refer to https://gazebosim.org/docs/latest/ros_installation for installation instructions. -For information on ROS 2 and Gazebo compatibility, refer to the [melodic branch README](https://github.com/gazebosim/ros_gz/tree/melodic) +* ROS 2 Jazzy Jalisco is slated for release on May 23rd, 2024. [Full ROS 2 release information is available in REP-2000.] + +For information on ROS(1) and Gazebo compatibility, refer to the [noetic branch README](https://github.com/gazebosim/ros_gz/tree/noetic) > Please [ticket an issue](https://github.com/gazebosim/ros_gz/issues/) if you'd like support to be added for some combination. @@ -55,11 +61,11 @@ This repository holds packages that provide integration between ## Install -This branch supports ROS Humble. See above for other ROS versions. +This branch supports ROS Rolling. See above for other ROS versions. ### Binaries -Humble binaries are available for Fortress. +Rolling binaries are available for Fortress. They are hosted at https://packages.ros.org. 1. Add https://packages.ros.org @@ -70,14 +76,14 @@ They are hosted at https://packages.ros.org. 1. Install `ros_gz` - sudo apt install ros-humble-ros-gz + sudo apt install ros-rolling-ros-gz ### From source #### ROS Be sure you've installed -[ROS Humble](https://docs.ros.org/en/humble/Installation.html) +[ROS Rolling](https://index.ros.org/doc/ros2/Installation/) (at least ROS-Base). More ROS dependencies will be installed below. #### Gazebo @@ -103,7 +109,7 @@ The following steps are for Linux and OSX. cd ~/ws/src # Download needed software - git clone https://github.com/gazebosim/ros_gz.git -b humble + git clone https://github.com/gazebosim/ros_gz.git -b ros2 ``` 1. Install dependencies (this may also install Gazebo): @@ -130,22 +136,6 @@ The following steps are for Linux and OSX. > try building with `colcon build --parallel-workers=1 --executor sequential`. You might also have to set `export MAKEFLAGS="-j 1"` before running `colcon build` to limit > the number of processors used to build a single package. - If `colcon build` fails with [this issue](https://github.com/gazebosim/ros_gz/issues/401) - - ``` - CMake Error at CMakeLists.txt:81 (find_package): - By not providing "Findactuator_msgs.cmake" in CMAKE_MODULE_PATH this - project has asked CMake to find a package configuration file provided by - "actuator_msgs", but CMake did not find one. - ``` - - ```bash - cd src - git clone git@github.com:rudislabs/actuator_msgs.git - cd ../ - colcon build - ``` - ## ROSCon 2022 [![](img/video_img.png)](https://vimeo.com/showcase/9954564/video/767127300) diff --git a/README_RENAME.md b/README_RENAME.md index 17007f4e..92ba754f 100644 --- a/README_RENAME.md +++ b/README_RENAME.md @@ -7,7 +7,7 @@ This allows users to do either of these and get equivalent behavior: ```bash ros2 run ros_gz parameter_bridge [...] -ros2 run ros_ign parameter_bridge [...] # Will emit deprecation warning +ros2 run ros_gz parameter_bridge [...] # Will emit deprecation warning ``` Additionally, installed files like launch files, message interfaces etc. are **duplicated** versions of the ones in `ros_gz` (but renamed as appropriate), and point to `ros_gz` dependencies as well (e.g. launch files pointing to `ros_gz` nodes.) diff --git a/img/video_img.png b/img/video_img.png new file mode 100644 index 00000000..626c7353 Binary files /dev/null and b/img/video_img.png differ diff --git a/ros_gz/CHANGELOG.rst b/ros_gz/CHANGELOG.rst index 61e5fd4f..8dd8c6a6 100644 --- a/ros_gz/CHANGELOG.rst +++ b/ros_gz/CHANGELOG.rst @@ -2,11 +2,49 @@ Changelog for package ros_gz ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- +2.0.0 (2024-07-22) +------------------ -0.244.11 (2023-05-23) ---------------------- +1.0.1 (2024-07-03) +------------------ +* Prepare for 1.0.0 Release (`#495 `_) +* 0.244.14 +* Changelog +* 0.244.13 +* Changelog +* 0.244.12 +* Changelog +* 0.246.0 +* Update changelogs +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Jose Luis Rivero, Michael Carroll, ahcorde + +1.0.0 (2024-04-24) +------------------ + +0.246.0 (2023-08-31) +-------------------- +* Port: humble to ros2 (`#386 `_) +* Update maintainers (`#376 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Contributors: Aditya Pande, Alejandro Hernández Cordero, Michael Carroll, ahcorde + +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Contributors: Alejandro Hernández Cordero, ahcorde 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz/package.xml b/ros_gz/package.xml index 9981ecb4..865a20cf 100644 --- a/ros_gz/package.xml +++ b/ros_gz/package.xml @@ -4,11 +4,14 @@ ros_gz - 0.244.12 + 2.0.0 Meta-package containing interfaces for using ROS 2 with Gazebo simulation. - Louise Poubel + Aditya Pande + Alejandro Hernandez Apache 2.0 + Louise Poubel + ament_cmake ros_gz_bridge diff --git a/ros_gz_bridge/CHANGELOG.rst b/ros_gz_bridge/CHANGELOG.rst index 74b8603b..b28f5bcf 100644 --- a/ros_gz_bridge/CHANGELOG.rst +++ b/ros_gz_bridge/CHANGELOG.rst @@ -2,22 +2,202 @@ Changelog for package ros_gz_bridge ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- -* Backport: Add conversion for geometry_msgs/msg/TwistStamped <-> gz.msgs.Twist (`#468 `_) (`#470 `_) -* Add support for Harmonic/Humble pairing (`#462 `_) -* Added messages for 2D Bounding Boxes to ros_gz_bridge (`#458 `_) -* Fix double wait in ros_gz_bridge (`#347 `_) (`#450 `_) -* [backport humble] SensorNoise msg bridging (`#417 `_) -* [backport humble] Added Altimeter msg bridging (`#413 `_) (`#414 `_) (`#426 `_) -* [backport humble] Update README.md (`#411 `_) +2.0.0 (2024-07-22) +------------------ +* Making use_composition true by default (`#578 `_) +* Contributors: Addisu Z. Taddese + +1.0.1 (2024-07-03) +------------------ +* Add support for gz.msgs.EntityWrench (base branch: ros2) (`#573 `_) +* Merge pull request `#571 `_ from azeey/jazzy_to_ros2 + Merge jazzy ➡️ ros2 +* Merge branch 'ros2' into jazzy_to_ros2 +* Use memcpy instead of std::copy when bridging images (`#565 `_) + While testing ros <-> gz communication using the bridge I noticed that the bridge was talking quite a bit of time copying images from Gazebo to ROS. I found that the std::copy operation that we're doing is substantially slower than the memcpy alternative. I think that in principle this shouldn't happen but the numbers are quite clear. Perhaps std::copy is doing something that doesn't use cache effectively + --------- + Co-authored-by: Jose Luis Rivero +* Merge jazzy into ros2 +* Merge pull request `#569 `_ from azeey/iron_to_jazzy + Merge iron ➡️ jazzy +* Merge iron into jazzy +* Add option to change material color from ROS. (`#521 `_) + Forward port of `#486 `_. + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. + (cherry picked from commit 78dc4823121f085594e6028a93f1e571eb04f58b) +* Merge pull request `#564 `_ from azeey/humble_to_iron + Humble ➡️ Iron +* Merge humble -> iron +* Use `ignoreLocalMessages` in the bridge (`#559 `_) + * Ignore local messages +* Update launch files with name parameter (`#556 `_) + * Name is required. +* Ensure the same container is used for the bridge and gz_server (`#553 `_) + This also adds a required `name` parameter for the bridge so that + multiple different bridges can be created without name collision +* Launch ros_gz_bridge from xml (`#550 `_) + * Add gzserver with ability to load an SDF file or string +* Launch gzserver and the bridge as composable nodes (`#528 `_) + * Add gzserver with ability to load an SDF file or string +* Add option to change material color from ROS. (`#521 `_) + Forward port of `#486 `_. + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. +* populate imu covariances when converting (`#375 `_) (`#540 `_) + Co-authored-by: El Jawad Alaa +* Prepare for 1.0.0 Release (`#495 `_) +* Use gz_vendor packages (`#531 `_) +* [backport Humble] Create bridge for GPSFix msg (`#316 `_) (`#538 `_) + Co-authored-by: Rousseau Vincent +* [backport Iron] Create bridge for GPSFix msg (`#316 `_) (`#537 `_) + Co-authored-by: Rousseau Vincent +* 0.244.14 +* Changelog +* Added conversion for Detection3D and Detection3DArray (`#523 `_) (`#526 `_) + Co-authored-by: wittenator <9154515+wittenator@users.noreply.github.com> +* Added conversion for Detection3D and Detection3DArray (`#523 `_) (`#525 `_) + Co-authored-by: wittenator <9154515+wittenator@users.noreply.github.com> +* [Backport rolling] Add ROS namespaces to GZ topics (`#517 `_) + Co-authored-by: Krzysztof Wojciechowski <49921081+Kotochleb@users.noreply.github.com> +* ign to gz (`#519 `_) +* Add ROS namespaces to GZ topics (`#512 `_) + Co-authored-by: Alejandro Hernández Cordero +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) (`#506 `_) +* Add a virtual destructor to suppress compiler warning (`#502 `_) (`#505 `_) + Co-authored-by: Michael Carroll +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) +* Add a virtual destructor to suppress compiler warning (`#502 `_) +* Add option to change material color from ROS. (`#486 `_) + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. + --------- + Co-authored-by: Alejandro Hernández Cordero + Co-authored-by: Addisu Z. Taddese + Co-authored-by: Addisu Z. Taddese +* 0.244.13 +* Changelog +* backport pr 374 (`#489 `_) +* populate imu covariances when converting (`#488 `_) +* 0.244.12 +* Changelog +* Backport: Add conversion for geometry_msgs/msg/TwistStamped <-> gz.msgs.Twist (`#468 `_) (`#470 `_) +* Add conversion for geometry_msgs/msg/TwistStamped <-> gz.msgs.Twist (`#468 `_) +* Added messages for 2D Bounding Boxes to ros_gz_bridge (`#458 `_) (`#466 `_) + Co-authored-by: Alejandro Hernandez Cordero +* populate imu covariances when converting (`#375 `_) +* 0.246.0 +* Update changelogs +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* SensorNoise msg bridging (`#417 `_) +* Added Altimeter msg bridging (`#413 `_) +* Update README.md (`#411 `_) The ROS type for gz.msgs.NavSat messages should be **sensor_msgs/msg/NavSatFix** instead of **sensor_msgs/msg/NavSatFixed** -* Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero, Arjun K Haridas, wittenator +* Add missing rosidl_cmake dep to ros_gz_bridge (`#391 `_) + Co-authored-by: Chris Lalancette +* allow converting from/to TwistWithCovarianceStamped (`#374 `_) + * allow converting from/to TwistWithCovarianceStamped + -------- + Co-authored-by: Alejandro Hernández Cordero +* Added doc (`#393 `_) +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* allow converting from/to PoseWithCovarianceStamped (`#381 `_) + * allow converting from/to PoseWithCovarianceStamped +* Add actuator_msgs to bridge. (`#378 `_) +* Update maintainers (`#376 `_) +* Fix warning message (`#371 `_) +* Improve error messages around config loading (`#356 `_) +* Bringing the Joy to gazebo. (`#350 `_) + Enable using the gazebo bridge with Joy. +* Fix double wait in ros_gz_bridge (`#347 `_) +* Create bridge for GPSFix msg (`#316 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Remove Humble+ deprecations (`#312 `_) + * Remove Humble+ deprecations +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Arjun K Haridas, Benjamin Perseghetti, Carlos Agüero, El Jawad Alaa, Jose Luis Rivero, Krzysztof Wojciechowski, Michael Carroll, Rousseau Vincent, Victor T. Noppeney, Yadu, ahcorde, wittenator, ymd-stella -0.244.11 (2023-05-23) ---------------------- -* Add actuator_msgs to humble bridge. (`#394 `_) -* Contributors: Benjamin Perseghetti +1.0.0 (2024-04-24) +------------------ +* Use gz_vendor packages (`#531 `_) +* Added conversion for Detection3D and Detection3DArray (`#523 `_) (`#525 `_) + Co-authored-by: wittenator <9154515+wittenator@users.noreply.github.com> +* [Backport rolling] Add ROS namespaces to GZ topics (`#517 `_) + Co-authored-by: Krzysztof Wojciechowski <49921081+Kotochleb@users.noreply.github.com> +* ign to gz (`#519 `_) +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) +* Add a virtual destructor to suppress compiler warning (`#502 `_) +* Add conversion for geometry_msgs/msg/TwistStamped <-> gz.msgs.Twist (`#468 `_) +* Added messages for 2D Bounding Boxes to ros_gz_bridge (`#458 `_) (`#466 `_) + Co-authored-by: Alejandro Hernandez Cordero +* populate imu covariances when converting (`#375 `_) +* Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero, El Jawad Alaa, Michael Carroll + +0.246.0 (2023-08-31) +-------------------- +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* SensorNoise msg bridging (`#417 `_) +* Added Altimeter msg bridging (`#413 `_) +* Update README.md (`#411 `_) + The ROS type for gz.msgs.NavSat messages should be **sensor_msgs/msg/NavSatFix** instead of **sensor_msgs/msg/NavSatFixed** +* Add missing rosidl_cmake dep to ros_gz_bridge (`#391 `_) + Co-authored-by: Chris Lalancette +* allow converting from/to TwistWithCovarianceStamped (`#374 `_) + Co-authored-by: Alejandro Hernández Cordero +* Added doc (`#393 `_) +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* allow converting from/to PoseWithCovarianceStamped (`#381 `_) + * allow converting from/to PoseWithCovarianceStamped +* Add actuator_msgs to bridge. (`#378 `_) +* Update maintainers (`#376 `_) +* Fix warning message (`#371 `_) +* Improve error messages around config loading (`#356 `_) +* Bringing the Joy to gazebo. (`#350 `_) + Enable using the gazebo bridge with Joy. +* Fix double wait in ros_gz_bridge (`#347 `_) +* Create bridge for GPSFix msg (`#316 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Contributors: Aditya Pande, Alejandro Hernández Cordero, Arjun K Haridas, Benjamin Perseghetti, El Jawad Alaa, Michael Carroll, Rousseau Vincent, Yadu, ahcorde, ymd-stella + +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Remove Humble+ deprecations (`#312 `_) + * Remove Humble+ deprecations +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Alejandro Hernández Cordero, Michael Carroll, ahcorde 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz_bridge/CMakeLists.txt b/ros_gz_bridge/CMakeLists.txt index 9446f3b4..349b5c47 100644 --- a/ros_gz_bridge/CMakeLists.txt +++ b/ros_gz_bridge/CMakeLists.txt @@ -14,64 +14,25 @@ find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(rclcpp_components REQUIRED) find_package(yaml_cpp_vendor REQUIRED) +find_package(yaml-cpp REQUIRED) -# TODO(CH3): Deprecated. Remove on tock. -if("$ENV{GZ_VERSION}" STREQUAL "" AND NOT "$ENV{IGNITION_VERSION}" STREQUAL "") - message(DEPRECATION "Environment variable [IGNITION_VERSION] is deprecated. Use [GZ_VERSION] instead.") - set(ENV{GZ_VERSION} $ENV{IGNITION_VERSION}) -endif() +find_package(gz_transport_vendor REQUIRED) +find_package(gz-transport REQUIRED) -# Edifice -if("$ENV{GZ_VERSION}" STREQUAL "edifice") - find_package(ignition-transport10 REQUIRED) - find_package(ignition-msgs7 REQUIRED) - - set(GZ_TARGET_PREFIX ignition) - set(GZ_MSGS_VER ${ignition-msgs7_VERSION_MAJOR}) - set(GZ_TRANSPORT_VER ${ignition-transport10_VERSION_MAJOR}) - - message(STATUS "Compiling against Ignition Edifice") -# Garden -elseif("$ENV{GZ_VERSION}" STREQUAL "garden") - find_package(gz-transport12 REQUIRED) - find_package(gz-msgs9 REQUIRED) - - set(GZ_TARGET_PREFIX gz) - set(GZ_MSGS_VER ${gz-msgs9_VERSION_MAJOR}) - set(GZ_TRANSPORT_VER ${gz-transport12_VERSION_MAJOR}) - - message(STATUS "Compiling against Gazebo Garden") -elseif("$ENV{GZ_VERSION}" STREQUAL "harmonic") - find_package(gz-transport13 REQUIRED) - find_package(gz-msgs10 REQUIRED) - - set(GZ_TARGET_PREFIX gz) - set(GZ_MSGS_VER ${gz-msgs10_VERSION_MAJOR}) - set(GZ_TRANSPORT_VER ${gz-transport13_VERSION_MAJOR}) - - message(STATUS "Compiling against Gazebo Harmonic") -# Default to Fortress -else() - find_package(ignition-transport11 REQUIRED) - find_package(ignition-msgs8 REQUIRED) - - set(GZ_TARGET_PREFIX ignition) - set(GZ_MSGS_VER ${ignition-msgs8_VERSION_MAJOR}) - set(GZ_TRANSPORT_VER ${ignition-transport11_VERSION_MAJOR}) - - message(STATUS "Compiling against Ignition Fortress") -endif() +find_package(gz_msgs_vendor REQUIRED) +find_package(gz-msgs REQUIRED) -set(GZ_MSGS_VERSION_MAJOR ${${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}_VERSION_MAJOR}) -set(GZ_MSGS_VERSION_MINOR ${${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}_VERSION_MINOR}) -set(GZ_MSGS_VERSION_PATCH ${${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}_VERSION_PATCH}) -set(GZ_MSGS_VERSION_FULL ${GZ_MSGS_VERSION_MAJOR}.${GZ_MSGS_VERSION_MINOR}.${GZ_MSGS_VERSION_PATCH}) +# Install the python module for this package +ament_python_install_package(${PROJECT_NAME}) + +set(GZ_MSGS_VERSION_FULL ${gz-msgs_VERSION}) set(BRIDGE_MESSAGE_TYPES builtin_interfaces actuator_msgs camera_track_msgs geometry_msgs + gps_msgs nav_msgs rcl_interfaces ros_gz_interfaces @@ -120,7 +81,7 @@ add_custom_command( COMMENT "Generating factories for interface types") set(bridge_lib - ros_gz_bridge_lib + ros_gz_bridge ) add_library(${bridge_lib} @@ -130,6 +91,7 @@ add_library(${bridge_lib} src/bridge_handle_ros_to_gz.cpp src/bridge_handle_gz_to_ros.cpp src/factory_interface.cpp + src/service_factory_interface.cpp src/service_factories/ros_gz_interfaces.cpp src/ros_gz_bridge.cpp ${convert_files} @@ -137,25 +99,27 @@ add_library(${bridge_lib} ) target_link_libraries(${bridge_lib} - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + PUBLIC + gz-msgs::core + gz-transport::core + PRIVATE + yaml-cpp::yaml-cpp ) ament_target_dependencies(${bridge_lib} - rclcpp - rclcpp_components - yaml_cpp_vendor - ${BRIDGE_MESSAGE_TYPES} + PUBLIC + rclcpp + rclcpp_components + ${BRIDGE_MESSAGE_TYPES} ) target_include_directories(${bridge_lib} - PUBLIC include - PRIVATE src ${generated_path} -) - -target_link_libraries(${bridge_lib} - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + PUBLIC + "$" + "$" + PRIVATE + "$" + "$" ) rclcpp_components_register_node( @@ -163,18 +127,20 @@ rclcpp_components_register_node( PLUGIN ros_gz_bridge::RosGzBridge EXECUTABLE bridge_node) -install(TARGETS ${bridge_lib} +install(TARGETS ${bridge_lib} EXPORT export_${PROJECT_NAME} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin) install( DIRECTORY include/ - DESTINATION include + DESTINATION include/${PROJECT_NAME} ) -ament_export_include_directories(include) -ament_export_libraries(${bridge_lib}) +install( + DIRECTORY launch/ + DESTINATION share/${PROJECT_NAME}/launch +) set(bridge_executables parameter_bridge @@ -194,7 +160,7 @@ foreach(bridge ${bridge_executables}) ${BRIDGE_MESSAGE_TYPES} ) install(TARGETS ${bridge} - DESTINATION lib/${PROJECT_NAME} + RUNTIME DESTINATION lib/${PROJECT_NAME} ) endforeach() @@ -211,7 +177,7 @@ if(BUILD_TESTING) ${PROJECT_SOURCE_DIR}/src/convert/rcl_interfaces_TEST.cpp ) target_link_libraries(test_rcl_interfaces - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core + gz-msgs::core ${rcl_interfaces_TARGETS} gtest gtest_main @@ -246,8 +212,8 @@ if(BUILD_TESTING) ) target_link_libraries(test_utils ${GTEST_LIBRARIES} - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + gz-msgs::core + gz-transport::core ) ament_target_dependencies(test_utils rclcpp @@ -349,9 +315,20 @@ if(BUILD_TESTING) endif() -ament_export_dependencies( - rclcpp - ${BRIDGE_MESSAGE_TYPES} -) +# Export old-style CMake variables +ament_export_include_directories("include/${PROJECT_NAME}") +ament_export_libraries(${bridge_lib}) + +# Export modern CMake targets +ament_export_targets(export_${PROJECT_NAME}) + +# specific order: dependents before dependencies +ament_export_dependencies(rclcpp) +ament_export_dependencies(rclcpp_components) +ament_export_dependencies(gz_msgs_vendor) +ament_export_dependencies(gz-msgs) +ament_export_dependencies(gz_transport_vendor) +ament_export_dependencies(gz-transport) +ament_export_dependencies(${BRIDGE_MESSAGE_TYPES}) ament_package() diff --git a/ros_gz_bridge/README.md b/ros_gz_bridge/README.md index e9a062ce..57289234 100644 --- a/ros_gz_bridge/README.md +++ b/ros_gz_bridge/README.md @@ -5,72 +5,91 @@ between ROS and Gazebo Transport. The following message types can be bridged for topics: -| ROS type | Gazebo type | -|--------------------------------------|:--------------------------------------:| -| builtin_interfaces/msg/Time | ignition::msgs::Time | -| std_msgs/msg/Bool | ignition::msgs::Boolean | -| std_msgs/msg/ColorRGBA | ignition::msgs::Color | -| std_msgs/msg/Empty | ignition::msgs::Empty | -| std_msgs/msg/Float32 | ignition::msgs::Float | -| std_msgs/msg/Float64 | ignition::msgs::Double | -| std_msgs/msg/Header | ignition::msgs::Header | -| std_msgs/msg/Int32 | ignition::msgs::Int32 | -| std_msgs/msg/UInt32 | ignition::msgs::UInt32 | -| std_msgs/msg/String | ignition::msgs::StringMsg | -| geometry_msgs/msg/Wrench | ignition::msgs::Wrench | -| geometry_msgs/msg/WrenchStamped | ignition::msgs::Wrench | -| geometry_msgs/msg/Quaternion | ignition::msgs::Quaternion | -| geometry_msgs/msg/Vector3 | ignition::msgs::Vector3d | -| geometry_msgs/msg/Point | ignition::msgs::Vector3d | -| geometry_msgs/msg/Pose | ignition::msgs::Pose | -| geometry_msgs/msg/PoseArray | ignition::msgs::Pose_V | -| geometry_msgs/msg/PoseWithCovariance | ignition::msgs::PoseWithCovariance | -| geometry_msgs/msg/PoseStamped | ignition::msgs::Pose | -| geometry_msgs/msg/Transform | ignition::msgs::Pose | -| geometry_msgs/msg/TransformStamped | ignition::msgs::Pose | -| geometry_msgs/msg/Twist | ignition::msgs::Twist | -| geometry_msgs/msg/TwistStamped | ignition::msgs::Twist | -| geometry_msgs/msg/TwistWithCovariance| ignition::msgs::TwistWithCovariance | -| nav_msgs/msg/Odometry | ignition::msgs::Odometry | -| nav_msgs/msg/Odometry | ignition::msgs::OdometryWithCovariance | -| rcl_interfaces/msg/ParameterValue | ignition::msgs::Any | -| ros_gz_interfaces/msg/Altimeter | ignition::msgs::Altimeter | -| ros_gz_interfaces/msg/Contact | ignition::msgs::Contact | -| ros_gz_interfaces/msg/Contacts | ignition::msgs::Contacts | -| ros_gz_interfaces/msg/Dataframe | ignition::msgs::Dataframe | -| ros_gz_interfaces/msg/Entity | ignition::msgs::Entity | -| ros_gz_interfaces/msg/Float32Array | ignition::msgs::Float_V | -| ros_gz_interfaces/msg/GuiCamera | ignition::msgs::GUICamera | -| ros_gz_interfaces/msg/JointWrench | ignition::msgs::JointWrench | -| ros_gz_interfaces/msg/Light | ignition::msgs::Light | -| ros_gz_interfaces/msg/SensorNoise | ignition::msgs::SensorNoise | -| ros_gz_interfaces/msg/StringVec | ignition::msgs::StringMsg_V | -| ros_gz_interfaces/msg/TrackVisual | ignition::msgs::TrackVisual | -| ros_gz_interfaces/msg/VideoRecord | ignition::msgs::VideoRecord | -| ros_gz_interfaces/msg/WorldControl | ignition::msgs::WorldControl | -| rosgraph_msgs/msg/Clock | ignition::msgs::Clock | -| sensor_msgs/msg/BatteryState | ignition::msgs::BatteryState | -| sensor_msgs/msg/CameraInfo | ignition::msgs::CameraInfo | -| sensor_msgs/msg/FluidPressure | ignition::msgs::FluidPressure | -| sensor_msgs/msg/Imu | ignition::msgs::IMU | -| sensor_msgs/msg/Image | ignition::msgs::Image | -| sensor_msgs/msg/JointState | ignition::msgs::Model | -| sensor_msgs/msg/Joy | ignition::msgs::Joy | -| sensor_msgs/msg/LaserScan | ignition::msgs::LaserScan | -| sensor_msgs/msg/MagneticField | ignition::msgs::Magnetometer | -| sensor_msgs/msg/NavSatFix | ignition::msgs::NavSat | -| sensor_msgs/msg/PointCloud2 | ignition::msgs::PointCloudPacked | -| tf2_msgs/msg/TFMessage | ignition::msgs::Pose_V | -| trajectory_msgs/msg/JointTrajectory | ignition::msgs::JointTrajectory | +| ROS type | Gazebo Transport Type | +| ---------------------------------------------- | :------------------------------: | +| actuator_msgs/msg/Actuators | gz.msgs.Actuators | +| builtin_interfaces/msg/Time | gz.msgs.Time | +| geometry_msgs/msg/Point | gz.msgs.Vector3d | +| geometry_msgs/msg/Pose | gz.msgs.Pose | +| geometry_msgs/msg/PoseArray | gz.msgs.Pose_V | +| geometry_msgs/msg/PoseStamped | gz.msgs.Pose | +| geometry_msgs/msg/PoseWithCovariance | gz.msgs.PoseWithCovariance | +| geometry_msgs/msg/PoseWithCovarianceStamped | gz.msgs.PoseWithCovariance | +| geometry_msgs/msg/Quaternion | gz.msgs.Quaternion | +| geometry_msgs/msg/Transform | gz.msgs.Pose | +| geometry_msgs/msg/TransformStamped | gz.msgs.Pose | +| geometry_msgs/msg/Twist | gz.msgs.Twist | +| geometry_msgs/msg/TwistStamped | gz.msgs.Twist | +| geometry_msgs/msg/TwistWithCovariance | gz.msgs.TwistWithCovariance | +| geometry_msgs/msg/TwistWithCovarianceStamped | gz.msgs.TwistWithCovariance | +| geometry_msgs/msg/Vector3 | gz.msgs.Vector3d | +| geometry_msgs/msg/Wrench | gz.msgs.Wrench | +| geometry_msgs/msg/WrenchStamped | gz.msgs.Wrench | +| gps_msgs/msg/GPSFix | gz.msgs.NavSat | +| nav_msgs/msg/Odometry | gz.msgs.Odometry | +| nav_msgs/msg/Odometry | gz.msgs.OdometryWithCovariance | +| rcl_interfaces/msg/ParameterValue | gz.msgs.Any | +| ros_gz_interfaces/msg/Altimeter | gz.msgs.Altimeter | +| ros_gz_interfaces/msg/Contact | gz.msgs.Contact | +| ros_gz_interfaces/msg/Contacts | gz.msgs.Contacts | +| ros_gz_interfaces/msg/Dataframe | gz.msgs.Dataframe | +| ros_gz_interfaces/msg/Entity | gz.msgs.Entity | +| ros_gz_interfaces/msg/EntityWrench | gz.msgs.EntityWrench | +| ros_gz_interfaces/msg/Float32Array | gz.msgs.Float_V | +| ros_gz_interfaces/msg/GuiCamera | gz.msgs.GUICamera | +| ros_gz_interfaces/msg/JointWrench | gz.msgs.JointWrench | +| ros_gz_interfaces/msg/Light | gz.msgs.Light | +| ros_gz_interfaces/msg/ParamVec | gz.msgs.Param | +| ros_gz_interfaces/msg/ParamVec | gz.msgs.Param_V | +| ros_gz_interfaces/msg/SensorNoise | gz.msgs.SensorNoise | +| ros_gz_interfaces/msg/StringVec | gz.msgs.StringMsg_V | +| ros_gz_interfaces/msg/TrackVisual | gz.msgs.TrackVisual | +| ros_gz_interfaces/msg/VideoRecord | gz.msgs.VideoRecord | +| rosgraph_msgs/msg/Clock | gz.msgs.Clock | +| sensor_msgs/msg/BatteryState | gz.msgs.BatteryState | +| sensor_msgs/msg/CameraInfo | gz.msgs.CameraInfo | +| sensor_msgs/msg/FluidPressure | gz.msgs.FluidPressure | +| sensor_msgs/msg/Image | gz.msgs.Image | +| sensor_msgs/msg/Imu | gz.msgs.IMU | +| sensor_msgs/msg/JointState | gz.msgs.Model | +| sensor_msgs/msg/Joy | gz.msgs.Joy | +| sensor_msgs/msg/LaserScan | gz.msgs.LaserScan | +| sensor_msgs/msg/MagneticField | gz.msgs.Magnetometer | +| sensor_msgs/msg/NavSatFix | gz.msgs.NavSat | +| sensor_msgs/msg/PointCloud2 | gz.msgs.PointCloudPacked | +| std_msgs/msg/Bool | gz.msgs.Boolean | +| std_msgs/msg/ColorRGBA | gz.msgs.Color | +| std_msgs/msg/Empty | gz.msgs.Empty | +| std_msgs/msg/Float32 | gz.msgs.Float | +| std_msgs/msg/Float64 | gz.msgs.Double | +| std_msgs/msg/Header | gz.msgs.Header | +| std_msgs/msg/Int32 | gz.msgs.Int32 | +| std_msgs/msg/String | gz.msgs.StringMsg | +| std_msgs/msg/UInt32 | gz.msgs.UInt32 | +| tf2_msgs/msg/TFMessage | gz.msgs.Pose_V | +| trajectory_msgs/msg/JointTrajectory | gz.msgs.JointTrajectory | +| vision_msgs/msg/Detection2D | gz.msgs.AnnotatedAxisAligned2DBox | +| vision_msgs/msg/Detection2DArray | gz.msgs.AnnotatedAxisAligned2DBox_V | +| vision_msgs/msg/Detection3D | gz::msgs::AnnotatedOriented3DBox | +| vision_msgs/msg/Detection3DArray | gz::msgs::AnnotatedOriented3DBox_V | And the following for services: | ROS type | Gazebo request | Gazebo response | |--------------------------------------|:--------------------------:| --------------------- | -| ros_gz_interfaces/srv/ControlWorld | ignition.msgs.WorldControl | ignition.msgs.Boolean | +| ros_gz_interfaces/srv/ControlWorld | gz.msgs.WorldControl | gz.msgs.Boolean | Run `ros2 run ros_gz_bridge parameter_bridge -h` for instructions. +**NOTE**: If during startup, gazebo detects that there is another publisher on `/clock`, it will only create the fully qualified `/world//clock topic`. +Gazebo would be the only `/clock` publisher, the sole source of clock information. + +You should create an unidirectional `/clock` bridge: + +```bash +ros2 run ros_gz_bridge parameter_bridge /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock +``` + ## Example 1a: Gazebo Transport talker and ROS 2 listener Start the parameter bridge which will watch the specified topics. @@ -78,14 +97,14 @@ Start the parameter bridge which will watch the specified topics. ``` # Shell A: . ~/bridge_ws/install/setup.bash -ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@ignition.msgs.StringMsg +ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@gz.msgs.StringMsg ``` Now we start the ROS listener. ``` # Shell B: -. /opt/ros/galactic/setup.bash +. /opt/ros/rolling/setup.bash ros2 topic echo /chatter ``` @@ -93,7 +112,7 @@ Now we start the Gazebo Transport talker. ``` # Shell C: -ign topic -t /chatter -m ignition.msgs.StringMsg -p 'data:"Hello"' +gz topic -t /chatter -m gz.msgs.StringMsg -p 'data:"Hello"' ``` ## Example 1b: ROS 2 talker and Gazebo Transport listener @@ -103,21 +122,21 @@ Start the parameter bridge which will watch the specified topics. ``` # Shell A: . ~/bridge_ws/install/setup.bash -ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@ignition.msgs.StringMsg +ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@gz.msgs.StringMsg ``` Now we start the Gazebo Transport listener. ``` # Shell B: -ign topic -e -t /chatter +gz topic -e -t /chatter ``` Now we start the ROS talker. ``` # Shell C: -. /opt/ros/galactic/setup.bash +. /opt/ros/rolling/setup.bash ros2 topic pub /chatter std_msgs/msg/String "data: 'Hi'" --once ``` @@ -131,14 +150,14 @@ First we start Gazebo Sim (don't forget to hit play, or Gazebo Sim won't generat ``` # Shell A: -ign gazebo sensors_demo.sdf +gz sim sensors_demo.sdf ``` Let's see the topic where camera images are published. ``` # Shell B: -ign topic -l | grep image +gz topic -l | grep image /rgbd_camera/depth_image /rgbd_camera/image ``` @@ -148,14 +167,14 @@ Then we start the parameter bridge with the previous topic. ``` # Shell B: . ~/bridge_ws/install/setup.bash -ros2 run ros_gz_bridge parameter_bridge /rgbd_camera/image@sensor_msgs/msg/Image@ignition.msgs.Image +ros2 run ros_gz_bridge parameter_bridge /rgbd_camera/image@sensor_msgs/msg/Image@gz.msgs.Image ``` Now we start the ROS GUI: ``` # Shell C: -. /opt/ros/galactic/setup.bash +. /opt/ros/rolling/setup.bash ros2 run rqt_image_view rqt_image_view /rgbd_camera/image ``` @@ -189,15 +208,15 @@ On terminal B, we start a ROS 2 listener: And terminal C, publish an Gazebo message: -`ign topic -t /chatter -m ignition.msgs.StringMsg -p 'data:"Hello"'` +`gz topic -t /chatter -m gz.msgs.StringMsg -p 'data:"Hello"'` At this point, you should see the ROS 2 listener echoing the message. Now let's try the other way around, ROS 2 -> Gazebo. -On terminal D, start an Igntion listener: +On terminal D, start an Gazebo listener: -`ign topic -e -t /chatter` +`gz topic -e -t /chatter` And on terminal E, publish a ROS 2 message: @@ -215,7 +234,7 @@ On terminal A, start the service bridge: On terminal B, start Gazebo, it will be paused by default: -`ign gazebo shapes.sdf` +`gz sim shapes.sdf` On terminal C, make a ROS request to unpause simulation: @@ -237,35 +256,35 @@ bridge may be specified: # Set just topic name, applies to both - topic_name: "chatter" ros_type_name: "std_msgs/msg/String" - gz_type_name: "ignition.msgs.StringMsg" + gz_type_name: "gz.msgs.StringMsg" # Set just ROS topic name, applies to both - ros_topic_name: "chatter_ros" ros_type_name: "std_msgs/msg/String" - gz_type_name: "ignition.msgs.StringMsg" + gz_type_name: "gz.msgs.StringMsg" # Set just GZ topic name, applies to both -- gz_topic_name: "chatter_ign" +- gz_topic_name: "chatter_gz" ros_type_name: "std_msgs/msg/String" - gz_type_name: "ignition.msgs.StringMsg" + gz_type_name: "gz.msgs.StringMsg" # Set each topic name explicitly - ros_topic_name: "chatter_both_ros" - gz_topic_name: "chatter_both_ign" + gz_topic_name: "chatter_both_gz" ros_type_name: "std_msgs/msg/String" - gz_type_name: "ignition.msgs.StringMsg" + gz_type_name: "gz.msgs.StringMsg" # Full set of configurations - ros_topic_name: "ros_chatter" - gz_topic_name: "ign_chatter" + gz_topic_name: "gz_chatter" ros_type_name: "std_msgs/msg/String" - gz_type_name: "ignition.msgs.StringMsg" + gz_type_name: "gz.msgs.StringMsg" subscriber_queue: 5 # Default 10 publisher_queue: 6 # Default 10 lazy: true # Default "false" direction: BIDIRECTIONAL # Default "BIDIRECTIONAL" - Bridge both directions - # "GZ_TO_ROS" - Bridge Ignition topic to ROS - # "ROS_TO_GZ" - Bridge ROS topic to Ignition + # "GZ_TO_ROS" - Bridge Gz topic to ROS + # "ROS_TO_GZ" - Bridge ROS topic to Gz ``` To run the bridge node with the above configuration: @@ -273,9 +292,43 @@ To run the bridge node with the above configuration: ros2 run ros_gz_bridge parameter_bridge --ros-args -p config_file:=$WORKSPACE/ros_gz/ros_gz_bridge/test/config/full.yaml ``` +## Example 6: Using ROS namespace with the Bridge + +When spawning multiple robots inside the same ROS environment, it is convenient to use namespaces to avoid overlapping topic names. +There are three main types of namespaces: relative, global (`/`) and private (`~/`). For more information, refer to ROS documentation. +Namespaces are applied to Gazebo topic both when specified as `topic_name` as well as `gz_topic_name`. + +By default, the Bridge will not apply ROS namespace on the Gazebo topics. To enable this feature, use parameter `expand_gz_topic_names`. +Let's test our topic with namespace: + +```bash +# Shell A: +. ~/bridge_ws/install/setup.bash +ros2 run ros_gz_bridge parameter_bridge chatter@std_msgs/msg/String@ignition.msgs.StringMsg \ + --ros-args -p expand_gz_topic_names:=true -r __ns:=/demo +``` + +Now we start the Gazebo Transport listener. + +```bash +# Shell B: +gz topic -e -t /demo/chatter +``` + +Now we start the ROS talker. + +```bash +# Shell C: +. /opt/ros/rolling/setup.bash +ros2 topic pub /demo/chatter std_msgs/msg/String "data: 'Hi from inside of a namespace'" --once +``` + +By changing `chatter` to `/chatter` or `~/chatter` you can obtain different results. + ## API ROS 2 Parameters: * `subscription_heartbeat` - Period at which the node checks for new subscribers for lazy bridges. * `config_file` - YAML file to be loaded as the bridge configuration + * `expand_gz_topic_names` - Enable or disable ROS namespace applied on GZ topics. diff --git a/ros_gz_bridge/bin/ros_gz_bridge_markdown_table b/ros_gz_bridge/bin/ros_gz_bridge_markdown_table index 05c11b72..6e5d12e4 100755 --- a/ros_gz_bridge/bin/ros_gz_bridge_markdown_table +++ b/ros_gz_bridge/bin/ros_gz_bridge_markdown_table @@ -37,11 +37,11 @@ def main(argv=sys.argv[1:]): msgs_ver = tuple(map(int, args.gz_msgs_ver.split('.'))) rows = [] - rows.append(f'| {"ROS type":32}| {"Gazebo Transport Type":32}|') - rows.append(f'|{"-":-<33}|:{"-":-<31}:|') + rows.append(f'| {"ROS type":35}| {"Gazebo Transport Type":35}|') + rows.append(f'|{"-":-<36}|:{"-":-<34}:|') for mapping in mappings(msgs_ver): - rows.append('| {:32}| {:32}|'.format( + rows.append('| {:35}| {:35}|'.format( mapping.ros2_package_name + '/msg/' + mapping.ros2_message_name, mapping.gz_string())) print('\n'.join(rows)) diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert.hpp index 88a4aa81..4f13fbd2 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/geometry_msgs.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/geometry_msgs.hpp index 43860e69..6416fa35 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert/geometry_msgs.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/geometry_msgs.hpp @@ -30,12 +30,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -111,6 +113,18 @@ convert_ros_to_gz( const geometry_msgs::msg::PoseWithCovariance & ros_msg, gz::msgs::PoseWithCovariance & gz_msg); +template<> +void +convert_gz_to_ros( + const gz::msgs::PoseWithCovariance & gz_msg, + geometry_msgs::msg::PoseWithCovarianceStamped & ros_msg); + +template<> +void +convert_ros_to_gz( + const geometry_msgs::msg::PoseWithCovarianceStamped & ros_msg, + gz::msgs::PoseWithCovariance & gz_msg); + template<> void convert_gz_to_ros( @@ -189,6 +203,18 @@ convert_gz_to_ros( const gz::msgs::TwistWithCovariance & gz_msg, geometry_msgs::msg::TwistWithCovariance & ros_msg); +template<> +void +convert_ros_to_gz( + const geometry_msgs::msg::TwistWithCovarianceStamped & ros_msg, + gz::msgs::TwistWithCovariance & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::TwistWithCovariance & gz_msg, + geometry_msgs::msg::TwistWithCovarianceStamped & ros_msg); + template<> void convert_ros_to_gz( diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/gps_msgs.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/gps_msgs.hpp new file mode 100644 index 00000000..d6cf194e --- /dev/null +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/gps_msgs.hpp @@ -0,0 +1,41 @@ +// Copyright 2022 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ROS_GZ_BRIDGE__CONVERT__GPS_MSGS_HPP_ +#define ROS_GZ_BRIDGE__CONVERT__GPS_MSGS_HPP_ + +// Gazebo Msgs +#include + +// ROS 2 messages +#include + +#include + +namespace ros_gz_bridge +{ +template<> +void +convert_ros_to_gz( + const gps_msgs::msg::GPSFix & ros_msg, + gz::msgs::NavSat & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::NavSat & gz_msg, + gps_msgs::msg::GPSFix & ros_msg); +} // namespace ros_gz_bridge + +#endif // ROS_GZ_BRIDGE__CONVERT__GPS_MSGS_HPP_ diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/rcl_interfaces.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/rcl_interfaces.hpp index 261849c5..a81e35a7 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert/rcl_interfaces.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/rcl_interfaces.hpp @@ -15,7 +15,7 @@ #ifndef ROS_GZ_BRIDGE__CONVERT__RCL_INTERFACES_HPP_ #define ROS_GZ_BRIDGE__CONVERT__RCL_INTERFACES_HPP_ -// Ignition messages +// GZ messages #include // ROS 2 messages diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/ros_gz_interfaces.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/ros_gz_interfaces.hpp index c7e671d4..b49f02d7 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert/ros_gz_interfaces.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/ros_gz_interfaces.hpp @@ -18,12 +18,15 @@ // Gazebo Msgs #include #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -35,12 +38,15 @@ // ROS 2 messages #include #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -48,14 +54,8 @@ #include #include -// Required for HAVE_DATAFRAME definition #include -#if HAVE_DATAFRAME -#include -#include -#endif // HAVE_DATAFRAME - #include namespace ros_gz_bridge @@ -97,6 +97,18 @@ convert_gz_to_ros( const gz::msgs::Entity & gz_msg, ros_gz_interfaces::msg::Entity & ros_msg); +template<> +void +convert_ros_to_gz( + const ros_gz_interfaces::msg::EntityWrench & ros_msg, + gz::msgs::EntityWrench & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::EntityWrench & gz_msg, + ros_gz_interfaces::msg::EntityWrench & ros_msg); + template<> void convert_ros_to_gz( @@ -121,7 +133,6 @@ convert_gz_to_ros( const gz::msgs::Contacts & gz_msg, ros_gz_interfaces::msg::Contacts & ros_msg); -#if HAVE_DATAFRAME template<> void convert_ros_to_gz( @@ -133,7 +144,6 @@ void convert_gz_to_ros( const gz::msgs::Dataframe & ign_msg, ros_gz_interfaces::msg::Dataframe & ros_msg); -#endif // HAVE_DATAFRAME template<> void @@ -159,6 +169,18 @@ convert_gz_to_ros( const gz::msgs::Light & gz_msg, ros_gz_interfaces::msg::Light & ros_msg); +template<> +void +convert_ros_to_gz( + const ros_gz_interfaces::msg::MaterialColor & ros_msg, + gz::msgs::MaterialColor & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::MaterialColor & gz_msg, + ros_gz_interfaces::msg::MaterialColor & ros_msg); + template<> void convert_ros_to_gz( diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/rosgraph_msgs.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/rosgraph_msgs.hpp index 7916aaa7..d4d7d510 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert/rosgraph_msgs.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/rosgraph_msgs.hpp @@ -16,7 +16,7 @@ #define ROS_GZ_BRIDGE__CONVERT__ROSGRAPH_MSGS_HPP_ // Gazebo Msgs -#include +#include // ROS 2 messages #include diff --git a/ros_gz_bridge/include/ros_gz_bridge/convert/vision_msgs.hpp b/ros_gz_bridge/include/ros_gz_bridge/convert/vision_msgs.hpp index f370144f..b1556f65 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/convert/vision_msgs.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/convert/vision_msgs.hpp @@ -17,9 +17,11 @@ // Gazebo Msgs #include +#include // ROS 2 messages #include "vision_msgs/msg/detection2_d_array.hpp" +#include "vision_msgs/msg/detection3_d_array.hpp" #include namespace ros_gz_bridge @@ -47,6 +49,30 @@ void convert_gz_to_ros( const gz::msgs::AnnotatedAxisAligned2DBox_V & gz_msg, vision_msgs::msg::Detection2DArray & ros_msg); + +template<> +void +convert_ros_to_gz( + const vision_msgs::msg::Detection3D & ros_msg, + gz::msgs::AnnotatedOriented3DBox & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::AnnotatedOriented3DBox & gz_msg, + vision_msgs::msg::Detection3D & ros_msg); + +template<> +void +convert_ros_to_gz( + const vision_msgs::msg::Detection3DArray & ros_msg, + gz::msgs::AnnotatedOriented3DBox_V & gz_msg); + +template<> +void +convert_gz_to_ros( + const gz::msgs::AnnotatedOriented3DBox_V & gz_msg, + vision_msgs::msg::Detection3DArray & ros_msg); } // namespace ros_gz_bridge #endif // ROS_GZ_BRIDGE__CONVERT__VISION_MSGS_HPP_ diff --git a/ros_gz_bridge/include/ros_gz_bridge/ros_gz_bridge.hpp b/ros_gz_bridge/include/ros_gz_bridge/ros_gz_bridge.hpp index 8d9ff631..735cdecc 100644 --- a/ros_gz_bridge/include/ros_gz_bridge/ros_gz_bridge.hpp +++ b/ros_gz_bridge/include/ros_gz_bridge/ros_gz_bridge.hpp @@ -24,18 +24,6 @@ #include #include "ros_gz_bridge/bridge_config.hpp" -// Dataframe is available from versions 8.4.0 (fortress) forward -// This can be removed when the minimum supported version passes 8.4.0 -#if (IGNITION_MSGS_MAJOR_VERSION > 8) || \ - ((IGNITION_MSGS_MAJOR_VERSION == 8) && (IGNITION_MSGS_MINOR_VERSION >= 4)) -#define HAVE_DATAFRAME true -#endif - -#if (GZ_MSGS_MAJOR_VERSION > 8) || \ - ((GZ_MSGS_MAJOR_VERSION == 8) && (GZ_MSGS_MINOR_VERSION >= 4)) -#define HAVE_DATAFRAME true -#endif - namespace ros_gz_bridge { /// Forward declarations @@ -49,7 +37,7 @@ class RosGzBridge : public rclcpp::Node /// \param[in] options options control creation of the ROS 2 node explicit RosGzBridge(const rclcpp::NodeOptions & options = rclcpp::NodeOptions()); - /// \brief Add a new ROS-IGN bridge to the node + /// \brief Add a new ROS-GZ bridge to the node /// \param[in] config Parameters to control creation of a new bridge void add_bridge(const BridgeConfig & config); diff --git a/ros_gz_bridge/launch/ros_gz_bridge.launch b/ros_gz_bridge/launch/ros_gz_bridge.launch new file mode 100644 index 00000000..80004a26 --- /dev/null +++ b/ros_gz_bridge/launch/ros_gz_bridge.launch @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/ros_gz_bridge/launch/ros_gz_bridge.launch.py b/ros_gz_bridge/launch/ros_gz_bridge.launch.py new file mode 100644 index 00000000..397816d1 --- /dev/null +++ b/ros_gz_bridge/launch/ros_gz_bridge.launch.py @@ -0,0 +1,114 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Launch ros_gz bridge in a component container.""" + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, GroupAction +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PythonExpression +from launch_ros.actions import LoadComposableNodes, Node +from launch_ros.descriptions import ComposableNode + + +def generate_launch_description(): + + name = LaunchConfiguration('name') + config_file = LaunchConfiguration('config_file') + container_name = LaunchConfiguration('container_name') + namespace = LaunchConfiguration('namespace') + use_composition = LaunchConfiguration('use_composition') + use_respawn = LaunchConfiguration('use_respawn') + log_level = LaunchConfiguration('log_level') + + declare_name_cmd = DeclareLaunchArgument( + 'name', description='Name of ros_gz_bridge node' + ) + + declare_config_file_cmd = DeclareLaunchArgument( + 'config_file', default_value='', description='YAML config file' + ) + + declare_container_name_cmd = DeclareLaunchArgument( + 'container_name', + default_value='ros_gz_container', + description='Name of container that nodes will load in if use composition', + ) + + declare_namespace_cmd = DeclareLaunchArgument( + 'namespace', default_value='', description='Top-level namespace' + ) + + declare_use_composition_cmd = DeclareLaunchArgument( + 'use_composition', default_value='True', description='Use composed bringup if True' + ) + + declare_use_respawn_cmd = DeclareLaunchArgument( + 'use_respawn', + default_value='False', + description='Whether to respawn if a node crashes. Applied when composition is disabled.', + ) + + declare_log_level_cmd = DeclareLaunchArgument( + 'log_level', default_value='info', description='log level' + ) + + load_nodes = GroupAction( + condition=IfCondition(PythonExpression(['not ', use_composition])), + actions=[ + Node( + package='ros_gz_bridge', + executable='bridge_node', + name=name, + namespace=namespace, + output='screen', + respawn=use_respawn, + respawn_delay=2.0, + parameters=[{'config_file': config_file}], + arguments=['--ros-args', '--log-level', log_level], + ), + ], + ) + + load_composable_nodes = LoadComposableNodes( + condition=IfCondition(use_composition), + target_container=container_name, + composable_node_descriptions=[ + ComposableNode( + package='ros_gz_bridge', + plugin='ros_gz_bridge::RosGzBridge', + name=name, + namespace=namespace, + parameters=[{'config_file': config_file}], + extra_arguments=[{'use_intra_process_comms': True}], + ), + ], + ) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_name_cmd) + ld.add_action(declare_config_file_cmd) + ld.add_action(declare_container_name_cmd) + ld.add_action(declare_namespace_cmd) + ld.add_action(declare_use_composition_cmd) + ld.add_action(declare_use_respawn_cmd) + ld.add_action(declare_log_level_cmd) + # Add the actions to launch all of the bridge nodes + ld.add_action(load_nodes) + ld.add_action(load_composable_nodes) + + return ld diff --git a/ros_gz_bridge/package.xml b/ros_gz_bridge/package.xml index 6921940b..beb5a5aa 100644 --- a/ros_gz_bridge/package.xml +++ b/ros_gz_bridge/package.xml @@ -2,20 +2,28 @@ ros_gz_bridge - 0.244.12 + 2.0.0 Bridge communication between ROS and Gazebo Transport - Louise Poubel + Aditya Pande + Alejandro Hernandez Apache 2.0 Shivesh Khaitan + Louise Poubel + Carlos Agüero ament_cmake + ament_cmake_python pkg-config + rosidl_pycommon actuator_msgs camera_track_msgs geometry_msgs + gps_msgs + launch + launch_ros nav_msgs rclcpp rclcpp_components @@ -28,20 +36,8 @@ yaml_cpp_vendor vision_msgs - - gz-msgs10 - gz-transport13 - - gz-msgs9 - gz-transport12 - - ignition-msgs8 - ignition-transport11 - ignition-msgs8 - ignition-transport11 - - ignition-msgs7 - ignition-transport10 + gz_msgs_vendor + gz_transport_vendor ament_cmake_gtest ament_lint_auto diff --git a/ros_gz_bridge/resource/pkg_factories.cpp.em b/ros_gz_bridge/resource/pkg_factories.cpp.em index ef81673e..2d9bcfaa 100644 --- a/ros_gz_bridge/resource/pkg_factories.cpp.em +++ b/ros_gz_bridge/resource/pkg_factories.cpp.em @@ -39,7 +39,7 @@ get_factory__@(ros2_package_name)( return std::make_shared< Factory< @(m.ros2_type()), - @(m.ign_type()) + @(m.gz_type()) > >("@(m.ros2_string())", "@(m.gz_string())"); } @@ -52,10 +52,10 @@ template<> void Factory< @(m.ros2_type()), - @(m.ign_type()) + @(m.gz_type()) >::convert_ros_to_gz( const @(m.ros2_type()) & ros_msg, - @(m.ign_type()) & gz_msg) + @(m.gz_type()) & gz_msg) { ros_gz_bridge::convert_ros_to_gz(ros_msg, gz_msg); } @@ -64,9 +64,9 @@ template<> void Factory< @(m.ros2_type()), - @(m.ign_type()) + @(m.gz_type()) >::convert_gz_to_ros( - const @(m.ign_type()) & gz_msg, + const @(m.gz_type()) & gz_msg, @(m.ros2_type()) & ros_msg) { ros_gz_bridge::convert_gz_to_ros(gz_msg, ros_msg); diff --git a/ros_gz_bridge/resource/ros_gz_bridge b/ros_gz_bridge/resource/ros_gz_bridge new file mode 100644 index 00000000..e69de29b diff --git a/ros_gz_bridge/ros_gz_bridge/__init__.py b/ros_gz_bridge/ros_gz_bridge/__init__.py index b9291840..f6ea05ee 100644 --- a/ros_gz_bridge/ros_gz_bridge/__init__.py +++ b/ros_gz_bridge/ros_gz_bridge/__init__.py @@ -16,9 +16,15 @@ import os -from ros_gz_bridge.mappings import MAPPINGS, MAPPINGS_8_4_0 +from ros_gz_bridge.mappings import MAPPINGS -from rosidl_cmake import expand_template +from rosidl_pycommon import expand_template + +from . import actions + +__all__ = [ + 'actions', +] @dataclass @@ -66,15 +72,6 @@ def mappings(gz_msgs_ver): ros2_message_name=mapping.ros_type, gz_message_name=mapping.gz_type )) - - if gz_msgs_ver >= (8, 4, 0): - for (ros2_package_name, mappings) in MAPPINGS_8_4_0.items(): - for mapping in sorted(mappings): - data.append(MessageMapping( - ros2_package_name=ros2_package_name, - ros2_message_name=mapping.ros_type, - gz_message_name=mapping.gz_type - )) return sorted(data, key=lambda mm: mm.ros2_string()) diff --git a/ros_gz_bridge/ros_gz_bridge/actions/__init__.py b/ros_gz_bridge/ros_gz_bridge/actions/__init__.py new file mode 100644 index 00000000..0a2c2665 --- /dev/null +++ b/ros_gz_bridge/ros_gz_bridge/actions/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Actions module.""" + +from .ros_gz_bridge import RosGzBridge + + +__all__ = [ + 'RosGzBridge', +] diff --git a/ros_gz_bridge/ros_gz_bridge/actions/ros_gz_bridge.py b/ros_gz_bridge/ros_gz_bridge/actions/ros_gz_bridge.py new file mode 100644 index 00000000..9704f44e --- /dev/null +++ b/ros_gz_bridge/ros_gz_bridge/actions/ros_gz_bridge.py @@ -0,0 +1,147 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module for the ros_gz bridge action.""" + +from typing import List +from typing import Optional + +from launch.action import Action +from launch.actions import IncludeLaunchDescription +from launch.frontend import Entity, expose_action, Parser +from launch.launch_context import LaunchContext +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.some_substitutions_type import SomeSubstitutionsType +from launch.substitutions import PathJoinSubstitution +from launch_ros.substitutions import FindPackageShare + + +@expose_action('ros_gz_bridge') +class RosGzBridge(Action): + """Action that executes a ros_gz bridge ROS [composable] node.""" + + def __init__( + self, + *, + name: SomeSubstitutionsType, + config_file: Optional[SomeSubstitutionsType] = None, + container_name: Optional[SomeSubstitutionsType] = None, + namespace: Optional[SomeSubstitutionsType] = None, + use_composition: Optional[SomeSubstitutionsType] = None, + use_respawn: Optional[SomeSubstitutionsType] = None, + log_level: Optional[SomeSubstitutionsType] = None, + **kwargs + ) -> None: + """ + Construct a ros_gz bridge action. + + All arguments are forwarded to `ros_gz_bridge.launch.ros_gz_bridge.launch.py`, + so see the documentation of that class for further details. + + :param: name Name of ros_gz_bridge node + :param: config_file YAML config file. + :param: container_name Name of container that nodes will load in if use composition. + :param: namespace Top-level namespace. + :param: use_composition Use composed bringup if True. + :param: use_respawn Whether to respawn if a node crashes (when composition is disabled). + :param: log_level Log level. + """ + super().__init__(**kwargs) + self.__name = name + self.__config_file = config_file + self.__container_name = container_name + self.__namespace = namespace + self.__use_composition = use_composition + self.__use_respawn = use_respawn + self.__log_level = log_level + + @classmethod + def parse(cls, entity: Entity, parser: Parser): + """Parse ros_gz_bridge.""" + _, kwargs = super().parse(entity, parser) + + name = entity.get_attr( + 'name', data_type=str, + optional=False) + + config_file = entity.get_attr( + 'config_file', data_type=str, + optional=False) + + container_name = entity.get_attr( + 'container_name', data_type=str, + optional=True) + + namespace = entity.get_attr( + 'namespace', data_type=str, + optional=True) + + use_composition = entity.get_attr( + 'use_composition', data_type=str, + optional=True) + + use_respawn = entity.get_attr( + 'use_respawn', data_type=str, + optional=True) + + log_level = entity.get_attr( + 'log_level', data_type=str, + optional=True) + + if isinstance(name, str): + name = parser.parse_substitution(name) + kwargs['name'] = name + + if isinstance(config_file, str): + config_file = parser.parse_substitution(config_file) + kwargs['config_file'] = config_file + + if isinstance(container_name, str): + container_name = parser.parse_substitution(container_name) + kwargs['container_name'] = container_name + + if isinstance(namespace, str): + namespace = parser.parse_substitution(namespace) + kwargs['namespace'] = namespace + + if isinstance(use_composition, str): + use_composition = parser.parse_substitution(use_composition) + kwargs['use_composition'] = use_composition + + if isinstance(use_respawn, str): + use_respawn = parser.parse_substitution(use_respawn) + kwargs['use_respawn'] = use_respawn + + if isinstance(log_level, str): + log_level = parser.parse_substitution(log_level) + kwargs['log_level'] = log_level + + return cls, kwargs + + def execute(self, context: LaunchContext) -> Optional[List[Action]]: + """Execute the action.""" + ros_gz_bridge_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_bridge'), + 'launch', + 'ros_gz_bridge.launch.py'])]), + launch_arguments=[('name', self.__name), + ('config_file', self.__config_file), + ('container_name', self.__container_name), + ('namespace', self.__namespace), + ('use_composition', self.__use_composition), + ('use_respawn', self.__use_respawn), + ('log_level', self.__log_level), ]) + + return [ros_gz_bridge_description] diff --git a/ros_gz_bridge/ros_gz_bridge/mappings.py b/ros_gz_bridge/ros_gz_bridge/mappings.py index 9de3472d..3b6c02df 100644 --- a/ros_gz_bridge/ros_gz_bridge/mappings.py +++ b/ros_gz_bridge/ros_gz_bridge/mappings.py @@ -39,16 +39,21 @@ Mapping('PoseArray', 'Pose_V'), Mapping('PoseStamped', 'Pose'), Mapping('PoseWithCovariance', 'PoseWithCovariance'), + Mapping('PoseWithCovarianceStamped', 'PoseWithCovariance'), Mapping('Quaternion', 'Quaternion'), Mapping('Transform', 'Pose'), Mapping('TransformStamped', 'Pose'), Mapping('Twist', 'Twist'), Mapping('TwistStamped', 'Twist'), Mapping('TwistWithCovariance', 'TwistWithCovariance'), + Mapping('TwistWithCovarianceStamped', 'TwistWithCovariance'), Mapping('Wrench', 'Wrench'), Mapping('WrenchStamped', 'Wrench'), Mapping('Vector3', 'Vector3d'), ], + 'gps_msgs': [ + Mapping('GPSFix', 'NavSat'), + ], 'nav_msgs': [ Mapping('Odometry', 'Odometry'), Mapping('Odometry', 'OdometryWithCovariance'), @@ -60,11 +65,14 @@ Mapping('Altimeter', 'Altimeter'), Mapping('Contact', 'Contact'), Mapping('Contacts', 'Contacts'), + Mapping('Dataframe', 'Dataframe'), Mapping('Entity', 'Entity'), + Mapping('EntityWrench', 'EntityWrench'), Mapping('Float32Array', 'Float_V'), Mapping('GuiCamera', 'GUICamera'), Mapping('JointWrench', 'JointWrench'), Mapping('Light', 'Light'), + Mapping('MaterialColor', 'MaterialColor'), Mapping('ParamVec', 'Param'), Mapping('ParamVec', 'Param_V'), Mapping('SensorNoise', 'SensorNoise'), @@ -108,11 +116,7 @@ 'vision_msgs': [ Mapping('Detection2DArray', 'AnnotatedAxisAligned2DBox_V'), Mapping('Detection2D', 'AnnotatedAxisAligned2DBox'), - ], -} - -MAPPINGS_8_4_0 = { - 'ros_gz_interfaces': [ - Mapping('Dataframe', 'Dataframe'), + Mapping('Detection3DArray', 'AnnotatedOriented3DBox_V'), + Mapping('Detection3D', 'AnnotatedOriented3DBox'), ], } diff --git a/ros_gz_bridge/setup.cfg b/ros_gz_bridge/setup.cfg new file mode 100644 index 00000000..1f707813 --- /dev/null +++ b/ros_gz_bridge/setup.cfg @@ -0,0 +1,3 @@ +[options.entry_points] +launch.frontend.launch_extension = + ros_gz_bridge = ros_gz_bridge diff --git a/ros_gz_bridge/src/bridge_config.cpp b/ros_gz_bridge/src/bridge_config.cpp index 52d649f7..d15e0dd8 100644 --- a/ros_gz_bridge/src/bridge_config.cpp +++ b/ros_gz_bridge/src/bridge_config.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include @@ -40,12 +41,6 @@ constexpr const char kBidirectional[] = "BIDIRECTIONAL"; constexpr const char kGzToRos[] = "GZ_TO_ROS"; constexpr const char kRosToGz[] = "ROS_TO_GZ"; -/// \TODO(mjcarroll) Remove these in releases past Humble/Garden -constexpr const char kIgnTypeName[] = "ign_type_name"; -constexpr const char kIgnTopicName[] = "ign_topic_name"; -constexpr const char kIgnToRos[] = "IGN_TO_ROS"; -constexpr const char kRosToIgn[] = "ROS_TO_IGN"; - /// \brief Parse a single sequence entry into a BridgeConfig /// \param[in] yaml_node A node containing a map of bridge config params /// \return BridgeConfig on success, nullopt on failure @@ -60,43 +55,37 @@ std::optional parseEntry(const YAML::Node & yaml_node) return {}; } - /// \TODO(mjcarroll) Remove gz_type_name logic in releases past Humble - std::string gz_type_name = ""; - if (yaml_node[kIgnTypeName] && !yaml_node[kGzTypeName]) { - gz_type_name = yaml_node[kIgnTypeName].as(); - RCLCPP_ERROR( - logger, - "%s is deprecated, migrate to %s", kIgnTypeName, kGzTypeName); - } else if (yaml_node[kGzTypeName]) { - gz_type_name = yaml_node[kGzTypeName].as(); - } - - /// \TODO(mjcarroll) Remove gz_topic_name logic in releases past Humble - std::string gz_topic_name = ""; - if (yaml_node[kIgnTopicName] && !yaml_node[kGzTopicName]) { - gz_topic_name = yaml_node[kIgnTopicName].as(); - RCLCPP_ERROR( - logger, - "%s is deprecated, migrate to %s", kIgnTopicName, kGzTopicName); - } else if (yaml_node[kGzTopicName]) { - gz_topic_name = yaml_node[kGzTopicName].as(); - } - - if (yaml_node[kTopicName] && yaml_node[kRosTopicName]) { + auto getValue = [yaml_node](const char * key) -> std::string + { + if (yaml_node[key]) { + return yaml_node[key].as(); + } else { + return ""; + } + }; + + const auto topic_name = getValue(kTopicName); + const auto ros_topic_name = getValue(kRosTopicName); + const auto ros_type_name = getValue(kRosTypeName); + const auto gz_topic_name = getValue(kGzTopicName); + const auto gz_type_name = getValue(kGzTypeName); + const auto direction = getValue(kDirection); + + if (!topic_name.empty() && !ros_topic_name.empty()) { RCLCPP_ERROR( logger, "Could not parse entry: %s and %s are mutually exclusive", kTopicName, kRosTopicName); return {}; } - if (yaml_node[kTopicName] && !gz_topic_name.empty()) { + if (!topic_name.empty() && !gz_topic_name.empty()) { RCLCPP_ERROR( logger, "Could not parse entry: %s and %s are mutually exclusive", kTopicName, kGzTopicName); return {}; } - if (!yaml_node[kRosTypeName] || gz_type_name.empty()) { + if (ros_type_name.empty() || gz_type_name.empty()) { RCLCPP_ERROR( logger, "Could not parse entry: both %s and %s must be set", kRosTypeName, kGzTypeName); @@ -108,52 +97,40 @@ std::optional parseEntry(const YAML::Node & yaml_node) ret.direction = BridgeDirection::BIDIRECTIONAL; if (yaml_node[kDirection]) { - auto dirStr = yaml_node[kDirection].as(); - - if (dirStr == kBidirectional) { + if (direction == kBidirectional) { ret.direction = BridgeDirection::BIDIRECTIONAL; - } else if (dirStr == kGzToRos) { + } else if (direction == kGzToRos) { ret.direction = BridgeDirection::GZ_TO_ROS; - } else if (dirStr == kRosToGz) { + } else if (direction == kRosToGz) { ret.direction = BridgeDirection::ROS_TO_GZ; - } else if (dirStr == kIgnToRos) { - ret.direction = BridgeDirection::GZ_TO_ROS; - RCLCPP_WARN( - logger, - "%s constant is deprecated, migrate to %s", kIgnToRos, kGzToRos); - } else if (dirStr == kRosToIgn) { - ret.direction = BridgeDirection::ROS_TO_GZ; - RCLCPP_WARN( - logger, - "%s constant is deprecated, migrate to %s", kRosToIgn, kRosToGz); } else { RCLCPP_ERROR( logger, - "Could not parse entry: invalid direction [%s]", dirStr.c_str()); + "Could not parse entry: invalid direction [%s]", direction.c_str()); return {}; } } - if (yaml_node[kTopicName]) { + if (!topic_name.empty()) { // Only "topic_name" is set - ret.gz_topic_name = yaml_node[kTopicName].as(); - ret.ros_topic_name = yaml_node[kTopicName].as(); - } else if (yaml_node[kRosTopicName] && gz_topic_name.empty()) { + ret.gz_topic_name = topic_name; + ret.ros_topic_name = topic_name; + } else if (!ros_topic_name.empty() && gz_topic_name.empty()) { // Only "ros_topic_name" is set - ret.gz_topic_name = yaml_node[kRosTopicName].as(); - ret.ros_topic_name = yaml_node[kRosTopicName].as(); - } else if (!gz_topic_name.empty() && !yaml_node[kRosTopicName]) { + ret.gz_topic_name = ros_topic_name; + ret.ros_topic_name = ros_topic_name; + } else if (!gz_topic_name.empty() && ros_topic_name.empty()) { // Only kGzTopicName is set ret.gz_topic_name = gz_topic_name; ret.ros_topic_name = gz_topic_name; } else { // Both are set ret.gz_topic_name = gz_topic_name; - ret.ros_topic_name = yaml_node[kRosTopicName].as(); + ret.ros_topic_name = ros_topic_name; } ret.gz_type_name = gz_type_name; - ret.ros_type_name = yaml_node[kRosTypeName].as(); + ret.ros_type_name = ros_type_name; if (yaml_node[kPublisherQueue]) { ret.publisher_queue_size = yaml_node[kPublisherQueue].as(); @@ -170,16 +147,16 @@ std::optional parseEntry(const YAML::Node & yaml_node) std::vector readFromYaml(std::istream & in) { + auto logger = rclcpp::get_logger("readFromYaml"); auto ret = std::vector(); YAML::Node yaml_node; yaml_node = YAML::Load(in); - auto logger = rclcpp::get_logger("readFromYaml"); if (!yaml_node.IsSequence()) { RCLCPP_ERROR( logger, - "Could not parse config, top level must be a YAML sequence"); + "Could not parse config: top level must be a YAML sequence"); return ret; } @@ -197,6 +174,29 @@ std::vector readFromYamlFile(const std::string & filename) { std::vector ret; std::ifstream in(filename); + + auto logger = rclcpp::get_logger("readFromYamlFile"); + if (!in.is_open()) { + RCLCPP_ERROR( + logger, + "Could not parse config: failed to open file [%s]", filename.c_str()); + return ret; + } + + // Compute file size to warn on empty configuration + const auto fbegin = in.tellg(); + in.seekg(0, std::ios::end); + const auto fend = in.tellg(); + const auto fsize = fend - fbegin; + + if (fsize == 0) { + RCLCPP_ERROR( + logger, + "Could not parse config: file empty [%s]", filename.c_str()); + return ret; + } + + in.seekg(0, std::ios::beg); return readFromYaml(in); } diff --git a/ros_gz_bridge/src/convert/actuator_msgs.cpp b/ros_gz_bridge/src/convert/actuator_msgs.cpp index 0c9bcde3..ddcdd205 100644 --- a/ros_gz_bridge/src/convert/actuator_msgs.cpp +++ b/ros_gz_bridge/src/convert/actuator_msgs.cpp @@ -17,7 +17,6 @@ namespace ros_gz_bridge { - template<> void convert_ros_to_gz( diff --git a/ros_gz_bridge/src/convert/geometry_msgs.cpp b/ros_gz_bridge/src/convert/geometry_msgs.cpp index 60ae1413..01c782a5 100644 --- a/ros_gz_bridge/src/convert/geometry_msgs.cpp +++ b/ros_gz_bridge/src/convert/geometry_msgs.cpp @@ -165,6 +165,27 @@ convert_gz_to_ros( } } +template<> +void +convert_ros_to_gz( + const geometry_msgs::msg::PoseWithCovarianceStamped & ros_msg, + gz::msgs::PoseWithCovariance & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_pose()->mutable_header())); + convert_ros_to_gz(ros_msg.pose, gz_msg); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::PoseWithCovariance & gz_msg, + geometry_msgs::msg::PoseWithCovarianceStamped & ros_msg) +{ + convert_gz_to_ros(gz_msg.pose().header(), ros_msg.header); + convert_gz_to_ros(gz_msg, ros_msg.pose); +} + + template<> void convert_ros_to_gz( @@ -306,6 +327,26 @@ convert_gz_to_ros( } } +template<> +void +convert_ros_to_gz( + const geometry_msgs::msg::TwistWithCovarianceStamped & ros_msg, + gz::msgs::TwistWithCovariance & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_twist()->mutable_header())); + convert_ros_to_gz(ros_msg.twist, gz_msg); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::TwistWithCovariance & gz_msg, + geometry_msgs::msg::TwistWithCovarianceStamped & ros_msg) +{ + convert_gz_to_ros(gz_msg.twist().header(), ros_msg.header); + convert_gz_to_ros(gz_msg, ros_msg.twist); +} + template<> void convert_ros_to_gz( diff --git a/ros_gz_bridge/src/convert/gps_msgs.cpp b/ros_gz_bridge/src/convert/gps_msgs.cpp new file mode 100644 index 00000000..cf2774d6 --- /dev/null +++ b/ros_gz_bridge/src/convert/gps_msgs.cpp @@ -0,0 +1,63 @@ +// Copyright 2022 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "convert/utils.hpp" +#include "ros_gz_bridge/convert/gps_msgs.hpp" + +namespace ros_gz_bridge +{ + +template<> +void +convert_ros_to_gz( + const gps_msgs::msg::GPSFix & ros_msg, + gz::msgs::NavSat & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_header())); + gz_msg.set_latitude_deg(ros_msg.latitude); + gz_msg.set_longitude_deg(ros_msg.longitude); + gz_msg.set_altitude(ros_msg.altitude); + gz_msg.set_frame_id(ros_msg.header.frame_id); + + gz_msg.set_velocity_east(cos(ros_msg.track) * ros_msg.speed); + gz_msg.set_velocity_north(sin(ros_msg.track) * ros_msg.speed); + gz_msg.set_velocity_up(ros_msg.climb); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::NavSat & gz_msg, + gps_msgs::msg::GPSFix & ros_msg) +{ + convert_gz_to_ros(gz_msg.header(), ros_msg.header); + ros_msg.header.frame_id = frame_id_gz_to_ros(gz_msg.frame_id()); + ros_msg.latitude = gz_msg.latitude_deg(); + ros_msg.longitude = gz_msg.longitude_deg(); + ros_msg.altitude = gz_msg.altitude(); + + ros_msg.speed = sqrt( + gz_msg.velocity_east() * gz_msg.velocity_east() + + gz_msg.velocity_north() * gz_msg.velocity_north()); + ros_msg.track = atan2(gz_msg.velocity_north(), gz_msg.velocity_east()); + ros_msg.climb = gz_msg.velocity_up(); + + // position_covariance is not supported in gz::msgs::NavSat. + ros_msg.position_covariance_type = gps_msgs::msg::GPSFix::COVARIANCE_TYPE_UNKNOWN; + ros_msg.status.status = gps_msgs::msg::GPSStatus::STATUS_GBAS_FIX; +} + +} // namespace ros_gz_bridge diff --git a/ros_gz_bridge/src/convert/ros_gz_interfaces.cpp b/ros_gz_bridge/src/convert/ros_gz_interfaces.cpp index fceb296a..eb923b34 100644 --- a/ros_gz_bridge/src/convert/ros_gz_interfaces.cpp +++ b/ros_gz_bridge/src/convert/ros_gz_interfaces.cpp @@ -139,6 +139,28 @@ convert_gz_to_ros( } } +template<> +void +convert_ros_to_gz( + const ros_gz_interfaces::msg::EntityWrench & ros_msg, + gz::msgs::EntityWrench & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_header())); + convert_ros_to_gz(ros_msg.entity, (*gz_msg.mutable_entity())); + convert_ros_to_gz(ros_msg.wrench, (*gz_msg.mutable_wrench())); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::EntityWrench & gz_msg, + ros_gz_interfaces::msg::EntityWrench & ros_msg) +{ + convert_gz_to_ros(gz_msg.header(), ros_msg.header); + convert_gz_to_ros(gz_msg.entity(), ros_msg.entity); + convert_gz_to_ros(gz_msg.wrench(), ros_msg.wrench); +} + template<> void convert_ros_to_gz( @@ -223,7 +245,6 @@ convert_gz_to_ros( } } -#if HAVE_DATAFRAME template<> void convert_ros_to_gz( @@ -273,7 +294,6 @@ convert_gz_to_ros( gz_msg.data().begin() + gz_msg.data().size(), ros_msg.data.begin()); } -#endif // HAVE_DATAFRAME template<> void @@ -380,6 +400,64 @@ convert_gz_to_ros( ros_msg.intensity = gz_msg.intensity(); } +template<> +void +convert_ros_to_gz( + const ros_gz_interfaces::msg::MaterialColor & ros_msg, + gz::msgs::MaterialColor & gz_msg) +{ + using EntityMatch = gz::msgs::MaterialColor::EntityMatch; + + switch (ros_msg.entity_match) { + case ros_gz_interfaces::msg::MaterialColor::FIRST: + gz_msg.set_entity_match(EntityMatch::MaterialColor_EntityMatch_FIRST); + break; + case ros_gz_interfaces::msg::MaterialColor::ALL: + gz_msg.set_entity_match(EntityMatch::MaterialColor_EntityMatch_ALL); + break; + default: + std::cerr << "Unsupported entity match type [" + << ros_msg.entity_match << "]\n"; + } + + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_header())); + convert_ros_to_gz(ros_msg.entity, *gz_msg.mutable_entity()); + convert_ros_to_gz(ros_msg.ambient, *gz_msg.mutable_ambient()); + convert_ros_to_gz(ros_msg.diffuse, *gz_msg.mutable_diffuse()); + convert_ros_to_gz(ros_msg.specular, *gz_msg.mutable_specular()); + convert_ros_to_gz(ros_msg.emissive, *gz_msg.mutable_emissive()); + + gz_msg.set_shininess(ros_msg.shininess); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::MaterialColor & gz_msg, + ros_gz_interfaces::msg::MaterialColor & ros_msg) +{ + using EntityMatch = gz::msgs::MaterialColor::EntityMatch; + if (gz_msg.entity_match() == EntityMatch::MaterialColor_EntityMatch_FIRST) { + ros_msg.entity_match = ros_gz_interfaces::msg::MaterialColor::FIRST; +/* *INDENT-OFF* */ + } else if (gz_msg.entity_match() == + EntityMatch::MaterialColor_EntityMatch_ALL) { +/* *INDENT-ON* */ + ros_msg.entity_match = ros_gz_interfaces::msg::MaterialColor::ALL; + } else { + std::cerr << "Unsupported EntityMatch [" << + gz_msg.entity_match() << "]" << std::endl; + } + convert_gz_to_ros(gz_msg.header(), ros_msg.header); + convert_gz_to_ros(gz_msg.entity(), ros_msg.entity); + convert_gz_to_ros(gz_msg.ambient(), ros_msg.ambient); + convert_gz_to_ros(gz_msg.diffuse(), ros_msg.diffuse); + convert_gz_to_ros(gz_msg.specular(), ros_msg.specular); + convert_gz_to_ros(gz_msg.emissive(), ros_msg.emissive); + + ros_msg.shininess = gz_msg.shininess(); +} + template<> void convert_ros_to_gz( @@ -415,9 +493,7 @@ convert_gz_to_ros( ros_msg.type = 0; } else if (gz_msg.type() == gz::msgs::SensorNoise_Type::SensorNoise_Type_GAUSSIAN) { ros_msg.type = 2; - } else if (gz_msg.type() == // NOLINT - gz::msgs::SensorNoise_Type::SensorNoise_Type_GAUSSIAN_QUANTIZED) // NOLINT - { // NOLINT + } else if (gz_msg.type() == gz::msgs::SensorNoise_Type::SensorNoise_Type_GAUSSIAN_QUANTIZED) { ros_msg.type = 3; } diff --git a/ros_gz_bridge/src/convert/sensor_msgs.cpp b/ros_gz_bridge/src/convert/sensor_msgs.cpp index cddc4f00..f537f908 100644 --- a/ros_gz_bridge/src/convert/sensor_msgs.cpp +++ b/ros_gz_bridge/src/convert/sensor_msgs.cpp @@ -17,6 +17,12 @@ #include "convert/utils.hpp" #include "ros_gz_bridge/convert/sensor_msgs.hpp" +#include "gz/msgs/config.hh" + +#if GZ_MSGS_MAJOR_VERSION >= 10 +#define GZ_MSGS_IMU_HAS_COVARIANCE +#endif + namespace ros_gz_bridge { @@ -160,13 +166,11 @@ convert_gz_to_ros( ros_msg.is_bigendian = false; ros_msg.step = ros_msg.width * num_channels * octets_per_channel; - - auto count = ros_msg.step * ros_msg.height; ros_msg.data.resize(ros_msg.step * ros_msg.height); - std::copy( - gz_msg.data().begin(), - gz_msg.data().begin() + count, - ros_msg.data.begin()); + + // Prefer memcpy over std::copy for performance reasons, + // see https://github.com/gazebosim/ros_gz/pull/565 + memcpy(ros_msg.data.data(), gz_msg.data().c_str(), gz_msg.data().size()); } template<> @@ -274,6 +278,18 @@ convert_ros_to_gz( convert_ros_to_gz(ros_msg.orientation, (*gz_msg.mutable_orientation())); convert_ros_to_gz(ros_msg.angular_velocity, (*gz_msg.mutable_angular_velocity())); convert_ros_to_gz(ros_msg.linear_acceleration, (*gz_msg.mutable_linear_acceleration())); + +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + for (const auto & elem : ros_msg.linear_acceleration_covariance) { + gz_msg.mutable_linear_acceleration_covariance()->add_data(elem); + } + for (const auto & elem : ros_msg.orientation_covariance) { + gz_msg.mutable_orientation_covariance()->add_data(elem); + } + for (const auto & elem : ros_msg.angular_velocity_covariance) { + gz_msg.mutable_angular_velocity_covariance()->add_data(elem); + } +#endif } template<> @@ -287,7 +303,29 @@ convert_gz_to_ros( convert_gz_to_ros(gz_msg.angular_velocity(), ros_msg.angular_velocity); convert_gz_to_ros(gz_msg.linear_acceleration(), ros_msg.linear_acceleration); - // Covariances not supported in gz::msgs::IMU +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + int data_size = gz_msg.linear_acceleration_covariance().data_size(); + if (data_size == 9) { + for (int i = 0; i < data_size; ++i) { + auto data = gz_msg.linear_acceleration_covariance().data()[i]; + ros_msg.linear_acceleration_covariance[i] = data; + } + } + data_size = gz_msg.angular_velocity_covariance().data_size(); + if (data_size == 9) { + for (int i = 0; i < data_size; ++i) { + auto data = gz_msg.angular_velocity_covariance().data()[i]; + ros_msg.angular_velocity_covariance[i] = data; + } + } + data_size = gz_msg.orientation_covariance().data_size(); + if (data_size == 9) { + for (int i = 0; i < data_size; ++i) { + auto data = gz_msg.orientation_covariance().data()[i]; + ros_msg.orientation_covariance[i] = data; + } + } +#endif } template<> @@ -480,7 +518,7 @@ convert_gz_to_ros( ros_msg.longitude = gz_msg.longitude_deg(); ros_msg.altitude = gz_msg.altitude(); - // position_covariance is not supported in Ignition::Msgs::NavSat. + // position_covariance is not supported in gz::msgs::NavSat. ros_msg.position_covariance_type = sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_UNKNOWN; ros_msg.status.status = sensor_msgs::msg::NavSatStatus::STATUS_FIX; } diff --git a/ros_gz_bridge/src/convert/vision_msgs.cpp b/ros_gz_bridge/src/convert/vision_msgs.cpp index 057426c7..61924af5 100644 --- a/ros_gz_bridge/src/convert/vision_msgs.cpp +++ b/ros_gz_bridge/src/convert/vision_msgs.cpp @@ -94,4 +94,89 @@ convert_gz_to_ros( } } +template<> +void +convert_ros_to_gz( + const vision_msgs::msg::Detection3D & ros_msg, + gz::msgs::AnnotatedOriented3DBox & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_header())); + + gz::msgs::Oriented3DBox * box = new gz::msgs::Oriented3DBox(); + gz::msgs::Vector3d * center = new gz::msgs::Vector3d(); + gz::msgs::Vector3d * box_size = new gz::msgs::Vector3d(); + gz::msgs::Quaternion * orientation = new gz::msgs::Quaternion(); + + if (ros_msg.results.size() != 0) { + auto id = ros_msg.results.at(0).hypothesis.class_id; + gz_msg.set_label(std::stoi(id)); + } + + center->set_x(ros_msg.bbox.center.position.x); + center->set_y(ros_msg.bbox.center.position.y); + center->set_z(ros_msg.bbox.center.position.z); + box_size->set_x(ros_msg.bbox.size.x); + box_size->set_y(ros_msg.bbox.size.y); + box_size->set_z(ros_msg.bbox.size.z); + orientation->set_x(ros_msg.bbox.center.orientation.x); + orientation->set_y(ros_msg.bbox.center.orientation.y); + orientation->set_z(ros_msg.bbox.center.orientation.z); + orientation->set_w(ros_msg.bbox.center.orientation.w); + box->set_allocated_center(center); + box->set_allocated_boxsize(box_size); + box->set_allocated_orientation(orientation); + gz_msg.set_allocated_box(box); +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::AnnotatedOriented3DBox & gz_msg, + vision_msgs::msg::Detection3D & ros_msg) +{ + convert_gz_to_ros(gz_msg.header(), ros_msg.header); + + ros_msg.results.resize(1); + ros_msg.results.at(0).hypothesis.class_id = std::to_string(gz_msg.label()); + ros_msg.results.at(0).hypothesis.score = 1.0; + + ros_msg.bbox.center.position.x = gz_msg.box().center().x(); + ros_msg.bbox.center.position.y = gz_msg.box().center().y(); + ros_msg.bbox.center.position.z = gz_msg.box().center().z(); + ros_msg.bbox.size.x = gz_msg.box().boxsize().x(); + ros_msg.bbox.size.y = gz_msg.box().boxsize().y(); + ros_msg.bbox.size.z = gz_msg.box().boxsize().z(); + ros_msg.bbox.center.orientation.x = gz_msg.box().orientation().x(); + ros_msg.bbox.center.orientation.y = gz_msg.box().orientation().y(); + ros_msg.bbox.center.orientation.z = gz_msg.box().orientation().z(); + ros_msg.bbox.center.orientation.w = gz_msg.box().orientation().w(); +} + +template<> +void +convert_ros_to_gz( + const vision_msgs::msg::Detection3DArray & ros_msg, + gz::msgs::AnnotatedOriented3DBox_V & gz_msg) +{ + convert_ros_to_gz(ros_msg.header, (*gz_msg.mutable_header())); + for (const auto & ros_box : ros_msg.detections) { + gz::msgs::AnnotatedOriented3DBox * gz_box = gz_msg.add_annotated_box(); + convert_ros_to_gz(ros_box, *gz_box); + } +} + +template<> +void +convert_gz_to_ros( + const gz::msgs::AnnotatedOriented3DBox_V & gz_msg, + vision_msgs::msg::Detection3DArray & ros_msg) +{ + convert_gz_to_ros(gz_msg.header(), ros_msg.header); + for (const auto & gz_box : gz_msg.annotated_box()) { + vision_msgs::msg::Detection3D ros_box; + convert_gz_to_ros(gz_box, ros_box); + ros_msg.detections.push_back(ros_box); + } +} + } // namespace ros_gz_bridge diff --git a/ros_gz_bridge/src/factory.hpp b/ros_gz_bridge/src/factory.hpp index 35daf416..1ee9ded7 100644 --- a/ros_gz_bridge/src/factory.hpp +++ b/ros_gz_bridge/src/factory.hpp @@ -20,6 +20,7 @@ #include #include +#include // include ROS 2 #include @@ -105,18 +106,16 @@ class Factory : public FactoryInterface size_t /*queue_size*/, rclcpp::PublisherBase::SharedPtr ros_pub) { - std::function subCb = - [this, ros_pub](const GZ_T & _msg, - const gz::transport::MessageInfo & _info) + std::function subCb = + [this, ros_pub](const GZ_T & _msg) { - // Ignore messages that are published from this bridge. - if (!_info.IntraProcess()) { - this->gz_callback(_msg, ros_pub); - } + this->gz_callback(_msg, ros_pub); }; - node->Subscribe(topic_name, subCb); + // Ignore messages that are published from this bridge. + gz::transport::SubscribeOptions opts; + opts.SetIgnoreLocalMessages(true); + node->Subscribe(topic_name, subCb, opts); } protected: diff --git a/ros_gz_bridge/src/parameter_bridge.cpp b/ros_gz_bridge/src/parameter_bridge.cpp index 12aac8ab..d7c80dc4 100644 --- a/ros_gz_bridge/src/parameter_bridge.cpp +++ b/ros_gz_bridge/src/parameter_bridge.cpp @@ -46,19 +46,19 @@ void usage() "the ROS service will forward request to the Gazebo service and then forward\n" "the response back to the ROS client.\n\n" "A bidirectional bridge example:\n" << - " parameter_bridge /chatter@std_msgs/String@ignition.msgs" << + " parameter_bridge /chatter@std_msgs/String@gz.msgs" << ".StringMsg\n\n" << "A bridge from Gazebo to ROS example:\n" << - " parameter_bridge /chatter@std_msgs/String[ignition.msgs" << + " parameter_bridge /chatter@std_msgs/String[gz.msgs" << ".StringMsg\n\n" << "A bridge from ROS to Gazebo example:\n" << - " parameter_bridge /chatter@std_msgs/String]ignition.msgs" << + " parameter_bridge /chatter@std_msgs/String]gz.msgs" << ".StringMsg\n" << "A service bridge:\n" << " parameter_bridge /world/default/control@ros_gz_interfaces/srv/ControlWorld\n" << "Or equivalently:\n" << " parameter_bridge /world/default/control@ros_gz_interfaces/srv/ControlWorld@" - "ignition.msgs.WorldControl@ignition.msgs.Boolean\n" << std::endl; + "gz.msgs.WorldControl@gz.msgs.Boolean\n" << std::endl; } using RosGzBridge = ros_gz_bridge::RosGzBridge; diff --git a/ros_gz_bridge/src/ros_gz_bridge.cpp b/ros_gz_bridge/src/ros_gz_bridge.cpp index f542ee90..46a86d98 100644 --- a/ros_gz_bridge/src/ros_gz_bridge.cpp +++ b/ros_gz_bridge/src/ros_gz_bridge.cpp @@ -20,6 +20,8 @@ #include "bridge_handle_ros_to_gz.hpp" #include "bridge_handle_gz_to_ros.hpp" +#include + namespace ros_gz_bridge { @@ -30,6 +32,7 @@ RosGzBridge::RosGzBridge(const rclcpp::NodeOptions & options) this->declare_parameter("subscription_heartbeat", 1000); this->declare_parameter("config_file", ""); + this->declare_parameter("expand_gz_topic_names", false); int heartbeat; this->get_parameter("subscription_heartbeat", heartbeat); @@ -43,14 +46,21 @@ void RosGzBridge::spin() if (handles_.empty()) { std::string config_file; this->get_parameter("config_file", config_file); + bool expand_names; + this->get_parameter("expand_gz_topic_names", expand_names); + const std::string ros_ns = this->get_namespace(); + const std::string ros_node_name = this->get_name(); if (!config_file.empty()) { auto entries = readFromYamlFile(config_file); - for (const auto & entry : entries) { + for (auto & entry : entries) { + if (expand_names) { + entry.gz_topic_name = rclcpp::expand_topic_or_service_name( + entry.gz_topic_name, ros_node_name, ros_ns, false); + } this->add_bridge(entry); } } } - for (auto & bridge : handles_) { bridge->Spin(); } diff --git a/ros_gz_bridge/src/service_factories/ros_gz_interfaces.cpp b/ros_gz_bridge/src/service_factories/ros_gz_interfaces.cpp index 17fb5289..a3c25a82 100644 --- a/ros_gz_bridge/src/service_factories/ros_gz_interfaces.cpp +++ b/ros_gz_bridge/src/service_factories/ros_gz_interfaces.cpp @@ -35,15 +35,15 @@ get_service_factory__ros_gz_interfaces( { if ( ros_type_name == "ros_gz_interfaces/srv/ControlWorld" && - (gz_req_type_name.empty() || gz_req_type_name == "ignition.msgs.WorldControl") && - (gz_rep_type_name.empty() || gz_rep_type_name == "ignition.msgs.Boolean")) + (gz_req_type_name.empty() || gz_req_type_name == "gz.msgs.WorldControl") && + (gz_rep_type_name.empty() || gz_rep_type_name == "gz.msgs.Boolean")) { return std::make_shared< ServiceFactory< ros_gz_interfaces::srv::ControlWorld, gz::msgs::WorldControl, gz::msgs::Boolean> - >(ros_type_name, "ignition.msgs.WorldControl", "ignition.msgs.Boolean"); + >(ros_type_name, "gz.msgs.WorldControl", "gz.msgs.Boolean"); } return nullptr; diff --git a/ros_gz_bridge/src/service_factory.hpp b/ros_gz_bridge/src/service_factory.hpp index f771d618..4a02503f 100644 --- a/ros_gz_bridge/src/service_factory.hpp +++ b/ros_gz_bridge/src/service_factory.hpp @@ -35,7 +35,7 @@ template bool send_response_on_error(RosResT & ros_response); -template +template class ServiceFactory : public ServiceFactoryInterface { public: @@ -60,12 +60,12 @@ class ServiceFactory : public ServiceFactoryInterface std::shared_ptr reqid, std::shared_ptr ros_req) { - std::function callback; + std::function callback; callback = [ srv_handle = std::move(srv_handle), reqid ]( - const IgnReplyT & reply, + const GzReplyT & reply, const bool result) { typename RosServiceT::Response ros_res; @@ -77,7 +77,7 @@ class ServiceFactory : public ServiceFactoryInterface convert_gz_to_ros(reply, ros_res); srv_handle->send_response(*reqid, ros_res); }; - IgnRequestT gz_req; + GzRequestT gz_req; convert_ros_to_gz(*ros_req, gz_req); gz_node->Request( service_name, diff --git a/ros_gz_bridge/src/service_factory_interface.cpp b/ros_gz_bridge/src/service_factory_interface.cpp new file mode 100644 index 00000000..4789e066 --- /dev/null +++ b/ros_gz_bridge/src/service_factory_interface.cpp @@ -0,0 +1,24 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "service_factory_interface.hpp" + +namespace ros_gz_bridge +{ + +ServiceFactoryInterface::~ServiceFactoryInterface() +{ +} + +} // namespace ros_gz_bridge diff --git a/ros_gz_bridge/src/service_factory_interface.hpp b/ros_gz_bridge/src/service_factory_interface.hpp index 9d4f7334..766ce515 100644 --- a/ros_gz_bridge/src/service_factory_interface.hpp +++ b/ros_gz_bridge/src/service_factory_interface.hpp @@ -29,6 +29,8 @@ namespace ros_gz_bridge class ServiceFactoryInterface { public: + virtual ~ServiceFactoryInterface() = 0; + virtual rclcpp::ServiceBase::SharedPtr create_ros_service( diff --git a/ros_gz_bridge/src/static_bridge.cpp b/ros_gz_bridge/src/static_bridge.cpp index bf5cd38d..7692866a 100644 --- a/ros_gz_bridge/src/static_bridge.cpp +++ b/ros_gz_bridge/src/static_bridge.cpp @@ -37,7 +37,7 @@ int main(int argc, char * argv[]) config.ros_topic_name = "chatter"; config.gz_topic_name = "chatter"; config.ros_type_name = "std_msgs/msg/String"; - config.gz_type_name = "ignition.msgs.StringMsg"; + config.gz_type_name = "gz.msgs.StringMsg"; config.is_lazy = lazy_subscription; bridge_node->add_bridge(config); diff --git a/ros_gz_bridge/test/bridge_config.cpp b/ros_gz_bridge/test/bridge_config.cpp index 45ace8a5..07987865 100644 --- a/ros_gz_bridge/test/bridge_config.cpp +++ b/ros_gz_bridge/test/bridge_config.cpp @@ -16,56 +16,61 @@ #include -TEST(BridgeConfig, Minimum) +#include "rcutils/logging.h" + +size_t g_log_calls = 0; + +struct LogEvent { - auto results = ros_gz_bridge::readFromYamlFile("test/config/minimum.yaml"); - EXPECT_EQ(4u, results.size()); + const rcutils_log_location_t * location; + int level; + std::string name; + rcutils_time_point_value_t timestamp; + std::string message; +}; +LogEvent g_last_log_event; +class BridgeConfig : public ::testing::Test +{ +public: + rcutils_logging_output_handler_t previous_output_handler; + void SetUp() { - auto config = results[0]; - EXPECT_EQ("chatter", config.ros_topic_name); - EXPECT_EQ("chatter", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(ros_gz_bridge::kDefaultPublisherQueue, config.publisher_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultSubscriberQueue, config.subscriber_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultLazy, config.is_lazy); - } - { - auto config = results[1]; - EXPECT_EQ("chatter_ros", config.ros_topic_name); - EXPECT_EQ("chatter_ros", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(ros_gz_bridge::kDefaultPublisherQueue, config.publisher_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultSubscriberQueue, config.subscriber_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultLazy, config.is_lazy); - } - { - auto config = results[2]; - EXPECT_EQ("chatter_gz", config.ros_topic_name); - EXPECT_EQ("chatter_gz", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(ros_gz_bridge::kDefaultPublisherQueue, config.publisher_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultSubscriberQueue, config.subscriber_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultLazy, config.is_lazy); + g_log_calls = 0; + ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); + rcutils_logging_set_default_logger_level(RCUTILS_LOG_SEVERITY_DEBUG); + + auto rcutils_logging_console_output_handler = []( + const rcutils_log_location_t * location, + int level, const char * name, rcutils_time_point_value_t timestamp, + const char * format, va_list * args) -> void + { + g_log_calls += 1; + g_last_log_event.location = location; + g_last_log_event.level = level; + g_last_log_event.name = name ? name : ""; + g_last_log_event.timestamp = timestamp; + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, *args); + g_last_log_event.message = buffer; + }; + + this->previous_output_handler = rcutils_logging_get_output_handler(); + rcutils_logging_set_output_handler(rcutils_logging_console_output_handler); } + + void TearDown() { - auto config = results[3]; - EXPECT_EQ("chatter_both_ros", config.ros_topic_name); - EXPECT_EQ("chatter_both_gz", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(ros_gz_bridge::kDefaultPublisherQueue, config.publisher_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultSubscriberQueue, config.subscriber_queue_size); - EXPECT_EQ(ros_gz_bridge::kDefaultLazy, config.is_lazy); + rcutils_logging_set_output_handler(this->previous_output_handler); + ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); + EXPECT_FALSE(g_rcutils_logging_initialized); } -} +}; -TEST(BridgeConfig, MinimumIgn) + +TEST_F(BridgeConfig, Minimum) { - auto results = ros_gz_bridge::readFromYamlFile("test/config/minimum_ign.yaml"); + auto results = ros_gz_bridge::readFromYamlFile("test/config/minimum.yaml"); EXPECT_EQ(4u, results.size()); { @@ -110,38 +115,7 @@ TEST(BridgeConfig, MinimumIgn) } } - -TEST(BridgeConfig, FullGz) -{ - auto results = ros_gz_bridge::readFromYamlFile("test/config/full.yaml"); - EXPECT_EQ(2u, results.size()); - - { - auto config = results[0]; - EXPECT_EQ("ros_chatter", config.ros_topic_name); - EXPECT_EQ("gz_chatter", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(6u, config.publisher_queue_size); - EXPECT_EQ(5u, config.subscriber_queue_size); - EXPECT_EQ(true, config.is_lazy); - EXPECT_EQ(ros_gz_bridge::BridgeDirection::ROS_TO_GZ, config.direction); - } - - { - auto config = results[1]; - EXPECT_EQ("ros_chatter", config.ros_topic_name); - EXPECT_EQ("gz_chatter", config.gz_topic_name); - EXPECT_EQ("std_msgs/msg/String", config.ros_type_name); - EXPECT_EQ("ignition.msgs.StringMsg", config.gz_type_name); - EXPECT_EQ(20u, config.publisher_queue_size); - EXPECT_EQ(10u, config.subscriber_queue_size); - EXPECT_EQ(false, config.is_lazy); - EXPECT_EQ(ros_gz_bridge::BridgeDirection::GZ_TO_ROS, config.direction); - } -} - -TEST(BridgeConfig, FullIgn) +TEST_F(BridgeConfig, FullGz) { auto results = ros_gz_bridge::readFromYamlFile("test/config/full.yaml"); EXPECT_EQ(2u, results.size()); @@ -171,7 +145,7 @@ TEST(BridgeConfig, FullIgn) } } -TEST(BridgeConfig, InvalidSetTwoRos) +TEST_F(BridgeConfig, InvalidSetTwoRos) { // Cannot set topic_name and ros_topic_name auto yaml = R"( @@ -180,9 +154,12 @@ TEST(BridgeConfig, InvalidSetTwoRos) auto results = ros_gz_bridge::readFromYamlString(yaml); EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse entry: topic_name and ros_topic_name are mutually exclusive", + g_last_log_event.message); } -TEST(BridgeConfig, InvalidSetTwoGz) +TEST_F(BridgeConfig, InvalidSetTwoGz) { // Cannot set topic_name and gz_topic_name auto yaml = R"( @@ -191,9 +168,12 @@ TEST(BridgeConfig, InvalidSetTwoGz) auto results = ros_gz_bridge::readFromYamlString(yaml); EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse entry: topic_name and gz_topic_name are mutually exclusive", + g_last_log_event.message); } -TEST(BridgeConfig, InvalidSetTypes) +TEST_F(BridgeConfig, InvalidSetTypes) { // Both ros_type_name and gz_type_name must be set auto yaml = R"( @@ -202,9 +182,12 @@ TEST(BridgeConfig, InvalidSetTypes) auto results = ros_gz_bridge::readFromYamlString(yaml); EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse entry: both ros_type_name and gz_type_name must be set", + g_last_log_event.message); } -TEST(BridgeConfig, ParseDirection) +TEST_F(BridgeConfig, ParseDirection) { { // Check that default is bidirectional @@ -264,10 +247,38 @@ TEST(BridgeConfig, ParseDirection) - topic_name: foo ros_type_name: std_msgs/msg/String gz_type_name: ignition.msgs.StringMsg - direction: asdfasdfasdfasdf + direction: foobar )"; auto results = ros_gz_bridge::readFromYamlString(yaml); EXPECT_EQ(0u, results.size()); + EXPECT_EQ("Could not parse entry: invalid direction [foobar]", g_last_log_event.message); } } + +TEST_F(BridgeConfig, InvalidFileDoesntExist) +{ + auto results = ros_gz_bridge::readFromYamlFile("this/should/never/be/a/file.yaml"); + EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse config: failed to open file [this/should/never/be/a/file.yaml]", + g_last_log_event.message); +} + +TEST_F(BridgeConfig, InvalidTopLevel) +{ + auto results = ros_gz_bridge::readFromYamlFile("test/config/invalid.yaml"); + EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse config: top level must be a YAML sequence", + g_last_log_event.message); +} + +TEST_F(BridgeConfig, EmptyYAML) +{ + auto results = ros_gz_bridge::readFromYamlFile("test/config/empty.yaml"); + EXPECT_EQ(0u, results.size()); + EXPECT_EQ( + "Could not parse config: file empty [test/config/empty.yaml]", + g_last_log_event.message); +} diff --git a/ros_gz_bridge/test/config/empty.yaml b/ros_gz_bridge/test/config/empty.yaml new file mode 100644 index 00000000..e69de29b diff --git a/ros_gz_bridge/test/config/full_ign.yaml b/ros_gz_bridge/test/config/full_ign.yaml deleted file mode 100644 index fbee755b..00000000 --- a/ros_gz_bridge/test/config/full_ign.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Full set of configurations -- ros_topic_name: "ros_chatter" - ign_topic_name: "gz_chatter" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" - subscriber_queue: 5 - publisher_queue: 6 - lazy: true - direction: ROS_TO_IGN - -- ros_topic_name: "ros_chatter" - ign_topic_name: "gz_chatter" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" - subscriber_queue: 10 - publisher_queue: 20 - lazy: false - direction: IGN_TO_ROS diff --git a/ros_gz_bridge/test/config/invalid.yaml b/ros_gz_bridge/test/config/invalid.yaml new file mode 100644 index 00000000..c14740ad --- /dev/null +++ b/ros_gz_bridge/test/config/invalid.yaml @@ -0,0 +1,8 @@ +ros_topic_name: "ros_chatter" +gz_topic_name: "gz_chatter" +ros_type_name: "std_msgs/msg/String" +gz_type_name: "ignition.msgs.StringMsg" +subscriber_queue: 5 +publisher_queue: 6 +lazy: true +direction: ROS_TO_GZ diff --git a/ros_gz_bridge/test/config/minimum_ign.yaml b/ros_gz_bridge/test/config/minimum_ign.yaml deleted file mode 100644 index 3fe8bc27..00000000 --- a/ros_gz_bridge/test/config/minimum_ign.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Set just topic name, applies to both -- topic_name: "chatter" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" - -# Set just ROS topic name, applies to both -- ros_topic_name: "chatter_ros" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" - -# Set just GZ topic name, applies to both -- gz_topic_name: "chatter_gz" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" - -# Set each topic name explicitly -- ros_topic_name: "chatter_both_ros" - ign_topic_name: "chatter_both_gz" - ros_type_name: "std_msgs/msg/String" - ign_type_name: "ignition.msgs.StringMsg" diff --git a/ros_gz_bridge/test/resource/gz_publisher.cpp.em b/ros_gz_bridge/test/resource/gz_publisher.cpp.em index 9cccbfe0..07a1de91 100644 --- a/ros_gz_bridge/test/resource/gz_publisher.cpp.em +++ b/ros_gz_bridge/test/resource/gz_publisher.cpp.em @@ -55,8 +55,8 @@ int main(int /*argc*/, char **/*argv*/) @[for m in mappings]@ // @(m.gz_string()). auto @(m.unique())_pub = - node.Advertise<@(m.ign_type())>("@(m.unique())"); - @(m.ign_type()) @(m.unique())_msg; + node.Advertise<@(m.gz_type())>("@(m.unique())"); + @(m.gz_type()) @(m.unique())_msg; ros_gz_bridge::testing::createTestMsg(@(m.unique())_msg); @[end for]@ diff --git a/ros_gz_bridge/test/resource/gz_subscriber.cpp.em b/ros_gz_bridge/test/resource/gz_subscriber.cpp.em index 6edae074..c6b899ed 100644 --- a/ros_gz_bridge/test/resource/gz_subscriber.cpp.em +++ b/ros_gz_bridge/test/resource/gz_subscriber.cpp.em @@ -54,7 +54,7 @@ private: gz::transport::Node node; ///////////////////////////////////////////////// TEST(GzSubscriberTest, @(m.unique())) { - MyTestClass<@(m.ign_type())> client("@(m.unique())"); + MyTestClass<@(m.gz_type())> client("@(m.unique())"); using namespace std::chrono_literals; ros_gz_bridge::testing::waitUntilBoolVar( diff --git a/ros_gz_bridge/test/utils/gz_test_msg.cpp b/ros_gz_bridge/test/utils/gz_test_msg.cpp index 505ed922..b13a06b1 100644 --- a/ros_gz_bridge/test/utils/gz_test_msg.cpp +++ b/ros_gz_bridge/test/utils/gz_test_msg.cpp @@ -18,6 +18,11 @@ #include #include +#include + +#if GZ_MSGS_MAJOR_VERSION >= 10 +#define GZ_MSGS_IMU_HAS_COVARIANCE +#endif namespace ros_gz_bridge { @@ -371,6 +376,7 @@ void createTestMsg(gz::msgs::PoseWithCovariance & _msg) { createTestMsg(*_msg.mutable_pose()->mutable_position()); createTestMsg(*_msg.mutable_pose()->mutable_orientation()); + createTestMsg(*_msg.mutable_pose()->mutable_header()); for (int i = 0; i < 36; i++) { _msg.mutable_covariance()->add_data(i); } @@ -428,12 +434,15 @@ void createTestMsg(gz::msgs::TwistWithCovariance & _msg) { gz::msgs::Vector3d linear_msg; gz::msgs::Vector3d angular_msg; + gz::msgs::Header header_msg; createTestMsg(linear_msg); createTestMsg(angular_msg); + createTestMsg(header_msg); _msg.mutable_twist()->mutable_linear()->CopyFrom(linear_msg); _msg.mutable_twist()->mutable_angular()->CopyFrom(angular_msg); + _msg.mutable_twist()->mutable_header()->CopyFrom(header_msg); for (int i = 0; i < 36; i++) { _msg.mutable_covariance()->add_data(i); } @@ -517,6 +526,30 @@ void compareTestMsg(const std::shared_ptr & _msg) EXPECT_EQ(expected_msg.type(), _msg->type()); } +void createTestMsg(gz::msgs::EntityWrench & _msg) +{ + gz::msgs::Header header_msg; + gz::msgs::Entity entity_msg; + gz::msgs::Wrench wrench_msg; + + createTestMsg(header_msg); + createTestMsg(entity_msg); + createTestMsg(wrench_msg); + + _msg.mutable_header()->CopyFrom(header_msg); + _msg.mutable_entity()->CopyFrom(entity_msg); + _msg.mutable_wrench()->CopyFrom(wrench_msg); +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + gz::msgs::EntityWrench expected_msg; + createTestMsg(expected_msg); + compareTestMsg(std::make_shared(_msg->header())); + compareTestMsg(std::make_shared(_msg->entity())); + compareTestMsg(std::make_shared(_msg->wrench())); +} + void createTestMsg(gz::msgs::Contact & _msg) { gz::msgs::Entity collision1; @@ -608,7 +641,6 @@ void compareTestMsg(const std::shared_ptr & _msg) } } -#if HAVE_DATAFRAME void createTestMsg(gz::msgs::Dataframe & _msg) { gz::msgs::Header header_msg; @@ -646,7 +678,6 @@ void compareTestMsg(const std::shared_ptr & _msg) EXPECT_EQ(expected_msg.dst_address(), _msg->dst_address()); EXPECT_EQ(expected_msg.data(), _msg->data()); } -#endif // HAVE_DATAFRAME void createTestMsg(gz::msgs::Image & _msg) { @@ -810,6 +841,13 @@ void createTestMsg(gz::msgs::IMU & _msg) _msg.mutable_orientation()->CopyFrom(quaternion_msg); _msg.mutable_angular_velocity()->CopyFrom(vector3_msg); _msg.mutable_linear_acceleration()->CopyFrom(vector3_msg); +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + for (int i = 0; i < 9; i++) { + _msg.mutable_orientation_covariance()->add_data(i + 1); + _msg.mutable_angular_velocity_covariance()->add_data(i + 1); + _msg.mutable_linear_acceleration_covariance()->add_data(i + 1); + } +#endif } void compareTestMsg(const std::shared_ptr & _msg) @@ -818,6 +856,13 @@ void compareTestMsg(const std::shared_ptr & _msg) compareTestMsg(std::make_shared(_msg->orientation())); compareTestMsg(std::make_shared(_msg->angular_velocity())); compareTestMsg(std::make_shared(_msg->linear_acceleration())); +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + for (int i = 0; i < 9; i++) { + EXPECT_EQ(_msg->orientation_covariance().data(i), i + 1); + EXPECT_EQ(_msg->angular_velocity_covariance().data(i), i + 1); + EXPECT_EQ(_msg->linear_acceleration_covariance().data(i), i + 1); + } +#endif } void createTestMsg(gz::msgs::Axis & _msg) @@ -1325,6 +1370,35 @@ void compareTestMsg(const std::shared_ptr & _msg) EXPECT_FLOAT_EQ(expected_msg.intensity(), _msg->intensity()); } +void createTestMsg(gz::msgs::MaterialColor & _msg) +{ + createTestMsg(*_msg.mutable_header()); + createTestMsg(*_msg.mutable_entity()); + createTestMsg(*_msg.mutable_ambient()); + createTestMsg(*_msg.mutable_diffuse()); + createTestMsg(*_msg.mutable_specular()); + createTestMsg(*_msg.mutable_emissive()); + + _msg.set_shininess(1.0); + _msg.set_entity_match(gz::msgs::MaterialColor::EntityMatch::MaterialColor_EntityMatch_ALL); +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + gz::msgs::MaterialColor expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(std::make_shared(_msg->header())); + compareTestMsg(std::make_shared(_msg->entity())); + compareTestMsg(std::make_shared(_msg->ambient())); + compareTestMsg(std::make_shared(_msg->diffuse())); + compareTestMsg(std::make_shared(_msg->specular())); + compareTestMsg(std::make_shared(_msg->emissive())); + + EXPECT_EQ(expected_msg.shininess(), _msg->shininess()); + EXPECT_EQ(expected_msg.entity_match(), _msg->entity_match()); +} + void createTestMsg(gz::msgs::GUICamera & _msg) { gz::msgs::Header header_msg; @@ -1539,5 +1613,92 @@ void compareTestMsg(const std::shared_ptr } } +void createTestMsg(gz::msgs::AnnotatedOriented3DBox & _msg) +{ + gz::msgs::Header header_msg; + + createTestMsg(header_msg); + + _msg.mutable_header()->CopyFrom(header_msg); + + _msg.set_label(1); + + gz::msgs::Oriented3DBox * box = new gz::msgs::Oriented3DBox(); + gz::msgs::Vector3d * center = new gz::msgs::Vector3d(); + gz::msgs::Vector3d * size = new gz::msgs::Vector3d(); + gz::msgs::Quaternion * orientation = new gz::msgs::Quaternion(); + + center->set_x(2.0); + center->set_y(4.0); + center->set_z(6.0); + size->set_x(3.0); + size->set_y(5.0); + size->set_z(7.0); + orientation->set_x(0.733); + orientation->set_y(0.462); + orientation->set_z(0.191); + orientation->set_w(0.462); + + box->set_allocated_center(center); + box->set_allocated_boxsize(size); + box->set_allocated_orientation(orientation); + _msg.set_allocated_box(box); +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + gz::msgs::AnnotatedOriented3DBox expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(std::make_shared(_msg->header())); + + EXPECT_EQ(expected_msg.label(), _msg->label()); + + gz::msgs::Oriented3DBox box = _msg->box(); + gz::msgs::Vector3d center = box.center(); + gz::msgs::Vector3d size = box.boxsize(); + gz::msgs::Quaternion orientation = box.orientation(); + + EXPECT_EQ(expected_msg.box().center().x(), center.x()); + EXPECT_EQ(expected_msg.box().center().y(), center.y()); + EXPECT_EQ(expected_msg.box().center().z(), center.z()); + EXPECT_EQ(expected_msg.box().boxsize().x(), size.x()); + EXPECT_EQ(expected_msg.box().boxsize().y(), size.y()); + EXPECT_EQ(expected_msg.box().boxsize().z(), size.z()); + EXPECT_EQ(expected_msg.box().orientation().w(), orientation.w()); + EXPECT_EQ(expected_msg.box().orientation().x(), orientation.x()); + EXPECT_EQ(expected_msg.box().orientation().y(), orientation.y()); + EXPECT_EQ(expected_msg.box().orientation().z(), orientation.z()); +} + +void createTestMsg(gz::msgs::AnnotatedOriented3DBox_V & _msg) +{ + gz::msgs::Header header_msg; + + createTestMsg(header_msg); + + _msg.mutable_header()->CopyFrom(header_msg); + + for (size_t i = 0; i < 4; i++) { + gz::msgs::AnnotatedOriented3DBox * box = _msg.add_annotated_box(); + createTestMsg(*box); + } +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + gz::msgs::AnnotatedOriented3DBox_V expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(std::make_shared(_msg->header())); + + for (size_t i = 0; i < 4; i++) { + compareTestMsg( + std::make_shared( + _msg->annotated_box( + i))); + } +} + } // namespace testing } // namespace ros_gz_bridge diff --git a/ros_gz_bridge/test/utils/gz_test_msg.hpp b/ros_gz_bridge/test/utils/gz_test_msg.hpp index 7ec6984a..cff1a0af 100644 --- a/ros_gz_bridge/test/utils/gz_test_msg.hpp +++ b/ros_gz_bridge/test/utils/gz_test_msg.hpp @@ -29,8 +29,9 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -65,13 +67,11 @@ #include #include #include +#include #include #include -#if HAVE_DATAFRAME -#include -#endif // HAVE_DATAFRAME namespace ros_gz_bridge { @@ -165,10 +165,6 @@ void createTestMsg(gz::msgs::Clock & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); -/// \brief Create a message used for testing. -/// \param[out] _msg The message populated. -void createTestMsg(gz::msgs::StringMsg & _msg); - /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(gz::msgs::SensorNoise & _msg); @@ -177,6 +173,10 @@ void createTestMsg(gz::msgs::SensorNoise & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gz::msgs::StringMsg & _msg); + /// \brief Compare a message with the populated for testing. /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); @@ -293,6 +293,14 @@ void createTestMsg(gz::msgs::Entity & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gz::msgs::EntityWrench & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(gz::msgs::Contact & _msg); @@ -309,7 +317,6 @@ void createTestMsg(gz::msgs::Contacts & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); -#if HAVE_DATAFRAME /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(gz::msgs::Dataframe & _msg); @@ -317,7 +324,6 @@ void createTestMsg(gz::msgs::Dataframe & _msg); /// \brief Compare a message with the populated for testing. /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); -#endif // HAVE_DATAFRAME /// \brief Create a message used for testing. /// \param[out] _msg The message populated. @@ -455,6 +461,14 @@ void createTestMsg(gz::msgs::Light & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gz::msgs::MaterialColor & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(gz::msgs::GUICamera & _msg); @@ -511,6 +525,22 @@ void createTestMsg(gz::msgs::AnnotatedAxisAligned2DBox_V & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gz::msgs::AnnotatedOriented3DBox & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gz::msgs::AnnotatedOriented3DBox_V & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + } // namespace testing } // namespace ros_gz_bridge diff --git a/ros_gz_bridge/test/utils/ros_test_msg.cpp b/ros_gz_bridge/test/utils/ros_test_msg.cpp index 6c30e98b..42f9b90b 100644 --- a/ros_gz_bridge/test/utils/ros_test_msg.cpp +++ b/ros_gz_bridge/test/utils/ros_test_msg.cpp @@ -18,6 +18,13 @@ #include #include +#include + +#include "gz/msgs/config.hh" + +#if GZ_MSGS_MAJOR_VERSION >= 10 +#define GZ_MSGS_IMU_HAS_COVARIANCE +#endif namespace ros_gz_bridge { @@ -51,6 +58,14 @@ void compareTestMsg(const std::shared_ptr & _msg) EXPECT_EQ(expected_msg.data, _msg->data); } +void createTestMsg(std_msgs::msg::ColorRGBA & _msg) +{ + _msg.r = 0.2; + _msg.g = 0.4; + _msg.b = 0.6; + _msg.a = 0.8; +} + void createTestMsg(actuator_msgs::msg::Actuators & _msg) { std_msgs::msg::Header header_msg; @@ -82,14 +97,6 @@ void compareTestMsg(const std::shared_ptr & _msg) } } -void createTestMsg(std_msgs::msg::ColorRGBA & _msg) -{ - _msg.r = 0.2; - _msg.g = 0.4; - _msg.b = 0.6; - _msg.a = 0.8; -} - void compareTestMsg(const std::shared_ptr & _msg) { std_msgs::msg::ColorRGBA expected_msg; @@ -374,6 +381,18 @@ void compareTestMsg(const std::shared_ptr & _msg) +{ + compareTestMsg(std::make_shared(_msg->pose)); + compareTestMsg(std::make_shared(_msg->header)); +} + void createTestMsg(geometry_msgs::msg::PoseStamped & _msg) { createTestMsg(_msg.header); @@ -477,6 +496,18 @@ void compareTestMsg(const std::shared_ptr & _msg) +{ + compareTestMsg(std::make_shared(_msg->twist)); + compareTestMsg(std::make_shared(_msg->header)); +} + void createTestMsg(geometry_msgs::msg::Wrench & _msg) { createTestMsg(_msg.force); @@ -502,6 +533,38 @@ void compareTestMsg(const std::shared_ptr & _ compareTestMsg(std::make_shared(_msg->wrench.force)); compareTestMsg(std::make_shared(_msg->wrench.torque)); } + +void createTestMsg(gps_msgs::msg::GPSFix & _msg) +{ + std_msgs::msg::Header header_msg; + createTestMsg(header_msg); + + _msg.header = header_msg; + _msg.status.status = gps_msgs::msg::GPSStatus::STATUS_GBAS_FIX; + _msg.latitude = 0.00; + _msg.longitude = 0.00; + _msg.altitude = 0.00; + _msg.position_covariance = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + _msg.position_covariance_type = gps_msgs::msg::GPSFix::COVARIANCE_TYPE_UNKNOWN; +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + gps_msgs::msg::GPSFix expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(_msg->header); + EXPECT_EQ(expected_msg.status, _msg->status); + EXPECT_FLOAT_EQ(expected_msg.latitude, _msg->latitude); + EXPECT_FLOAT_EQ(expected_msg.longitude, _msg->longitude); + EXPECT_FLOAT_EQ(expected_msg.altitude, _msg->altitude); + EXPECT_EQ(expected_msg.position_covariance_type, _msg->position_covariance_type); + + for (auto i = 0u; i < 9; ++i) { + EXPECT_FLOAT_EQ(0, _msg->position_covariance[i]); + } +} + void createTestMsg(ros_gz_interfaces::msg::Light & _msg) { createTestMsg(_msg.header); @@ -559,6 +622,34 @@ void compareTestMsg(const std::shared_ptr & _msg) EXPECT_FLOAT_EQ(expected_msg.intensity, _msg->intensity); } +void createTestMsg(ros_gz_interfaces::msg::MaterialColor & _msg) +{ + createTestMsg(_msg.header); + createTestMsg(_msg.entity); + createTestMsg(_msg.ambient); + createTestMsg(_msg.diffuse); + createTestMsg(_msg.specular); + createTestMsg(_msg.emissive); + _msg.shininess = 1.0; + _msg.entity_match = ros_gz_interfaces::msg::MaterialColor::ALL; +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + ros_gz_interfaces::msg::MaterialColor expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(_msg->header); + compareTestMsg(std::make_shared(_msg->entity)); + compareTestMsg(std::make_shared(_msg->ambient)); + compareTestMsg(std::make_shared(_msg->diffuse)); + compareTestMsg(std::make_shared(_msg->specular)); + compareTestMsg(std::make_shared(_msg->emissive)); + + EXPECT_EQ(expected_msg.shininess, _msg->shininess); + EXPECT_EQ(expected_msg.entity_match, _msg->entity_match); +} + void createTestMsg(ros_gz_interfaces::msg::GuiCamera & _msg) { createTestMsg(_msg.header); @@ -776,6 +867,23 @@ void compareTestMsg(const std::shared_ptr & _msg EXPECT_EQ(expected_msg.type, _msg->type); } +void createTestMsg(ros_gz_interfaces::msg::EntityWrench & _msg) +{ + createTestMsg(_msg.header); + createTestMsg(_msg.entity); + createTestMsg(_msg.wrench); +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + ros_gz_interfaces::msg::EntityWrench expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(std::make_shared(_msg->header)); + compareTestMsg(std::make_shared(_msg->entity)); + compareTestMsg(std::make_shared(_msg->wrench)); +} + void createTestMsg(ros_gz_interfaces::msg::Contact & _msg) { createTestMsg(_msg.collision1); @@ -837,7 +945,6 @@ void compareTestMsg(const std::shared_ptr & _m } } -#if HAVE_DATAFRAME void createTestMsg(ros_gz_interfaces::msg::Dataframe & _msg) { createTestMsg(_msg.header); @@ -863,7 +970,6 @@ void compareTestMsg(const std::shared_ptr & _ EXPECT_EQ(expected_msg.data[ii], _msg->data[ii]); } } -#endif // HAVE_DATAFRAME void createTestMsg(nav_msgs::msg::Odometry & _msg) { @@ -1022,6 +1128,11 @@ void createTestMsg(sensor_msgs::msg::Imu & _msg) _msg.orientation = quaternion_msg; _msg.angular_velocity = vector3_msg; _msg.linear_acceleration = vector3_msg; +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + _msg.orientation_covariance = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + _msg.angular_velocity_covariance = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + _msg.linear_acceleration_covariance = {1, 2, 3, 4, 5, 6, 7, 8, 9}; +#endif } void compareTestMsg(const std::shared_ptr & _msg) @@ -1030,6 +1141,14 @@ void compareTestMsg(const std::shared_ptr & _msg) compareTestMsg(_msg->orientation); compareTestMsg(std::make_shared(_msg->angular_velocity)); compareTestMsg(std::make_shared(_msg->linear_acceleration)); + +#ifdef GZ_MSGS_IMU_HAS_COVARIANCE + for (int i = 0; i < 9; ++i) { + EXPECT_EQ(_msg->orientation_covariance[i], i + 1); + EXPECT_EQ(_msg->angular_velocity_covariance[i], i + 1); + EXPECT_EQ(_msg->linear_acceleration_covariance[i], i + 1); + } +#endif } void createTestMsg(sensor_msgs::msg::JointState & _msg) @@ -1415,5 +1534,76 @@ void compareTestMsg(const std::shared_ptr & } } +void createTestMsg(vision_msgs::msg::Detection3D & _msg) +{ + std_msgs::msg::Header header_msg; + createTestMsg(header_msg); + _msg.header = header_msg; + + vision_msgs::msg::ObjectHypothesisWithPose class_prob; + class_prob.hypothesis.class_id = "1"; + class_prob.hypothesis.score = 1.0; + _msg.results.push_back(class_prob); + + _msg.bbox.size.x = 3.0; + _msg.bbox.size.y = 5.0; + _msg.bbox.size.z = 7.0; + _msg.bbox.center.position.x = 2.0; + _msg.bbox.center.position.y = 4.0; + _msg.bbox.center.position.z = 6.0; + _msg.bbox.center.orientation.x = 0.733; + _msg.bbox.center.orientation.y = 0.462; + _msg.bbox.center.orientation.z = 0.191; + _msg.bbox.center.orientation.w = 0.462; +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + vision_msgs::msg::Detection3D expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(_msg->header); + EXPECT_EQ(expected_msg.results.size(), _msg->results.size()); + for (size_t i = 0; i < _msg->results.size(); i++) { + EXPECT_EQ(expected_msg.results[i].hypothesis.class_id, _msg->results[i].hypothesis.class_id); + EXPECT_EQ(expected_msg.results[i].hypothesis.score, _msg->results[i].hypothesis.score); + } + EXPECT_EQ(expected_msg.bbox.size.x, _msg->bbox.size.x); + EXPECT_EQ(expected_msg.bbox.size.y, _msg->bbox.size.y); + EXPECT_EQ(expected_msg.bbox.size.z, _msg->bbox.size.z); + EXPECT_EQ(expected_msg.bbox.center.position.x, _msg->bbox.center.position.x); + EXPECT_EQ(expected_msg.bbox.center.position.y, _msg->bbox.center.position.y); + EXPECT_EQ(expected_msg.bbox.center.position.z, _msg->bbox.center.position.z); + EXPECT_EQ(expected_msg.bbox.center.orientation.x, _msg->bbox.center.orientation.x); + EXPECT_EQ(expected_msg.bbox.center.orientation.y, _msg->bbox.center.orientation.y); + EXPECT_EQ(expected_msg.bbox.center.orientation.z, _msg->bbox.center.orientation.z); + EXPECT_EQ(expected_msg.bbox.center.orientation.w, _msg->bbox.center.orientation.w); +} + +void createTestMsg(vision_msgs::msg::Detection3DArray & _msg) +{ + std_msgs::msg::Header header_msg; + createTestMsg(header_msg); + _msg.header = header_msg; + + for (size_t i = 0; i < 4; i++) { + vision_msgs::msg::Detection3D detection; + createTestMsg(detection); + _msg.detections.push_back(detection); + } +} + +void compareTestMsg(const std::shared_ptr & _msg) +{ + vision_msgs::msg::Detection3DArray expected_msg; + createTestMsg(expected_msg); + + compareTestMsg(_msg->header); + EXPECT_EQ(expected_msg.detections.size(), _msg->detections.size()); + for (size_t i = 0; i < _msg->detections.size(); i++) { + compareTestMsg(std::make_shared(_msg->detections[i])); + } +} + } // namespace testing } // namespace ros_gz_bridge diff --git a/ros_gz_bridge/test/utils/ros_test_msg.hpp b/ros_gz_bridge/test/utils/ros_test_msg.hpp index d1e6caf2..68211305 100644 --- a/ros_gz_bridge/test/utils/ros_test_msg.hpp +++ b/ros_gz_bridge/test/utils/ros_test_msg.hpp @@ -34,28 +34,31 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include +#include #include #include #include #include #include -#if HAVE_DATAFRAME #include -#endif // HAVE_DATAFRAME #include +#include #include #include #include @@ -78,6 +81,7 @@ #include #include #include "vision_msgs/msg/detection2_d_array.hpp" +#include "vision_msgs/msg/detection3_d_array.hpp" namespace ros_gz_bridge { @@ -262,6 +266,18 @@ void createTestMsg(geometry_msgs::msg::PoseWithCovariance & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const geometry_msgs::msg::PoseWithCovarianceStamped & _msg); + +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(geometry_msgs::msg::PoseWithCovarianceStamped & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(geometry_msgs::msg::PoseStamped & _msg); @@ -314,6 +330,14 @@ void createTestMsg(geometry_msgs::msg::TwistWithCovariance & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(geometry_msgs::msg::TwistWithCovarianceStamped & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(geometry_msgs::msg::Wrench & _msg); @@ -330,6 +354,16 @@ void createTestMsg(geometry_msgs::msg::WrenchStamped & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// gps_msgs + +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(gps_msgs::msg::GPSFix & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// tf2_msgs /// \brief Create a message used for testing. @@ -376,6 +410,14 @@ void createTestMsg(ros_gz_interfaces::msg::Light & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(ros_gz_interfaces::msg::MaterialColor & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(ros_gz_interfaces::msg::Entity & _msg); @@ -384,6 +426,14 @@ void createTestMsg(ros_gz_interfaces::msg::Entity & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(ros_gz_interfaces::msg::EntityWrench & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(ros_gz_interfaces::msg::Contact & _msg); @@ -400,7 +450,6 @@ void createTestMsg(ros_gz_interfaces::msg::Contacts & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); -#if HAVE_DATAFRAME /// \brief Create a message used for testing. /// \param[out] _msg The message populated. void createTestMsg(ros_gz_interfaces::msg::Dataframe & _msg); @@ -408,7 +457,6 @@ void createTestMsg(ros_gz_interfaces::msg::Dataframe & _msg); /// \brief Compare a message with the populated for testing. /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); -#endif // HAVE_DATAFRAME /// \brief Create a message used for testing. /// \param[out] _msg The message populated. @@ -598,6 +646,22 @@ void createTestMsg(vision_msgs::msg::Detection2D & _msg); /// \param[in] _msg The message to compare. void compareTestMsg(const std::shared_ptr & _msg); +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(vision_msgs::msg::Detection3DArray & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + +/// \brief Create a message used for testing. +/// \param[out] _msg The message populated. +void createTestMsg(vision_msgs::msg::Detection3D & _msg); + +/// \brief Compare a message with the populated for testing. +/// \param[in] _msg The message to compare. +void compareTestMsg(const std::shared_ptr & _msg); + } // namespace testing } // namespace ros_gz_bridge diff --git a/ros_gz_image/CHANGELOG.rst b/ros_gz_image/CHANGELOG.rst index 3a3b593c..a574419f 100644 --- a/ros_gz_image/CHANGELOG.rst +++ b/ros_gz_image/CHANGELOG.rst @@ -2,14 +2,93 @@ Changelog for package ros1_ign_image ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- -* Add support for Harmonic/Humble pairing (`#462 `_) -* Fix double wait in ros_gz_bridge (`#347 `_) (`#450 `_) +2.0.0 (2024-07-22) +------------------ + +1.0.1 (2024-07-03) +------------------ +* Merge pull request `#571 `_ from azeey/jazzy_to_ros2 + Merge jazzy ➡️ ros2 +* Merge jazzy into ros2 +* Merge pull request `#569 `_ from azeey/iron_to_jazzy + Merge iron ➡️ jazzy +* Merge iron into jazzy +* Prepare for 1.0.0 Release (`#495 `_) +* Use gz_vendor packages (`#531 `_) +* 0.244.14 +* Changelog +* ign to gz (`#519 `_) +* 0.244.13 +* Changelog +* 0.244.12 +* Changelog +* 0.246.0 +* Update changelogs +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Fix linter error by reordering headers (`#373 `_) +* Add QoS profile parameter to image bridge (`#335 `_) +* Fix double wait in ros_gz_bridge (`#347 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Jose Luis Rivero, Michael Carroll, Sebastian Castro, ahcorde, ymd-stella + +1.0.0 (2024-04-24) +------------------ +* Use gz_vendor packages (`#531 `_) +* ign to gz (`#519 `_) * Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero -0.244.11 (2023-05-23) ---------------------- +0.246.0 (2023-08-31) +-------------------- +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* Update maintainers (`#376 `_) +* Fix linter error by reordering headers (`#373 `_) +* Add QoS profile parameter to image bridge (`#335 `_) +* Fix double wait in ros_gz_bridge (`#347 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Michael Carroll, Sebastian Castro, ahcorde, ymd-stella + +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Alejandro Hernández Cordero, Michael Carroll, ahcorde + 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz_image/CMakeLists.txt b/ros_gz_image/CMakeLists.txt index 545b0b27..e6e8de26 100644 --- a/ros_gz_image/CMakeLists.txt +++ b/ros_gz_image/CMakeLists.txt @@ -16,55 +16,11 @@ find_package(ros_gz_bridge REQUIRED) find_package(rclcpp REQUIRED) find_package(sensor_msgs REQUIRED) -# TODO(CH3): Deprecated. Remove on tock. -if("$ENV{GZ_VERSION}" STREQUAL "" AND NOT "$ENV{IGNITION_VERSION}" STREQUAL "") - message(DEPRECATION "Environment variable [IGNITION_VERSION] is deprecated. Use [GZ_VERSION] instead.") - set(ENV{GZ_VERSION} $ENV{IGNITION_VERSION}) -endif() - -# Edifice -if("$ENV{GZ_VERSION}" STREQUAL "edifice") - find_package(ignition-transport10 REQUIRED) - set(GZ_TRANSPORT_VER ${ignition-transport10_VERSION_MAJOR}) - - find_package(ignition-msgs7 REQUIRED) - set(GZ_MSGS_VER ${ignition-msgs7_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX ignition) - - message(STATUS "Compiling against Ignition Edifice") -# Fortress -elseif("$ENV{GZ_VERSION}" STREQUAL "garden") - find_package(gz-transport12 REQUIRED) - set(GZ_TRANSPORT_VER ${gz-transport12_VERSION_MAJOR}) - - find_package(gz-msgs9 REQUIRED) - set(GZ_MSGS_VER ${gz-msgs9_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX gz) +find_package(gz_transport_vendor REQUIRED) +find_package(gz-transport REQUIRED) - message(STATUS "Compiling against Gazebo Garden") -elseif("$ENV{GZ_VERSION}" STREQUAL "harmonic") - find_package(gz-transport13 REQUIRED) - find_package(gz-msgs10 REQUIRED) - - set(GZ_TARGET_PREFIX gz) - set(GZ_MSGS_VER ${gz-msgs10_VERSION_MAJOR}) - set(GZ_TRANSPORT_VER ${gz-transport13_VERSION_MAJOR}) - - message(STATUS "Compiling against Gazebo Harmonic") -# Default to Fortress -else() - find_package(ignition-transport11 REQUIRED) - set(GZ_TRANSPORT_VER ${ignition-transport11_VERSION_MAJOR}) - - find_package(ignition-msgs8 REQUIRED) - set(GZ_MSGS_VER ${ignition-msgs8_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX ignition) - - message(STATUS "Compiling against Ignition Fortress") -endif() +find_package(gz_msgs_vendor REQUIRED) +find_package(gz-msgs REQUIRED) include_directories(include) @@ -77,8 +33,8 @@ add_executable(${executable} ) target_link_libraries(${executable} - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + gz-msgs::core + gz-transport::core ) ament_target_dependencies(${executable} @@ -112,8 +68,8 @@ if(BUILD_TESTING) # ) # target_link_libraries(${test_publisher}_image # ${catkin_LIBRARIES} - # ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - # ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + # $gz-msgs$::core + # $gz-transport::core # gtest # gtest_main # ) @@ -125,8 +81,8 @@ if(BUILD_TESTING) # test/subscribers/${test_subscriber}.cpp) # target_link_libraries(test_${test_subscriber}_image # ${catkin_LIBRARIES} - # ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - # ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + # $gz-msgs::core + # $gz-transport::core # ) # endforeach(test_subscriber) endif() diff --git a/ros_gz_image/README.md b/ros_gz_image/README.md index b7b27e1f..a6c9c5e5 100644 --- a/ros_gz_image/README.md +++ b/ros_gz_image/README.md @@ -1,7 +1,7 @@ # Image utilities for using ROS and Gazebo Transport This package provides a unidirectional bridge for images from Gazebo to ROS. -The bridge subscribes to Gazebo image messages (`ignition::msgs::Image`) +The bridge subscribes to Gazebo image messages (`gz::msgs::Image`) and republishes them to ROS using [image_transport](http://wiki.ros.org/image_transport). For compressed images, install @@ -9,3 +9,14 @@ For compressed images, install and the bridge will publish `/compressed` images. The same goes for other `image_transport` plugins. +To run the bridge from the command line: + +```shell +ros2 run ros_gz_image image_bridge /topic1 /topic2 +``` + +You can also modify the [Quality of Service (QoS) policy](https://docs.ros.org/en/rolling/Concepts/About-Quality-of-Service-Settings.html#qos-policies) used to publish images using an additional `qos` ROS parameter. For example: + +```shell +ros2 run ros_gz_image image_bridge /topic1 /topic2 --ros-args qos:=sensor_data +``` diff --git a/ros_gz_image/package.xml b/ros_gz_image/package.xml index 12bd3f94..794826b1 100644 --- a/ros_gz_image/package.xml +++ b/ros_gz_image/package.xml @@ -1,9 +1,12 @@ ros_gz_image - 0.244.12 + 2.0.0 Image utilities for Gazebo simulation with ROS. Apache 2.0 - Louise Poubel + Aditya Pande + Alejandro Hernandez + + Louise Poubel ament_cmake pkg-config @@ -13,20 +16,8 @@ rclcpp sensor_msgs - - gz-msgs10 - gz-transport13 - - gz-msgs9 - gz-transport12 - - ignition-msgs8 - ignition-transport11 - ignition-msgs8 - ignition-transport11 - - ignition-msgs7 - ignition-transport10 + gz_msgs_vendor + gz_transport_vendor ament_lint_auto ament_lint_common diff --git a/ros_gz_image/src/image_bridge.cpp b/ros_gz_image/src/image_bridge.cpp index c167c67c..db21f42c 100644 --- a/ros_gz_image/src/image_bridge.cpp +++ b/ros_gz_image/src/image_bridge.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include @@ -19,25 +20,42 @@ #include #include -#include #include +#include #include ////////////////////////////////////////////////// -/// \brief Bridges one topic +/// \brief Bridges one image topic class Handler { public: /// \brief Constructor /// \param[in] _topic Image base topic - /// \param[in] _it_node Pointer to image transport node + /// \param[in] _node Pointer to ROS node /// \param[in] _gz_node Pointer to Gazebo node Handler( const std::string & _topic, - std::shared_ptr _it_node, + std::shared_ptr _node, std::shared_ptr _gz_node) { - this->ros_pub = _it_node->advertise(_topic, 1); + // Get QoS profile from parameter + rmw_qos_profile_t qos_profile = rmw_qos_profile_default; + const auto qos_str = + _node->get_parameter("qos").get_parameter_value().get(); + if (qos_str == "system_default") { + qos_profile = rmw_qos_profile_system_default; + } else if (qos_str == "sensor_data") { + qos_profile = rmw_qos_profile_sensor_data; + } else if (qos_str != "default") { + RCLCPP_ERROR( + _node->get_logger(), + "Invalid QoS profile %s specified. Using default profile.", + qos_str.c_str()); + } + + // Create publishers and subscribers + this->ros_pub = image_transport::create_publisher( + _node.get(), _topic, qos_profile); _gz_node->Subscribe(_topic, &Handler::OnImage, this); } @@ -77,7 +95,7 @@ int main(int argc, char * argv[]) // ROS node auto node_ = rclcpp::Node::make_shared("ros_gz_image"); - auto it_node = std::make_shared(node_); + node_->declare_parameter("qos", "default"); // Gazebo node auto gz_node = std::make_shared(); @@ -91,7 +109,7 @@ int main(int argc, char * argv[]) // Create publishers and subscribers for (auto topic : args) { - handlers.push_back(std::make_shared(topic, it_node, gz_node)); + handlers.push_back(std::make_shared(topic, node_, gz_node)); } // Spin ROS and Gz until shutdown diff --git a/ros_gz_interfaces/CHANGELOG.rst b/ros_gz_interfaces/CHANGELOG.rst index a58b27cf..68e65c99 100644 --- a/ros_gz_interfaces/CHANGELOG.rst +++ b/ros_gz_interfaces/CHANGELOG.rst @@ -2,14 +2,77 @@ Changelog for package ros_gz_interfaces ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- -* [backport humble] SensorNoise msg bridging (`#417 `_) -* [backport humble] Added Altimeter msg bridging (`#413 `_) (`#414 `_) (`#426 `_) -* Contributors: Alejandro Hernández Cordero +2.0.0 (2024-07-22) +------------------ + +1.0.1 (2024-07-03) +------------------ +* Add support for gz.msgs.EntityWrench (base branch: ros2) (`#573 `_) +* Add option to change material color from ROS. (`#521 `_) + Forward port of `#486 `_. + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. + (cherry picked from commit 78dc4823121f085594e6028a93f1e571eb04f58b) +* Add option to change material color from ROS. (`#521 `_) + Forward port of `#486 `_. + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. +* Prepare for 1.0.0 Release (`#495 `_) +* 0.244.14 +* Changelog +* Add option to change material color from ROS. (`#486 `_) + * Message and bridge for MaterialColor. + This allows bridging MaterialColor from ROS to GZ and is + important for allowing simulation users to create status lights. + --------- + Co-authored-by: Alejandro Hernández Cordero + Co-authored-by: Addisu Z. Taddese + Co-authored-by: Addisu Z. Taddese +* 0.244.13 +* Changelog +* 0.244.12 +* Changelog +* 0.246.0 +* Update changelogs +* SensorNoise msg bridging (`#417 `_) +* Added Altimeter msg bridging (`#413 `_) +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* Export rcl_interfaces exec dependency (`#317 `_) +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Benjamin Perseghetti, Jose Luis Rivero, Michael Carroll, Victor T. Noppeney, ahcorde + +1.0.0 (2024-04-24) +------------------ + +0.246.0 (2023-08-31) +-------------------- +* SensorNoise msg bridging (`#417 `_) +* Added Altimeter msg bridging (`#413 `_) +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Export rcl_interfaces exec dependency (`#317 `_) +* Contributors: Aditya Pande, Alejandro Hernández Cordero, Michael Carroll, ahcorde + +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Contributors: Alejandro Hernández Cordero, ahcorde -0.244.11 (2023-05-23) ---------------------- 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz_interfaces/CMakeLists.txt b/ros_gz_interfaces/CMakeLists.txt index 49c49126..9f3d7a1f 100644 --- a/ros_gz_interfaces/CMakeLists.txt +++ b/ros_gz_interfaces/CMakeLists.txt @@ -23,10 +23,12 @@ set(msg_files "msg/Dataframe.msg" "msg/Entity.msg" "msg/EntityFactory.msg" + "msg/EntityWrench.msg" "msg/Float32Array.msg" "msg/GuiCamera.msg" "msg/JointWrench.msg" "msg/Light.msg" + "msg/MaterialColor.msg" "msg/ParamVec.msg" "msg/SensorNoise.msg" "msg/StringVec.msg" diff --git a/ros_gz_interfaces/README.md b/ros_gz_interfaces/README.md index 88ed27d7..610cb7e3 100644 --- a/ros_gz_interfaces/README.md +++ b/ros_gz_interfaces/README.md @@ -8,6 +8,7 @@ This package currently contains some Gazebo-specific ROS message and service dat * [Contacts](msg/Contacts.msg): related to [ignition::msgs::Contacts](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/contacts.proto). A list of contacts. * [Entity](msg/Entity.msg): related to [ignition::msgs::Entity](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/entity.proto). Entity of Gazebo Sim. * [EntityFactory](msg/EntityFactory.msg): related to [ignition::msgs::EntityFactory](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/entity_factory.proto). Message to create a new entity. +* [EntityWrench](msg/EntityWrench.msg): related to [ignition::msgs::EntityWrench](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/gz/msgs/entity_wrench.proto). Wrench to be applied to a specified Entity of Gazebo Sim. * [Light](msg/Light.msg): related to [ignition::msgs::Light](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/light.proto). Light info in Gazebo Sim. * [WorldControl](msg/WorldControl.msg): related to [ignition::msgs::WorldControl](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/world_control.proto). Message to control world of Gazebo Sim. * [WorldReset](msg/WorldReset.msg): related to [ignition::msgs::WorldReset](https://github.com/gazebosim/gz-msgs/blob/ign-msgs7/proto/ignition/msgs/world_reset.proto). Reset time and model of simulation. diff --git a/ros_gz_interfaces/msg/EntityWrench.msg b/ros_gz_interfaces/msg/EntityWrench.msg new file mode 100644 index 00000000..c1a03987 --- /dev/null +++ b/ros_gz_interfaces/msg/EntityWrench.msg @@ -0,0 +1,3 @@ +std_msgs/Header header # Time stamp +ros_gz_interfaces/Entity entity # Entity +geometry_msgs/Wrench wrench # Wrench to be applied to entity \ No newline at end of file diff --git a/ros_gz_interfaces/msg/MaterialColor.msg b/ros_gz_interfaces/msg/MaterialColor.msg new file mode 100644 index 00000000..cda67d27 --- /dev/null +++ b/ros_gz_interfaces/msg/MaterialColor.msg @@ -0,0 +1,12 @@ +# Entities that match to apply material color: constant definition +uint8 FIRST = 0 +uint8 ALL = 1 + +std_msgs/Header header # Optional header data +ros_gz_interfaces/Entity entity # Entity to change material color +std_msgs/ColorRGBA ambient # Ambient color +std_msgs/ColorRGBA diffuse # Diffuse color +std_msgs/ColorRGBA specular # Specular color +std_msgs/ColorRGBA emissive # Emissive color +float64 shininess # Specular exponent +uint8 entity_match # Entities that match to apply material color diff --git a/ros_gz_interfaces/package.xml b/ros_gz_interfaces/package.xml index ba558aa2..56c49ffa 100644 --- a/ros_gz_interfaces/package.xml +++ b/ros_gz_interfaces/package.xml @@ -1,10 +1,12 @@ ros_gz_interfaces - 0.244.12 + 2.0.0 Message and service data structures for interacting with Gazebo from ROS2. Apache 2.0 - Louise Poubel + Louise Poubel Zhenpeng Ge + Aditya Pande + Alejandro Hernandez ament_cmake rosidl_default_generators diff --git a/ros_gz_point_cloud/examples/depth_camera.sdf b/ros_gz_point_cloud/examples/depth_camera.sdf index 574d0ce4..85beba43 100644 --- a/ros_gz_point_cloud/examples/depth_camera.sdf +++ b/ros_gz_point_cloud/examples/depth_camera.sdf @@ -15,7 +15,7 @@ 3. Load the example world, unpaused: - ign gazebo -r examples/depth_camera.sdf + gz sim -r examples/depth_camera.sdf 4. Launch RViz to visualize the point cloud: diff --git a/ros_gz_point_cloud/examples/gpu_lidar.sdf b/ros_gz_point_cloud/examples/gpu_lidar.sdf index 7bd3a735..3feed57a 100644 --- a/ros_gz_point_cloud/examples/gpu_lidar.sdf +++ b/ros_gz_point_cloud/examples/gpu_lidar.sdf @@ -15,7 +15,7 @@ 3. Load this world, unpaused: - ign gazebo -r examples/gpu_lidar.sdf + gz sim -r examples/gpu_lidar.sdf 4. Launch RViz to visualize the point cloud: diff --git a/ros_gz_point_cloud/examples/rgbd_camera.sdf b/ros_gz_point_cloud/examples/rgbd_camera.sdf index 64a77b6a..235cb225 100644 --- a/ros_gz_point_cloud/examples/rgbd_camera.sdf +++ b/ros_gz_point_cloud/examples/rgbd_camera.sdf @@ -16,7 +16,7 @@ 3. Load the example world, unpaused: - ign gazebo -r examples/rgbd_camera.sdf + gz sim -r examples/rgbd_camera.sdf 4. Launch RViz to visualize the point cloud: diff --git a/ros_gz_point_cloud/package.xml b/ros_gz_point_cloud/package.xml index b3d5717e..9256c482 100644 --- a/ros_gz_point_cloud/package.xml +++ b/ros_gz_point_cloud/package.xml @@ -3,7 +3,10 @@ 0.7.0 Point cloud utilities for Gazebo simulation with ROS. Apache 2.0 - Louise Poubel + Aditya Pande + Alejandro Hernandez + + Louise Poubel catkin diff --git a/ros_gz_sim/CHANGELOG.rst b/ros_gz_sim/CHANGELOG.rst index 0351b1f8..87e32aa7 100644 --- a/ros_gz_sim/CHANGELOG.rst +++ b/ros_gz_sim/CHANGELOG.rst @@ -2,14 +2,140 @@ Changelog for package ros_gz_sim ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- -* Add support for Harmonic/Humble pairing (`#462 `_) -* Set on_exit_shutdown argument for gz-sim ExecuteProcess (`#355 `_) (`#451 `_) -* Contributors: Addisu Z. Taddese, Michael Carroll +2.0.0 (2024-07-22) +------------------ +* Making use_composition true by default (`#578 `_) +* Contributors: Addisu Z. Taddese + +1.0.1 (2024-07-03) +------------------ +* Merge pull request `#571 `_ from azeey/jazzy_to_ros2 + Merge jazzy ➡️ ros2 +* Merge jazzy into ros2 +* Merge pull request `#569 `_ from azeey/iron_to_jazzy + Merge iron ➡️ jazzy +* Merge remote-tracking branch 'origin/jazzy' into iron_to_jazzy +* Add a ROS node that runs Gazebo (`#500 `_) (`#567 `_) + * Add gzserver with ability to load an SDF file or string + --------- + (cherry picked from commit 92a2891f4adf35e4a4119aca2447dee93e22a06a) + Co-authored-by: Addisu Z. Taddese +* Merge iron into jazzy +* Merge pull request `#564 `_ from azeey/humble_to_iron + Humble ➡️ Iron +* Merge humble -> iron +* Update launch files with name parameter (`#556 `_) + * Name is required. +* Launch gz_spawn_model from xml (`#551 `_) + Spawn models from XML. + Co-authored-by: Addisu Z. Taddese +* Launch ros_gz_bridge from xml (`#550 `_) + * Add gzserver with ability to load an SDF file or string +* Launch gzserver and the bridge as composable nodes (`#528 `_) + * Add gzserver with ability to load an SDF file or string +* Add a ROS node that runs Gazebo (`#500 `_) + * Add gzserver with ability to load an SDF file or string + --------- +* Prepare for 1.0.0 Release (`#495 `_) +* Use gz_vendor packages (`#531 `_) +* 0.244.14 +* Changelog +* ign to gz (`#519 `_) +* Support `` in `package.xml` exports (`#492 `_) + This copies the implementation from `gazebo_ros_paths.py` to provide a + way for packages to set resource paths from `package.xml`. + ``` + e.g. + + + + ``` + The value of `gazebo_model_path` and `gazebo_media_path` is appended to `GZ_SIM_RESOURCE_PATH` + The value of `plugin_path` appended to `GZ_SIM_SYSTEM_PLUGIN_PATH` + --------- +* Undeprecate use of commandline flags (`#491 `_) +* 0.244.13 +* Changelog +* Remove deprecations using ros_gz_sim_create (`#476 `_) +* Added support for using ROS 2 parameters to spawn entities in Gazebo using ros_gz_sim::create (`#475 `_) +* Fix bug in `create` where command line arguments were truncated (`#472 `_) +* 0.244.12 +* Changelog +* Filter ROS arguments before gflags parsing (`#453 `_) +* 0.246.0 +* Update changelogs +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* Replace deprecated ign_find_package with gz_find_package (`#432 `_) + Co-authored-by: jmackay2 +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* set on_exit_shutdown argument for gz-sim ExecuteProcess (`#355 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Ayush Singh, Carlos Agüero, Jose Luis Rivero, Michael Carroll, ahcorde, andermi, jmackay2, mergify[bot] + +1.0.0 (2024-04-24) +------------------ +* Use gz_vendor packages (`#531 `_) +* ign to gz (`#519 `_) +* Undeprecate use of commandline flags (`#491 `_) +* Remove deprecations using ros_gz_sim_create (`#476 `_) +* Added support for using ROS 2 parameters to spawn entities in Gazebo using ros_gz_sim::create (`#475 `_) +* Fix bug in `create` where command line arguments were truncated (`#472 `_) +* Filter ROS arguments before gflags parsing (`#453 `_) +* Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero, Ayush Singh, Michael Carroll + +0.246.0 (2023-08-31) +-------------------- +* Add harmonic CI (`#447 `_) + * Add harmonic CI + * Include garden options + * Add harmonic stanza + * Additional message headers + --------- +* Replace deprecated ign_find_package with gz_find_package (`#432 `_) + Co-authored-by: jmackay2 +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* set on_exit_shutdown argument for gz-sim ExecuteProcess (`#355 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Aditya Pande, Alejandro Hernández Cordero, Michael Carroll, ahcorde, andermi, jmackay2 + +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Alejandro Hernández Cordero, Michael Carroll, ahcorde -0.244.11 (2023-05-23) ---------------------- 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz_sim/CMakeLists.txt b/ros_gz_sim/CMakeLists.txt index 29d2ea28..dc21f8a9 100644 --- a/ros_gz_sim/CMakeLists.txt +++ b/ros_gz_sim/CMakeLists.txt @@ -12,94 +12,31 @@ endif() find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) +find_package(rclcpp_components REQUIRED) find_package(std_msgs REQUIRED) -# TODO(CH3): Deprecated. Remove on tock. -if("$ENV{GZ_VERSION}" STREQUAL "" AND NOT "$ENV{IGNITION_VERSION}" STREQUAL "") - message(DEPRECATION "Environment variable [IGNITION_VERSION] is deprecated. Use [GZ_VERSION] instead.") - set(ENV{GZ_VERSION} $ENV{IGNITION_VERSION}) -endif() - -# Edifice -if("$ENV{GZ_VERSION}" STREQUAL "edifice") - find_package(ignition-math6 REQUIRED) - set(GZ_MATH_VER ${ignition-math6_VERSION_MAJOR}) - - find_package(ignition-transport10 REQUIRED) - set(GZ_TRANSPORT_VER ${ignition-transport10_VERSION_MAJOR}) - - find_package(ignition-msgs7 REQUIRED) - set(GZ_MSGS_VER ${ignition-msgs7_VERSION_MAJOR}) - - find_package(ignition-gazebo5 REQUIRED) - set(GZ_SIM_VER ${ignition-gazebo5_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX ignition) - macro(gz_find_package) - ign_find_package(${ARGV}) - endmacro() - - message(STATUS "Compiling against Gazebo Edifice") -# Garden -elseif("$ENV{GZ_VERSION}" STREQUAL "garden") - find_package(gz-math7 REQUIRED) - set(GZ_MATH_VER ${gz-math7_VERSION_MAJOR}) - - find_package(gz-transport12 REQUIRED) - set(GZ_TRANSPORT_VER ${gz-transport12_VERSION_MAJOR}) - - find_package(gz-msgs9 REQUIRED) - set(GZ_MSGS_VER ${gz-msgs9_VERSION_MAJOR}) - - find_package(gz-sim7 REQUIRED) - set(GZ_SIM_VER ${gz-sim7_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX gz) - - message(STATUS "Compiling against Gazebo Garden") -elseif("$ENV{GZ_VERSION}" STREQUAL "harmonic") - find_package(gz-math7 REQUIRED) - set(GZ_MATH_VER ${gz-math7_VERSION_MAJOR}) - - find_package(gz-transport13 REQUIRED) - set(GZ_TRANSPORT_VER ${gz-transport13_VERSION_MAJOR}) - - find_package(gz-msgs10 REQUIRED) - set(GZ_MSGS_VER ${gz-msgs10_VERSION_MAJOR}) - - find_package(gz-sim8 REQUIRED) - set(GZ_SIM_VER ${gz-sim8_VERSION_MAJOR}) - - set(GZ_TARGET_PREFIX gz) - - message(STATUS "Compiling against Gazebo Harmonic") -# Default to Fortress -else() - find_package(ignition-math6 REQUIRED) - set(GZ_MATH_VER ${ignition-math6_VERSION_MAJOR}) - - find_package(ignition-transport11 REQUIRED) - set(GZ_TRANSPORT_VER ${ignition-transport11_VERSION_MAJOR}) - - find_package(ignition-msgs8 REQUIRED) - set(GZ_MSGS_VER ${ignition-msgs8_VERSION_MAJOR}) +find_package(gz_math_vendor REQUIRED) +find_package(gz-math REQUIRED) - find_package(ignition-gazebo6 REQUIRED) - set(GZ_SIM_VER ${ignition-gazebo6_VERSION_MAJOR}) +find_package(gz_transport_vendor REQUIRED) +find_package(gz-transport REQUIRED) - set(GZ_TARGET_PREFIX ignition) +find_package(gz_msgs_vendor REQUIRED) +find_package(gz-msgs REQUIRED) - message(STATUS "Compiling against Gazebo Fortress") - macro(gz_find_package) - ign_find_package(${ARGV}) - endmacro() -endif() +find_package(gz_sim_vendor REQUIRED) +find_package(gz-sim REQUIRED) +# Needed in launch/gz_sim.launch.py.in +set(GZ_SIM_VER ${gz-sim_VERSION_MAJOR}) gz_find_package(gflags REQUIRED PKGCONFIG gflags) find_package(std_msgs REQUIRED) +# Install the python module for this package +ament_python_install_package(${PROJECT_NAME}) + add_executable(create src/create.cpp) ament_target_dependencies(create rclcpp @@ -107,9 +44,9 @@ ament_target_dependencies(create ) target_link_libraries(create gflags - ${GZ_TARGET_PREFIX}-math${GZ_MATH_VER}::core - ${GZ_TARGET_PREFIX}-msgs${GZ_MSGS_VER}::core - ${GZ_TARGET_PREFIX}-transport${GZ_TRANSPORT_VER}::core + gz-math::core + gz-msgs::core + gz-transport::core ) ament_target_dependencies(create std_msgs) @@ -127,6 +64,23 @@ install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION include/${PROJECT_NAME} ) +add_library(gzserver_component SHARED src/gzserver.cpp) +rclcpp_components_register_nodes(gzserver_component "ros_gz_sim::GzServer") +ament_target_dependencies(gzserver_component + rclcpp + rclcpp_components + std_msgs +) +target_link_libraries(gzserver_component + gz-sim::core +) +ament_target_dependencies(gzserver_component std_msgs) +rclcpp_components_register_node( + gzserver_component + PLUGIN "ros_gz_sim::GzServer" + EXECUTABLE gzserver +) + configure_file( launch/gz_sim.launch.py.in launch/gz_sim.launch.py.configured @@ -142,10 +96,33 @@ install(FILES DESTINATION share/${PROJECT_NAME}/launch ) +install(FILES + "launch/gz_server.launch" + "launch/gz_server.launch.py" + "launch/gz_spawn_model.launch" + "launch/gz_spawn_model.launch.py" + "launch/ros_gz_sim.launch" + "launch/ros_gz_sim.launch.py" + "launch/ros_gz_spawn_model.launch.py" + DESTINATION share/${PROJECT_NAME}/launch +) + install(TARGETS create DESTINATION lib/${PROJECT_NAME} ) +install(TARGETS + gzserver + DESTINATION lib/${PROJECT_NAME} +) + +ament_export_targets(export_gzserver_component) +install(TARGETS gzserver_component + EXPORT export_gzserver_component + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) install( TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME} @@ -164,11 +141,15 @@ if(BUILD_TESTING) # GTest find_package(ament_cmake_gtest REQUIRED) + find_package(launch_testing_ament_cmake REQUIRED) ament_find_gtest() ament_add_gtest_executable(test_stopwatch test/test_stopwatch.cpp ) + ament_add_gtest_executable(test_create + test/test_create.cpp + ) ament_target_dependencies(test_stopwatch rclcpp) @@ -180,12 +161,16 @@ if(BUILD_TESTING) target_link_libraries(test_stopwatch ${PROJECT_NAME} ) + target_link_libraries(test_create + gz-transport::core + ) install( - TARGETS test_stopwatch + TARGETS test_stopwatch test_create DESTINATION lib/${PROJECT_NAME} ) ament_add_gtest_test(test_stopwatch) + add_launch_test(test/test_create_node.launch.py TIMEOUT 200) endif() ament_package() diff --git a/ros_gz_sim/README.md b/ros_gz_sim/README.md index c4561a5d..cf4e8ca9 100644 --- a/ros_gz_sim/README.md +++ b/ros_gz_sim/README.md @@ -29,7 +29,7 @@ ros2 launch ros_gz_sim gz_sim.launch.py then spawn a model: ``` -ros2 run ros_gz_sim create -world default -file 'https://fuel.ignitionrobotics.org/1.0/openrobotics/models/Gazebo' +ros2 run ros_gz_sim create -world default -file 'https://fuel.gazebosim.org/1.0/openrobotics/models/Gazebo' ``` See more options with: @@ -37,3 +37,77 @@ See more options with: ``` ros2 run ros_gz_sim create --helpshort ``` + +### Using `` to export model paths in `package.xml` + +The `` tag inside the `` tag of a `package.xml` file can be +used to add paths to `GZ_SIM_RESOURCE_PATH` and `GZ_SIM_SYSTEM_PLUGIN_PATH`, +which are environment variables used to configure Gazebo search paths for +resources (e.g. SDFormat files, meshes, etc) and plugins respectively. + +The values in the attributes `gazebo_model_path` and `gazebo_media_path` are +appended to `GZ_SIM_RESOURCE_PATH`. The value of `plugin_path` is appended to +`GZ_SIM_SYSTEM_PLUGIN_PATH`. See the +[Finding resources](https://gazebosim.org/api/sim/8/resources.html) tutorial to +learn more about these environment variables. + +The keyword `${prefix}` can be used when setting these values and it will be +expanded to the package's share path (i.e., the value of +`ros2 pkg prefix --share `) + +```xml + + + + + + +``` + +Thus the required directory needs to be installed from `CMakeLists.txt` + +```cmake +install(DIRECTORY models + DESTINATION share/${PROJECT_NAME}) +``` + +In order to reference the models in a ROS package unambiguously, it is +recommended to set the value of `gazebo_model_path` to be the parent +of the `prefix`. + +```xml + + + + +``` + +Consider an example where we have a ROS package called `my_awesome_pkg` +and it contains an SDFormat model cool `cool_robot`: + +```bash +my_awesome_pkg +├── models +│   └── cool_robot +│   ├── model.config +│   └── model.sdf +└── package.xml +``` + +With `gazebo_model_path="${prefix}/../` set up, we can +reference the `cool_robot` model in a world file using the package name +in the `uri`: + +```xml + + + + package://my_awesome_pkg/models/cool_robot + + + +``` + +However, if we set `gazebo_model_path=${prefix}/models`, we would +need to reference `cool_robot` as `package://cool_robot`, which +might have a name conflict with other models in the system. diff --git a/ros_gz_sim/launch/gz_server.launch b/ros_gz_sim/launch/gz_server.launch new file mode 100644 index 00000000..4d667434 --- /dev/null +++ b/ros_gz_sim/launch/gz_server.launch @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/ros_gz_sim/launch/gz_server.launch.py b/ros_gz_sim/launch/gz_server.launch.py new file mode 100644 index 00000000..0dc33d9c --- /dev/null +++ b/ros_gz_sim/launch/gz_server.launch.py @@ -0,0 +1,80 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Launch gz_server in a component container.""" + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration, PythonExpression, TextSubstitution +from launch_ros.actions import ComposableNodeContainer, Node +from launch_ros.descriptions import ComposableNode + + +def generate_launch_description(): + + declare_world_sdf_file_cmd = DeclareLaunchArgument( + 'world_sdf_file', default_value=TextSubstitution(text=''), + description='Path to the SDF world file') + declare_world_sdf_string_cmd = DeclareLaunchArgument( + 'world_sdf_string', default_value=TextSubstitution(text=''), + description='SDF world string') + declare_container_name_cmd = DeclareLaunchArgument( + 'container_name', default_value='ros_gz_container', + description='Name of container that nodes will load in if use composition',) + declare_use_composition_cmd = DeclareLaunchArgument( + 'use_composition', default_value='True', + description='Use composed bringup if True') + + load_nodes = Node( + condition=IfCondition(PythonExpression(['not ', LaunchConfiguration('use_composition')])), + package='ros_gz_sim', + executable='gzserver', + output='screen', + parameters=[{'world_sdf_file': LaunchConfiguration('world_sdf_file'), + 'world_sdf_string': LaunchConfiguration('world_sdf_string')}], + ) + + load_composable_nodes = ComposableNodeContainer( + condition=IfCondition(LaunchConfiguration('use_composition')), + name=LaunchConfiguration('container_name'), + namespace='', + package='rclcpp_components', + executable='component_container', + composable_node_descriptions=[ + ComposableNode( + package='ros_gz_sim', + plugin='ros_gz_sim::GzServer', + name='gz_server', + parameters=[{'world_sdf_file': LaunchConfiguration('world_sdf_file'), + 'world_sdf_string': LaunchConfiguration('world_sdf_string')}], + extra_arguments=[{'use_intra_process_comms': True}], + ), + ], + output='screen', + ) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_world_sdf_file_cmd) + ld.add_action(declare_world_sdf_string_cmd) + ld.add_action(declare_container_name_cmd) + ld.add_action(declare_use_composition_cmd) + # Add the actions to launch all of the gz_server nodes + ld.add_action(load_nodes) + ld.add_action(load_composable_nodes) + + return ld diff --git a/ros_gz_sim/launch/gz_sim.launch.py.in b/ros_gz_sim/launch/gz_sim.launch.py.in index 7bed5243..d41bede6 100644 --- a/ros_gz_sim/launch/gz_sim.launch.py.in +++ b/ros_gz_sim/launch/gz_sim.launch.py.in @@ -14,20 +14,86 @@ """Launch Gazebo Sim with command line arguments.""" +import os from os import environ +from ament_index_python.packages import get_package_share_directory +from catkin_pkg.package import InvalidPackage, PACKAGE_MANIFEST_FILENAME, parse_package +from ros2pkg.api import get_package_names from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, OpaqueFunction from launch.actions import ExecuteProcess, Shutdown from launch.substitutions import LaunchConfiguration +# Copied from https://github.com/ros-simulation/gazebo_ros_pkgs/blob/79fd94c6da76781a91499bc0f54b70560b90a9d2/gazebo_ros/scripts/gazebo_ros_paths.py +""" +Search for model, plugin and media paths exported by packages. + +e.g. + + + +${prefix} is replaced by package's share directory in install. + +Thus the required directory needs to be installed from CMakeLists.txt +e.g. install(DIRECTORY models + DESTINATION share/${PROJECT_NAME}) +""" + +class GazeboRosPaths: + + @staticmethod + def get_paths(): + gazebo_model_path = [] + gazebo_plugin_path = [] + gazebo_media_path = [] + + for package_name in get_package_names(): + package_share_path = get_package_share_directory(package_name) + package_file_path = os.path.join(package_share_path, PACKAGE_MANIFEST_FILENAME) + if os.path.isfile(package_file_path): + try: + package = parse_package(package_file_path) + except InvalidPackage: + continue + for export in package.exports: + if export.tagname == 'gazebo_ros': + if 'gazebo_model_path' in export.attributes: + xml_path = export.attributes['gazebo_model_path'] + xml_path = xml_path.replace('${prefix}', package_share_path) + gazebo_model_path.append(xml_path) + if 'plugin_path' in export.attributes: + xml_path = export.attributes['plugin_path'] + xml_path = xml_path.replace('${prefix}', package_share_path) + gazebo_plugin_path.append(xml_path) + if 'gazebo_media_path' in export.attributes: + xml_path = export.attributes['gazebo_media_path'] + xml_path = xml_path.replace('${prefix}', package_share_path) + gazebo_media_path.append(xml_path) + + gazebo_model_path = os.pathsep.join(gazebo_model_path + gazebo_media_path) + gazebo_plugin_path = os.pathsep.join(gazebo_plugin_path) + + return gazebo_model_path, gazebo_plugin_path + def launch_gz(context, *args, **kwargs): - env = {'GZ_SIM_SYSTEM_PLUGIN_PATH': - ':'.join([environ.get('GZ_SIM_SYSTEM_PLUGIN_PATH', default=''), - environ.get('LD_LIBRARY_PATH', default='')]), - 'IGN_GAZEBO_SYSTEM_PLUGIN_PATH': # TODO(CH3): To support pre-garden. Deprecated. - ':'.join([environ.get('IGN_GAZEBO_SYSTEM_PLUGIN_PATH', default=''), - environ.get('LD_LIBRARY_PATH', default='')])} + model_paths, plugin_paths = GazeboRosPaths.get_paths() + + env = { + "GZ_SIM_SYSTEM_PLUGIN_PATH": os.pathsep.join( + [ + environ.get("GZ_SIM_SYSTEM_PLUGIN_PATH", default=""), + environ.get("LD_LIBRARY_PATH", default=""), + plugin_paths, + ] + ), + "GZ_SIM_RESOURCE_PATH": os.pathsep.join( + [ + environ.get("GZ_SIM_RESOURCE_PATH", default=""), + model_paths, + ] + ), + } gz_args = LaunchConfiguration('gz_args').perform(context) gz_version = LaunchConfiguration('gz_version').perform(context) diff --git a/ros_gz_sim/launch/gz_spawn_model.launch b/ros_gz_sim/launch/gz_spawn_model.launch new file mode 100644 index 00000000..3f289048 --- /dev/null +++ b/ros_gz_sim/launch/gz_spawn_model.launch @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + diff --git a/ros_gz_sim/launch/gz_spawn_model.launch.py b/ros_gz_sim/launch/gz_spawn_model.launch.py new file mode 100644 index 00000000..59cb4361 --- /dev/null +++ b/ros_gz_sim/launch/gz_spawn_model.launch.py @@ -0,0 +1,94 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Launch create to spawn models in gz sim.""" + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration, TextSubstitution +from launch_ros.actions import Node + + +def generate_launch_description(): + + world = LaunchConfiguration('world') + file = LaunchConfiguration('file') + xml_string = LaunchConfiguration('string') + topic = LaunchConfiguration('topic') + name = LaunchConfiguration('name') + allow_renaming = LaunchConfiguration('allow_renaming') + x = LaunchConfiguration('x', default='0.0') + y = LaunchConfiguration('y', default='0.0') + z = LaunchConfiguration('z', default='0.0') + roll = LaunchConfiguration('R', default='0.0') + pitch = LaunchConfiguration('P', default='0.0') + yaw = LaunchConfiguration('Y', default='0.0') + + declare_world_cmd = DeclareLaunchArgument( + 'world', default_value=TextSubstitution(text=''), + description='World name') + declare_file_cmd = DeclareLaunchArgument( + 'file', default_value=TextSubstitution(text=''), + description='SDF filename') + declare_xml_string_cmd = DeclareLaunchArgument( + 'string', + default_value='', + description='XML string', + ) + declare_topic_cmd = DeclareLaunchArgument( + 'topic', default_value=TextSubstitution(text=''), + description='Get XML from this topic' + ) + declare_name_cmd = DeclareLaunchArgument( + 'name', default_value=TextSubstitution(text=''), + description='Name of the entity' + ) + declare_allow_renaming_cmd = DeclareLaunchArgument( + 'allow_renaming', default_value='False', + description='Whether the entity allows renaming or not' + ) + + load_nodes = Node( + package='ros_gz_sim', + executable='create', + output='screen', + parameters=[{'world': world, + 'file': file, + 'string': xml_string, + 'topic': topic, + 'name': name, + 'allow_renaming': allow_renaming, + 'x': x, + 'y': y, + 'z': z, + 'R': roll, + 'P': pitch, + 'Y': yaw, + }], + ) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_world_cmd) + ld.add_action(declare_file_cmd) + ld.add_action(declare_xml_string_cmd) + ld.add_action(declare_topic_cmd) + ld.add_action(declare_name_cmd) + ld.add_action(declare_allow_renaming_cmd) + # Add the actions to launch all of the create nodes + ld.add_action(load_nodes) + + return ld diff --git a/ros_gz_sim/launch/ros_gz_sim.launch b/ros_gz_sim/launch/ros_gz_sim.launch new file mode 100644 index 00000000..cc6b04fc --- /dev/null +++ b/ros_gz_sim/launch/ros_gz_sim.launch @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/ros_gz_sim/launch/ros_gz_sim.launch.py b/ros_gz_sim/launch/ros_gz_sim.launch.py new file mode 100644 index 00000000..d0a68835 --- /dev/null +++ b/ros_gz_sim/launch/ros_gz_sim.launch.py @@ -0,0 +1,111 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Launch gzsim + ros_gz_bridge in a component container.""" + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution, TextSubstitution +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + + config_file = LaunchConfiguration('config_file') + container_name = LaunchConfiguration('container_name') + namespace = LaunchConfiguration('namespace') + use_composition = LaunchConfiguration('use_composition') + use_respawn = LaunchConfiguration('use_respawn') + bridge_log_level = LaunchConfiguration('bridge_log_level') + + world_sdf_file = LaunchConfiguration('world_sdf_file') + world_sdf_string = LaunchConfiguration('world_sdf_string') + + declare_config_file_cmd = DeclareLaunchArgument( + 'config_file', default_value='', description='YAML config file' + ) + + declare_container_name_cmd = DeclareLaunchArgument( + 'container_name', + default_value='ros_gz_container', + description='Name of container that nodes will load in if use composition', + ) + + declare_namespace_cmd = DeclareLaunchArgument( + 'namespace', default_value='', description='Top-level namespace' + ) + + declare_use_composition_cmd = DeclareLaunchArgument( + 'use_composition', default_value='True', description='Use composed bringup if True' + ) + + declare_use_respawn_cmd = DeclareLaunchArgument( + 'use_respawn', + default_value='False', + description='Whether to respawn if a node crashes. Applied when composition is disabled.', + ) + + declare_bridge_log_level_cmd = DeclareLaunchArgument( + 'bridge_log_level', default_value='info', description='Bridge log level' + ) + + declare_world_sdf_file_cmd = DeclareLaunchArgument( + 'world_sdf_file', default_value=TextSubstitution(text=''), + description='Path to the SDF world file' + ) + + declare_world_sdf_string_cmd = DeclareLaunchArgument( + 'world_sdf_string', default_value=TextSubstitution(text=''), + description='SDF world string' + ) + + bridge_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_bridge'), + 'launch', + 'ros_gz_bridge.launch.py'])]), + launch_arguments=[('config_file', config_file), + ('container_name', container_name), + ('namespace', namespace), + ('use_composition', use_composition), + ('use_respawn', use_respawn), + ('bridge_log_level', bridge_log_level)]) + + gz_server_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_sim'), + 'launch', + 'gz_server.launch.py'])]), + launch_arguments=[('world_sdf_file', world_sdf_file), + ('world_sdf_string', world_sdf_string), + ('use_composition', use_composition), ]) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_config_file_cmd) + ld.add_action(declare_container_name_cmd) + ld.add_action(declare_namespace_cmd) + ld.add_action(declare_use_composition_cmd) + ld.add_action(declare_use_respawn_cmd) + ld.add_action(declare_bridge_log_level_cmd) + ld.add_action(declare_world_sdf_file_cmd) + ld.add_action(declare_world_sdf_string_cmd) + # Add the actions to launch all of the bridge + gz_server nodes + ld.add_action(bridge_description) + ld.add_action(gz_server_description) + + return ld diff --git a/ros_gz_sim/launch/ros_gz_spawn_model.launch.py b/ros_gz_sim/launch/ros_gz_spawn_model.launch.py new file mode 100644 index 00000000..87dcb248 --- /dev/null +++ b/ros_gz_sim/launch/ros_gz_spawn_model.launch.py @@ -0,0 +1,154 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Launch gzsim + ros_gz_bridge in a component container.""" + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution, TextSubstitution +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + + config_file = LaunchConfiguration('config_file') + container_name = LaunchConfiguration('container_name') + namespace = LaunchConfiguration('namespace') + use_composition = LaunchConfiguration('use_composition') + use_respawn = LaunchConfiguration('use_respawn') + log_level = LaunchConfiguration('log_level') + + world = LaunchConfiguration('world') + file = LaunchConfiguration('file') + xml_string = LaunchConfiguration('string') + topic = LaunchConfiguration('topic') + name = LaunchConfiguration('name') + allow_renaming = LaunchConfiguration('allow_renaming') + x = LaunchConfiguration('x', default='0.0') + y = LaunchConfiguration('y', default='0.0') + z = LaunchConfiguration('z', default='0.0') + roll = LaunchConfiguration('R', default='0.0') + pitch = LaunchConfiguration('P', default='0.0') + yaw = LaunchConfiguration('Y', default='0.0') + + declare_config_file_cmd = DeclareLaunchArgument( + 'config_file', default_value='', description='YAML config file' + ) + + declare_container_name_cmd = DeclareLaunchArgument( + 'container_name', + default_value='ros_gz_container', + description='Name of container that nodes will load in if use composition', + ) + + declare_namespace_cmd = DeclareLaunchArgument( + 'namespace', default_value='', description='Top-level namespace' + ) + + declare_use_composition_cmd = DeclareLaunchArgument( + 'use_composition', default_value='True', description='Use composed bringup if True' + ) + + declare_use_respawn_cmd = DeclareLaunchArgument( + 'use_respawn', + default_value='False', + description='Whether to respawn if a node crashes. Applied when composition is disabled.', + ) + + declare_log_level_cmd = DeclareLaunchArgument( + 'log_level', default_value='info', description='log level' + ) + + declare_world_cmd = DeclareLaunchArgument( + 'world', default_value=TextSubstitution(text=''), + description='World name') + + declare_file_cmd = DeclareLaunchArgument( + 'file', default_value=TextSubstitution(text=''), + description='SDF filename') + + declare_xml_string_cmd = DeclareLaunchArgument( + 'string', + default_value='', + description='XML string', + ) + + declare_topic_cmd = DeclareLaunchArgument( + 'topic', default_value=TextSubstitution(text=''), + description='Get XML from this topic' + ) + + declare_name_cmd = DeclareLaunchArgument( + 'name', default_value=TextSubstitution(text=''), + description='Name of the entity' + ) + + declare_allow_renaming_cmd = DeclareLaunchArgument( + 'allow_renaming', default_value='False', + description='Whether the entity allows renaming or not' + ) + + bridge_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_bridge'), + 'launch', + 'ros_gz_bridge.launch.py'])]), + launch_arguments=[('config_file', config_file), + ('container_name', container_name), + ('namespace', namespace), + ('use_composition', use_composition), + ('use_respawn', use_respawn), + ('log_level', log_level), ]) + + spawn_model_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_sim'), + 'launch', + 'gz_spawn_model.launch.py'])]), + launch_arguments=[('world', world), + ('file', file), + ('xml_string', xml_string), + ('topic', topic), + ('name', name), + ('allow_renaming', allow_renaming), + ('x', x), + ('y', y), + ('z', z), + ('R', roll), + ('P', pitch), + ('Y', yaw), + ('use_composition', use_composition), ]) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_config_file_cmd) + ld.add_action(declare_container_name_cmd) + ld.add_action(declare_namespace_cmd) + ld.add_action(declare_use_composition_cmd) + ld.add_action(declare_use_respawn_cmd) + ld.add_action(declare_log_level_cmd) + ld.add_action(declare_world_cmd) + ld.add_action(declare_file_cmd) + ld.add_action(declare_xml_string_cmd) + ld.add_action(declare_topic_cmd) + ld.add_action(declare_name_cmd) + ld.add_action(declare_allow_renaming_cmd) + # Add the actions to launch all of the bridge + spawn_model nodes + ld.add_action(bridge_description) + ld.add_action(spawn_model_description) + + return ld diff --git a/ros_gz_sim/package.xml b/ros_gz_sim/package.xml index 9774b03a..b7fb5ea8 100644 --- a/ros_gz_sim/package.xml +++ b/ros_gz_sim/package.xml @@ -2,41 +2,39 @@ ros_gz_sim - 0.244.12 + 2.0.0 Tools for using Gazebo Sim simulation with ROS. Alejandro Hernandez + Aditya Pande Apache 2.0 Alejandro Hernandez + Addisu Taddese + Carlos Agüero ament_cmake + ament_cmake_python pkg-config ament_index_python + launch + launch_ros libgflags-dev rclcpp + rclcpp_components std_msgs - - gz-math7 - gz-msgs10 - gz-sim8 - gz-transport13 - - gz-sim7 - gz-math7 - - ignition-gazebo6 - ignition-math6 - ignition-gazebo6 - ignition-math6 - - ignition-gazebo5 - ignition-math6 + gz_math_vendor + gz_msgs_vendor + gz_sim_vendor + gz_transport_vendor ament_lint_auto ament_lint_common + launch_testing_ament_cmake + launch_ros + launch_testing ament_cmake diff --git a/ros_gz_sim/resource/ros_gz_sim b/ros_gz_sim/resource/ros_gz_sim new file mode 100644 index 00000000..e69de29b diff --git a/ros_gz_sim/ros_gz_sim/__init__.py b/ros_gz_sim/ros_gz_sim/__init__.py new file mode 100644 index 00000000..17b9696c --- /dev/null +++ b/ros_gz_sim/ros_gz_sim/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Main entry point for the `ros_gz_sim` package.""" + +from . import actions + + +__all__ = [ + 'actions', +] diff --git a/ros_gz_sim/ros_gz_sim/actions/__init__.py b/ros_gz_sim/ros_gz_sim/actions/__init__.py new file mode 100644 index 00000000..bea18edd --- /dev/null +++ b/ros_gz_sim/ros_gz_sim/actions/__init__.py @@ -0,0 +1,24 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Actions module.""" + +from .gz_spawn_model import GzSpawnModel +from .gzserver import GzServer + + +__all__ = [ + 'GzSpawnModel', + 'GzServer', +] diff --git a/ros_gz_sim/ros_gz_sim/actions/gz_spawn_model.py b/ros_gz_sim/ros_gz_sim/actions/gz_spawn_model.py new file mode 100644 index 00000000..7626eb01 --- /dev/null +++ b/ros_gz_sim/ros_gz_sim/actions/gz_spawn_model.py @@ -0,0 +1,207 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module for the gz_spawn_model action.""" + +from typing import List +from typing import Optional + +from launch.action import Action +from launch.actions import IncludeLaunchDescription +from launch.frontend import Entity, expose_action, Parser +from launch.launch_context import LaunchContext +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.some_substitutions_type import SomeSubstitutionsType +from launch.substitutions import PathJoinSubstitution +from launch_ros.substitutions import FindPackageShare + + +@expose_action('gz_spawn_model') +class GzSpawnModel(Action): + """Action that executes a gz_spawn_model ROS node.""" + + def __init__( + self, + *, + world: Optional[SomeSubstitutionsType] = None, + file: Optional[SomeSubstitutionsType] = None, + xml_string: Optional[SomeSubstitutionsType] = None, + topic: Optional[SomeSubstitutionsType] = None, + name: Optional[SomeSubstitutionsType] = None, + allow_renaming: Optional[SomeSubstitutionsType] = None, + x: Optional[SomeSubstitutionsType] = None, + y: Optional[SomeSubstitutionsType] = None, + z: Optional[SomeSubstitutionsType] = None, + roll: Optional[SomeSubstitutionsType] = None, + pitch: Optional[SomeSubstitutionsType] = None, + yaw: Optional[SomeSubstitutionsType] = None, + **kwargs + ) -> None: + """ + Construct a gz_spawn_model action. + + All arguments are forwarded to `ros_gz_sim.launch.gz_spawn_model.launch.py`, + so see the documentation of that class for further details. + + :param: world World name. + :param: file SDF filename. + :param: xml_string XML string. + :param: topic Get XML from this topic. + :param: name Name of the entity. + :param: allow_renaming Whether the entity allows renaming or not. + :param: x X coordinate. + :param: y Y coordinate. + :param: z Z coordinate. + :param: roll Roll orientation. + :param: pitch Pitch orientation. + :param: yaw Yaw orientation. + """ + super().__init__(**kwargs) + self.__world = world + self.__file = file + self.__xml_string = xml_string + self.__topic = topic + self.__name = name + self.__allow_renaming = allow_renaming + self.__x = x + self.__y = y + self.__z = z + self.__roll = roll + self.__pitch = pitch + self.__yaw = yaw + + @classmethod + def parse(cls, entity: Entity, parser: Parser): + """Parse gz_spawn_model.""" + _, kwargs = super().parse(entity, parser) + + world = entity.get_attr( + 'world', data_type=str, + optional=True) + + file = entity.get_attr( + 'file', data_type=str, + optional=True) + + xml_string = entity.get_attr( + 'xml_string', data_type=str, + optional=True) + + topic = entity.get_attr( + 'topic', data_type=str, + optional=True) + + name = entity.get_attr( + 'name', data_type=str, + optional=True) + + allow_renaming = entity.get_attr( + 'allow_renaming', data_type=str, + optional=True) + + x = entity.get_attr( + 'x', data_type=str, + optional=True) + + y = entity.get_attr( + 'y', data_type=str, + optional=True) + + z = entity.get_attr( + 'z', data_type=str, + optional=True) + + roll = entity.get_attr( + 'roll', data_type=str, + optional=True) + + pitch = entity.get_attr( + 'pitch', data_type=str, + optional=True) + + yaw = entity.get_attr( + 'yaw', data_type=str, + optional=True) + + if isinstance(world, str): + world = parser.parse_substitution(world) + kwargs['world'] = world + + if isinstance(file, str): + file = parser.parse_substitution(file) + kwargs['file'] = file + + if isinstance(xml_string, str): + xml_string = parser.parse_substitution(xml_string) + kwargs['xml_string'] = xml_string + + if isinstance(topic, str): + topic = parser.parse_substitution(topic) + kwargs['topic'] = topic + + if isinstance(name, str): + name = parser.parse_substitution(name) + kwargs['name'] = name + + if isinstance(allow_renaming, str): + allow_renaming = parser.parse_substitution(allow_renaming) + kwargs['allow_renaming'] = allow_renaming + + if isinstance(x, str): + x = parser.parse_substitution(x) + kwargs['x'] = x + + if isinstance(y, str): + y = parser.parse_substitution(y) + kwargs['y'] = y + + if isinstance(z, str): + z = parser.parse_substitution(z) + kwargs['z'] = z + + if isinstance(roll, str): + roll = parser.parse_substitution(roll) + kwargs['roll'] = roll + + if isinstance(pitch, str): + pitch = parser.parse_substitution(pitch) + kwargs['pitch'] = pitch + + if isinstance(yaw, str): + yaw = parser.parse_substitution(yaw) + kwargs['yaw'] = yaw + + return cls, kwargs + + def execute(self, context: LaunchContext) -> Optional[List[Action]]: + """Execute the action.""" + gz_spawn_model_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_sim'), + 'launch', + 'gz_spawn_model.launch.py'])]), + launch_arguments=[('world', self.__world), + ('file', self.__file), + ('xml_string', self.__xml_string), + ('topic', self.__topic), + ('name', self.__name), + ('allow_renaming', self.__allow_renaming), + ('x', self.__x), + ('y', self.__y), + ('z', self.__z), + ('roll', self.__roll), + ('pitch', self.__pitch), + ('yaw', self.__yaw), ]) + + return [gz_spawn_model_description] diff --git a/ros_gz_sim/ros_gz_sim/actions/gzserver.py b/ros_gz_sim/ros_gz_sim/actions/gzserver.py new file mode 100644 index 00000000..14df9aab --- /dev/null +++ b/ros_gz_sim/ros_gz_sim/actions/gzserver.py @@ -0,0 +1,111 @@ +# Copyright 2024 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module for the GzServer action.""" + +from typing import List +from typing import Optional + +from launch.action import Action +from launch.actions import IncludeLaunchDescription +from launch.frontend import Entity, expose_action, Parser +from launch.launch_context import LaunchContext +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.some_substitutions_type import SomeSubstitutionsType +from launch.substitutions import PathJoinSubstitution +from launch_ros.substitutions import FindPackageShare + + +@expose_action('gz_server') +class GzServer(Action): + """Action that executes a gz_server ROS [composable] node.""" + + def __init__( + self, + *, + world_sdf_file: Optional[SomeSubstitutionsType] = None, + world_sdf_string: Optional[SomeSubstitutionsType] = None, + container_name: Optional[SomeSubstitutionsType] = None, + use_composition: Optional[SomeSubstitutionsType] = None, + **kwargs + ) -> None: + """ + Construct a gz_server action. + + All arguments are forwarded to `ros_gz_sim.launch.gz_server.launch.py`, + so see the documentation of that class for further details. + + :param: world_sdf_file Path to the SDF world file. + :param: world_sdf_string SDF world string. + :param: container_name Name of container that nodes will load in if use composition. + :param: use_composition Use composed bringup if True. + """ + super().__init__(**kwargs) + self.__world_sdf_file = world_sdf_file + self.__world_sdf_string = world_sdf_string + self.__container_name = container_name + self.__use_composition = use_composition + + @classmethod + def parse(cls, entity: Entity, parser: Parser): + """Parse gz_server.""" + _, kwargs = super().parse(entity, parser) + + world_sdf_file = entity.get_attr( + 'world_sdf_file', data_type=str, + optional=True) + + world_sdf_string = entity.get_attr( + 'world_sdf_string', data_type=str, + optional=True) + + container_name = entity.get_attr( + 'container_name', data_type=str, + optional=True) + + use_composition = entity.get_attr( + 'use_composition', data_type=str, + optional=True) + + if isinstance(world_sdf_file, str): + world_sdf_file = parser.parse_substitution(world_sdf_file) + kwargs['world_sdf_file'] = world_sdf_file + + if isinstance(world_sdf_string, str): + world_sdf_string = parser.parse_substitution(world_sdf_string) + kwargs['world_sdf_string'] = world_sdf_string + + if isinstance(container_name, str): + container_name = parser.parse_substitution(container_name) + kwargs['container_name'] = container_name + + if isinstance(use_composition, str): + use_composition = parser.parse_substitution(use_composition) + kwargs['use_composition'] = use_composition + + return cls, kwargs + + def execute(self, context: LaunchContext) -> Optional[List[Action]]: + """Execute the action.""" + gz_server_description = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [PathJoinSubstitution([FindPackageShare('ros_gz_sim'), + 'launch', + 'gz_server.launch.py'])]), + launch_arguments=[('world_sdf_file', self.__world_sdf_file), + ('world_sdf_string', self.__world_sdf_string), + ('container_name', self.__container_name), + ('use_composition', self.__use_composition), ]) + + return [gz_server_description] diff --git a/ros_gz_sim/setup.cfg b/ros_gz_sim/setup.cfg new file mode 100644 index 00000000..c044b41d --- /dev/null +++ b/ros_gz_sim/setup.cfg @@ -0,0 +1,3 @@ +[options.entry_points] +launch.frontend.launch_extension = + ros_gz_sim = ros_gz_sim diff --git a/ros_gz_sim/src/create.cpp b/ros_gz_sim/src/create.cpp index 6b12daf8..db2b7452 100644 --- a/ros_gz_sim/src/create.cpp +++ b/ros_gz_sim/src/create.cpp @@ -21,6 +21,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -29,7 +33,11 @@ #include #include +// ROS interface for spawning entities into Gazebo. +// Suggested for use with roslaunch and loading entities from ROS param. +// If these are not needed, just use the `gz service` command line instead. +// \TODO(anyone) Remove GFlags in ROS-J DEFINE_string(world, "", "World name."); DEFINE_string(file, "", "Load XML from a file."); DEFINE_string(param, "", "Load XML from a ROS param."); @@ -44,23 +52,94 @@ DEFINE_double(R, 0, "Roll component of initial orientation, in radians."); DEFINE_double(P, 0, "Pitch component of initial orientation, in radians."); DEFINE_double(Y, 0, "Yaw component of initial orientation, in radians."); -// ROS interface for spawning entities into Gazebo. -// Suggested for use with roslaunch and loading entities from ROS param. -// If these are not needed, just use the `gz service` command line instead. +// Utility Function to avoid code duplication + +bool set_XML_from_topic( + const std::string & topic_name, const rclcpp::Node::SharedPtr ros2_node, + gz::msgs::EntityFactory & req) +{ + const auto timeout = std::chrono::seconds(1); + std::promise xml_promise; + std::shared_future xml_future(xml_promise.get_future()); + + std::function fun = + [&xml_promise](const std_msgs::msg::String::SharedPtr msg) { + xml_promise.set_value(msg->data); + }; + + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(ros2_node); + rclcpp::Subscription::SharedPtr description_subs; + // Transient local is similar to latching in ROS 1. + description_subs = ros2_node->create_subscription( + topic_name, rclcpp::QoS(1).transient_local(), fun); + + rclcpp::FutureReturnCode future_ret; + do { + RCLCPP_INFO(ros2_node->get_logger(), "Waiting messages on topic [%s].", topic_name.c_str()); + future_ret = executor.spin_until_future_complete(xml_future, timeout); + } while (rclcpp::ok() && future_ret != rclcpp::FutureReturnCode::SUCCESS); + + if (future_ret == rclcpp::FutureReturnCode::SUCCESS) { + req.set_sdf(xml_future.get()); + return true; + } else { + RCLCPP_ERROR( + ros2_node->get_logger(), "Failed to get XML from topic [%s].", topic_name.c_str()); + return false; + } +} + int main(int _argc, char ** _argv) { - rclcpp::init(_argc, _argv); + auto filtered_arguments = rclcpp::init_and_remove_ros_arguments(_argc, _argv); auto ros2_node = rclcpp::Node::make_shared("ros_gz_sim"); + // Construct a new argc/argv pair from the flags that weren't parsed by ROS + // Gflags wants a mutable pointer to argv, which is why we can't use a + // vector of strings here + int filtered_argc = filtered_arguments.size(); + char ** filtered_argv = new char *[(filtered_argc + 1)]; + for (int ii = 0; ii < filtered_argc; ++ii) { + filtered_argv[ii] = new char[filtered_arguments[ii].size() + 1]; + snprintf( + filtered_argv[ii], + filtered_arguments[ii].size() + 1, "%s", filtered_arguments[ii].c_str()); + } + filtered_argv[filtered_argc] = nullptr; + gflags::AllowCommandLineReparsing(); gflags::SetUsageMessage( R"(Usage: create -world [arg] [-file FILE] [-param PARAM] [-topic TOPIC] [-string STRING] [-name NAME] [-allow_renaming RENAMING] [-x X] [-y Y] [-z Z] [-R ROLL] [-P PITCH] [-Y YAW])"); - gflags::ParseCommandLineFlags(&_argc, &_argv, true); + gflags::ParseCommandLineFlags(&filtered_argc, &filtered_argv, false); + + // Free our temporary argc/argv pair + for (size_t ii = 0; filtered_argv[ii] != nullptr; ++ii) { + delete[] filtered_argv[ii]; + } + delete[] filtered_argv; + + // Declare ROS 2 parameters to be passed from launch file + ros2_node->declare_parameter("world", ""); + ros2_node->declare_parameter("file", ""); + ros2_node->declare_parameter("string", ""); + ros2_node->declare_parameter("topic", ""); + ros2_node->declare_parameter("name", ""); + ros2_node->declare_parameter("allow_renaming", false); + ros2_node->declare_parameter("x", static_cast(0)); + ros2_node->declare_parameter("y", static_cast(0)); + ros2_node->declare_parameter("z", static_cast(0)); + ros2_node->declare_parameter("R", static_cast(0)); + ros2_node->declare_parameter("P", static_cast(0)); + ros2_node->declare_parameter("Y", static_cast(0)); // World - std::string world_name = FLAGS_world; + std::string world_name = ros2_node->get_parameter("world").as_string(); + if (world_name.empty() && !FLAGS_world.empty()) { + world_name = FLAGS_world; + } if (world_name.empty()) { // If caller doesn't provide a world name, get list of worlds from gz-sim server gz::transport::Node node; @@ -94,69 +173,83 @@ int main(int _argc, char ** _argv) // Request message gz::msgs::EntityFactory req; - // File - if (!FLAGS_file.empty()) { - req.set_sdf_filename(FLAGS_file); - } else if (!FLAGS_param.empty()) { // Param - ros2_node->declare_parameter(FLAGS_param); - - std::string xmlStr; - if (ros2_node->get_parameter(FLAGS_param, xmlStr)) { - req.set_sdf(xmlStr); - } else { - RCLCPP_ERROR( - ros2_node->get_logger(), "Failed to get XML from param [%s].", FLAGS_param.c_str()); + // Get ROS parameters + std::string file_name = ros2_node->get_parameter("file").as_string(); + std::string xml_string = ros2_node->get_parameter("string").as_string(); + std::string topic_name = ros2_node->get_parameter("topic").as_string(); + // Check for the SDF filename or XML string or topic name + if (!file_name.empty()) { + req.set_sdf_filename(file_name); + } else if (!xml_string.empty()) { + req.set_sdf(xml_string); + } else if (!topic_name.empty()) { + // set XML string by fetching it from the given topic + if (!set_XML_from_topic(topic_name, ros2_node, req)) { return -1; } - } else if (!FLAGS_string.empty()) { // string - req.set_sdf(FLAGS_string); - } else if (!FLAGS_topic.empty()) { // topic - const auto timeout = std::chrono::seconds(1); - std::promise xml_promise; - std::shared_future xml_future(xml_promise.get_future()); - - std::function fun = - [&xml_promise](const std_msgs::msg::String::SharedPtr msg) { - xml_promise.set_value(msg->data); - }; - - rclcpp::executors::SingleThreadedExecutor executor; - executor.add_node(ros2_node); - rclcpp::Subscription::SharedPtr description_subs; - // Transient local is similar to latching in ROS 1. - description_subs = ros2_node->create_subscription( - FLAGS_topic, rclcpp::QoS(1).transient_local(), fun); - - rclcpp::FutureReturnCode future_ret; - do { - RCLCPP_INFO(ros2_node->get_logger(), "Waiting messages on topic [%s].", FLAGS_topic.c_str()); - future_ret = executor.spin_until_future_complete(xml_future, timeout); - } while (rclcpp::ok() && future_ret != rclcpp::FutureReturnCode::SUCCESS); - - if (future_ret == rclcpp::FutureReturnCode::SUCCESS) { - req.set_sdf(xml_future.get()); + } else if (filtered_arguments.size() > 1) { + // Revert to Gflags, if ROS parameters aren't specified + // File + if (!FLAGS_file.empty()) { + req.set_sdf_filename(FLAGS_file); + } else if (!FLAGS_param.empty()) { // Param + ros2_node->declare_parameter(FLAGS_param); + std::string xmlStr; + if (ros2_node->get_parameter(FLAGS_param, xmlStr)) { + req.set_sdf(xmlStr); + } else { + RCLCPP_ERROR( + ros2_node->get_logger(), "Failed to get XML from param [%s].", FLAGS_param.c_str()); + return -1; + } + } else if (!FLAGS_string.empty()) { // string + req.set_sdf(FLAGS_string); + } else if (!FLAGS_topic.empty()) { // topic + // set XML string by fetching it from the given topic + if (!set_XML_from_topic(FLAGS_topic, ros2_node, req)) { + return -1; + } } else { RCLCPP_ERROR( - ros2_node->get_logger(), "Failed to get XML from topic [%s].", FLAGS_topic.c_str()); + ros2_node->get_logger(), "Must specify either -file, -param, -string or -topic"); return -1; } + // TODO(azeey) Deprecate use of command line flags in ROS 2 K-turtle in + // favor of ROS 2 parameters. } else { - RCLCPP_ERROR(ros2_node->get_logger(), "Must specify either -file, -param, -stdin or -topic"); + RCLCPP_ERROR( + ros2_node->get_logger(), "Must specify either file, string or topic as ROS 2 parameters"); return -1; } // Pose + double x_coords = ros2_node->get_parameter("x").as_double(); + double y_coords = ros2_node->get_parameter("y").as_double(); + double z_coords = ros2_node->get_parameter("z").as_double(); + double roll = ros2_node->get_parameter("R").as_double(); + double pitch = ros2_node->get_parameter("P").as_double(); + double yaw = ros2_node->get_parameter("Y").as_double(); + + FLAGS_x = (x_coords != 0.0) ? x_coords : FLAGS_x; + FLAGS_y = (y_coords != 0.0) ? y_coords : FLAGS_y; + FLAGS_z = (z_coords != 0.0) ? z_coords : FLAGS_z; + FLAGS_R = (roll != 0.0) ? roll : FLAGS_R; + FLAGS_P = (pitch != 0.0) ? pitch : FLAGS_P; + FLAGS_Y = (yaw != 0.0) ? yaw : FLAGS_Y; gz::math::Pose3d pose{FLAGS_x, FLAGS_y, FLAGS_z, FLAGS_R, FLAGS_P, FLAGS_Y}; gz::msgs::Set(req.mutable_pose(), pose); // Name - if (!FLAGS_name.empty()) { + std::string entity_name = ros2_node->get_parameter("name").as_string(); + if (!entity_name.empty()) { + req.set_name(entity_name); + } else { req.set_name(FLAGS_name); } - if (FLAGS_allow_renaming) { - req.set_allow_renaming(FLAGS_allow_renaming); - } + // Allow Renaming + bool allow_renaming = ros2_node->get_parameter("allow_renaming").as_bool(); + req.set_allow_renaming((allow_renaming || FLAGS_allow_renaming)); // Request gz::transport::Node node; diff --git a/ros_gz_sim/src/gzserver.cpp b/ros_gz_sim/src/gzserver.cpp new file mode 100644 index 00000000..aa4361f5 --- /dev/null +++ b/ros_gz_sim/src/gzserver.cpp @@ -0,0 +1,80 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include + +// ROS node that executes a gz-sim Server given a world SDF file or string. +namespace ros_gz_sim +{ +class GzServer : public rclcpp::Node +{ +public: + // Class constructor. + explicit GzServer(const rclcpp::NodeOptions & options) + : Node("gzserver", options) + { + thread_ = std::thread(std::bind(&GzServer::OnStart, this)); + } + +public: + // Class destructor. + ~GzServer() + { + // Make sure to join the thread on shutdown. + if (thread_.joinable()) { + thread_.join(); + } + } + +public: + /// \brief Run the gz sim server. + void OnStart() + { + auto world_sdf_file = this->declare_parameter("world_sdf_file", ""); + auto world_sdf_string = this->declare_parameter("world_sdf_string", ""); + + gz::common::Console::SetVerbosity(4); + gz::sim::ServerConfig server_config; + + if (!world_sdf_file.empty()) { + server_config.SetSdfFile(world_sdf_file); + } else if (!world_sdf_string.empty()) { + server_config.SetSdfString(world_sdf_string); + } else { + RCLCPP_ERROR( + this->get_logger(), + "Must specify either 'world_sdf_file' or 'world_sdf_string'"); + rclcpp::shutdown(); + return; + } + + gz::sim::Server server(server_config); + server.Run(true /*blocking*/, 0, false /*paused*/); + rclcpp::shutdown(); + } + +private: + /// \brief We don't want to block the ROS thread. + std::thread thread_; +}; +} // namespace ros_gz_sim + +RCLCPP_COMPONENTS_REGISTER_NODE(ros_gz_sim::GzServer) diff --git a/ros_gz_sim/test/test_create.cpp b/ros_gz_sim/test/test_create.cpp new file mode 100644 index 00000000..ee92bf39 --- /dev/null +++ b/ros_gz_sim/test/test_create.cpp @@ -0,0 +1,56 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include +#include +#include +#include +#include + +// Simple application that provides a `/create` service and prints out the +// sdf_filename of the request. This works in conjection with +// test_create_node.launch.py +int main() +{ + std::mutex m; + std::condition_variable cv; + bool test_complete = false; + + gz::transport::Node node; + auto cb = std::function( + [&]( + const gz::msgs::EntityFactory & _req, + gz::msgs::Boolean & _res) -> bool { + std::cout << _req.sdf_filename() << std::endl; + _res.set_data(true); + + { + std::lock_guard lk(m); + test_complete = true; + } + cv.notify_one(); + return true; + }); + + node.Advertise("/world/default/create", cb); + // wait until we receive a message. + std::unique_lock lk(m); + cv.wait(lk, [&] {return test_complete;}); + // Sleep so that the service response can be sent before exiting. + std::this_thread::sleep_for(std::chrono::seconds(1)); +} diff --git a/ros_gz_sim/test/test_create_node.launch.py b/ros_gz_sim/test/test_create_node.launch.py new file mode 100644 index 00000000..79c31c5c --- /dev/null +++ b/ros_gz_sim/test/test_create_node.launch.py @@ -0,0 +1,47 @@ +# Copyright 2023 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from launch import LaunchDescription + +from launch_ros.actions import Node + +import launch_testing + + +def generate_test_description(): + expected_file_name = 'nonexistent/long/file_name' + create = Node(package='ros_gz_sim', executable='create', + parameters=[{'world': 'default', 'file': expected_file_name}], output='screen') + test_create = Node(package='ros_gz_sim', executable='test_create', output='screen') + return LaunchDescription([ + create, + test_create, + launch_testing.util.KeepAliveProc(), + launch_testing.actions.ReadyToTest(), + ]), locals() + + +class WaitForTests(unittest.TestCase): + + def test_termination(self, test_create, proc_info): + proc_info.assertWaitForShutdown(process=test_create, timeout=200) + + +@launch_testing.post_shutdown_test() +class CreateTest(unittest.TestCase): + + def test_output(self, expected_file_name, test_create, proc_output): + launch_testing.asserts.assertInStdout(proc_output, expected_file_name, test_create) diff --git a/ros_gz_sim_demos/CHANGELOG.rst b/ros_gz_sim_demos/CHANGELOG.rst index 8763d55e..336cf38e 100644 --- a/ros_gz_sim_demos/CHANGELOG.rst +++ b/ros_gz_sim_demos/CHANGELOG.rst @@ -2,15 +2,103 @@ Changelog for package ros1_gz_sim_demos ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0.244.12 (2023-12-13) ---------------------- -* [backport Humble] Added more topic to the bridge (`#422 `_) +2.0.0 (2024-07-22) +------------------ + +1.0.1 (2024-07-03) +------------------ +* Prepare for 1.0.0 Release (`#495 `_) +* Use gz_vendor packages (`#531 `_) +* [backport Humble] Create bridge for GPSFix msg (`#316 `_) (`#538 `_) + Co-authored-by: Rousseau Vincent +* [backport Iron] Create bridge for GPSFix msg (`#316 `_) (`#537 `_) + Co-authored-by: Rousseau Vincent +* 0.244.14 +* Changelog +* 0.244.13 +* Changelog +* Remove deprecations using ros_gz_sim_create (`#476 `_) +* 0.244.12 +* Changelog +* 0.246.0 +* Update changelogs +* Added more topic to the bridge (`#422 `_) +* Fix incorrect subscription on demo (`#405 `_) (`#408 `_) + This PR fixes an incorrect subscription on one of the demos. Running + ``` + ros2 launch ros_gz_sim_demos gpu_lidar_bridge.launch.py + ``` + causes rviz2 to crash and exit with the error: + ``` + rviz2-3] + [rviz2-3] >>> [rcutils|error_handling.c:108] rcutils_set_error_state() + [rviz2-3] This error state is being overwritten: + [rviz2-3] + [rviz2-3] 'create_subscription() called for existing topic name rt/lidar with incompatible type sensor_msgs::msg::dds\_::PointCloud2\_, at ./src/subscription.cpp:146, at ./src/rcl/subscription.c:108' + [rviz2-3] + [rviz2-3] with this new error message: + [rviz2-3] + [rviz2-3] 'invalid allocator, at ./src/rcl/subscription.c:218' + [rviz2-3] + [rviz2-3] rcutils_reset_error() should be called after error handling to avoid this. + ``` + This is due to an incorrect subscription on the part of the demo. This + PR fixes it by getting a subscription to the right topic for the + pointcloud display. (`lidar/points` instead of `lidar`). Was tested on + garden + humble. + Co-authored-by: Arjo Chakravarty +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Rename 'ign gazebo' to 'gz sim' (`#343 `_) +* Create bridge for GPSFix msg (`#316 `_) +* Humble ➡️ ROS2 (`#323 `_) + Humble ➡️ ROS2 +* Merge branch 'humble' into ports/humble_to_ros2 +* Fixed ros_gz_sim_demos launch files (`#319 `_) +* 0.245.0 +* Changelog +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Addisu Z. Taddese, Aditya Pande, Alejandro Hernández Cordero, Clyde McQueen, Jose Luis Rivero, Michael Carroll, Rousseau Vincent, ahcorde + +1.0.0 (2024-04-24) +------------------ +* Use gz_vendor packages (`#531 `_) +* Remove deprecations using ros_gz_sim_create (`#476 `_) +* Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero + +0.246.0 (2023-08-31) +-------------------- * Added more topic to the bridge (`#422 `_) -* Fix incorrect subscription on demo (`#405 `_) -* Contributors: Alejandro Hernández Cordero, Arjo Chakravarty +* Fix incorrect subscription on demo (`#405 `_) (`#408 `_) + Co-authored-by: Arjo Chakravarty +* Port: humble to ros2 (`#386 `_) +* Merge branch 'humble' into mjcarroll/humble_to_ros2 +* Update maintainers (`#376 `_) +* Rename 'ign gazebo' to 'gz sim' (`#343 `_) +* Create bridge for GPSFix msg (`#316 `_) +* Humble ➡️ ROS2 (`#323 `_) +* Fixed ros_gz_sim_demos launch files (`#319 `_) +* Contributors: Aditya Pande, Alejandro Hernández Cordero, Clyde McQueen, Michael Carroll, Rousseau Vincent, ahcorde -0.244.11 (2023-05-23) ---------------------- +0.245.0 (2022-10-12) +-------------------- +* humble to ros2 (`#311 `_) + Co-authored-by: Michael Carroll +* Merge remote-tracking branch 'origin/humble' into ahcorde/humble_to_ros2 +* Remove all ignition references on ROS 2 branch (`#302 `_) + * Remove all shims + * Update CMakeLists and package.xml for garden + * Complete garden gz renaming + * Drop fortress CI +* Contributors: Alejandro Hernández Cordero, Michael Carroll, ahcorde 0.244.10 (2023-05-03) --------------------- diff --git a/ros_gz_sim_demos/launch/joint_states.launch.py b/ros_gz_sim_demos/launch/joint_states.launch.py index 95bf1906..7b61c350 100644 --- a/ros_gz_sim_demos/launch/joint_states.launch.py +++ b/ros_gz_sim_demos/launch/joint_states.launch.py @@ -63,10 +63,8 @@ def generate_launch_description(): spawn = Node( package='ros_gz_sim', executable='create', - arguments=[ - '-name', 'rrbot', - '-topic', 'robot_description', - ], + parameters=[{'name': 'rrbot', + 'topic': 'robot_description'}], output='screen', ) diff --git a/ros_gz_sim_demos/launch/navsat_gpsfix.launch.py b/ros_gz_sim_demos/launch/navsat_gpsfix.launch.py new file mode 100644 index 00000000..83adcdcc --- /dev/null +++ b/ros_gz_sim_demos/launch/navsat_gpsfix.launch.py @@ -0,0 +1,63 @@ +# Copyright 2022 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.actions import IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration + +from launch_ros.actions import Node + + +def generate_launch_description(): + + pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim') + + gz_sim = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(pkg_ros_gz_sim, 'launch', 'gz_sim.launch.py')), + launch_arguments={ + 'gz_args': '-v 4 -r spherical_coordinates.sdf' + }.items(), + ) + + # RQt + rqt = Node( + package='rqt_topic', + executable='rqt_topic', + arguments=['-t'], + condition=IfCondition(LaunchConfiguration('rqt')) + ) + + # Bridge + bridge = Node( + package='ros_gz_bridge', + executable='parameter_bridge', + arguments=['/navsat@gps_msgs/msg/GPSFix@gz.msgs.NavSat'], + output='screen' + ) + + return LaunchDescription([ + gz_sim, + DeclareLaunchArgument('rqt', default_value='true', + description='Open RQt.'), + bridge, + rqt + ]) diff --git a/ros_gz_sim_demos/launch/robot_description_publisher.launch.py b/ros_gz_sim_demos/launch/robot_description_publisher.launch.py index 882cdee3..7fa6fc09 100755 --- a/ros_gz_sim_demos/launch/robot_description_publisher.launch.py +++ b/ros_gz_sim_demos/launch/robot_description_publisher.launch.py @@ -77,12 +77,12 @@ def generate_launch_description(): # Spawn spawn = Node(package='ros_gz_sim', executable='create', - arguments=[ - '-name', 'my_custom_model', - '-x', '1.2', - '-z', '2.3', - '-Y', '3.4', - '-topic', '/robot_description'], + parameters=[{ + 'name': 'my_custom_model', + 'x': 1.2, + 'z': 2.3, + 'Y': 3.4, + 'topic': '/robot_description'}], output='screen') return LaunchDescription([ diff --git a/ros_gz_sim_demos/launch/tf_bridge.launch.py b/ros_gz_sim_demos/launch/tf_bridge.launch.py index e134864e..42f76cdc 100644 --- a/ros_gz_sim_demos/launch/tf_bridge.launch.py +++ b/ros_gz_sim_demos/launch/tf_bridge.launch.py @@ -27,7 +27,7 @@ def generate_launch_description(): # Launch gazebo ExecuteProcess( cmd=[ - 'ign', 'gazebo', '-r', + 'gz', 'sim', '-r', os.path.join( pkg_ros_gz_sim_demos, 'models', diff --git a/ros_gz_sim_demos/package.xml b/ros_gz_sim_demos/package.xml index 4caa54fe..82959fe2 100644 --- a/ros_gz_sim_demos/package.xml +++ b/ros_gz_sim_demos/package.xml @@ -1,17 +1,16 @@ ros_gz_sim_demos - 0.244.12 + 2.0.0 Demos using Gazebo Sim simulation with ROS. Apache 2.0 - Louise Poubel + Aditya Pande + Alejandro Hernandez + + Louise Poubel ament_cmake - - ignition-gazebo6 - ignition-gazebo6 - - ignition-gazebo5 + gz_sim_vendor image_transport_plugins robot_state_publisher diff --git a/ros_ign/CHANGELOG.rst b/ros_ign/CHANGELOG.rst deleted file mode 100644 index ca3124cd..00000000 --- a/ros_ign/CHANGELOG.rst +++ /dev/null @@ -1,32 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign/CMakeLists.txt b/ros_ign/CMakeLists.txt deleted file mode 100644 index 80524e92..00000000 --- a/ros_ign/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(ros_ign) -find_package(ament_cmake REQUIRED) - -if(BUILD_TESTING) - find_package(ament_lint_auto REQUIRED) - ament_lint_auto_find_test_dependencies() -endif() - -ament_package() diff --git a/ros_ign/README.md b/ros_ign/README.md deleted file mode 100644 index 7f2dcc88..00000000 --- a/ros_ign/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim meta-package -For [ros_gz](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz) diff --git a/ros_ign/package.xml b/ros_ign/package.xml deleted file mode 100644 index 6217f10a..00000000 --- a/ros_ign/package.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - ros_ign - 0.244.12 - Shim meta-package to redirect to ros_gz. - Brandon Ong - Apache 2.0 - - ament_cmake - ros_gz - - ros_ign_bridge - ros_ign_gazebo - ros_ign_gazebo_demos - ros_ign_image - - ament_lint_auto - ament_lint_common - - - ament_cmake - - diff --git a/ros_ign_bridge/CHANGELOG.rst b/ros_ign_bridge/CHANGELOG.rst deleted file mode 100644 index 0501476c..00000000 --- a/ros_ign_bridge/CHANGELOG.rst +++ /dev/null @@ -1,70 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign_bridge -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- -* Merge branch 'ros2' into ports/galactic_to_ros2 -* Merge branch 'galactic' into ports/galactic_to_ros2 -* Make tests faster and more robust (`#272 `_) -* Improve documentation around yaml configuration (`#271 `_) -* Fix small typo in bridge README (`#270 `_) -* Port NavSat (`#224 `_) from ROS 1 to ROS 2 (`#268 `_) - Co-authored-by: Tyler Howell <76003804+TyHowellWork@users.noreply.github.com> -* Add ParamVec and bridge from Ignition (`#261 `_) - * Introduces `ros_ign_interfaces::msg::ParamVec` for storing a list of Parameters that are int, bool, double, or string. - * Introduces bridge for `ignition::msgs::param` to `ros_ign_interfaces::msg::ParamVec` - * Introduces bridge for `ignition::msgs::param_v` to `ros_ign_interfaces::msg::ParamVec` -* Add support for converting Any <-> ParamValue (`#260 `_) - * Add support for converting Any <-> ParamValue -* Feature: set QoS options to override durability (`#250 `_) (`#259 `_) - Co-authored-by: Louise Poubel - Co-authored-by: Daisuke Nishimatsu <42202095+wep21@users.noreply.github.com> -* Add node component and yaml-configured bridge node (`#238 `_) - * Refactor in support of adding yaml-configured node -* Add rssi to Dataframe.msg (`#249 `_) - * Adding rssi field to ros_ign_interfaces/Dataframe.msg -* Use the python generator for tests as well (`#234 `_) - * Use the python generator for tests as well -* Generate boilerplate files from Python scripts (`#233 `_) - The way that we add factories can be a bit error-prone, as there are a lot of strings that cannot be checked at compilation time. This changes several of the boilerplate files to be generated automatically by python scripts, in line with how ros1_bridge does it. -* [galactic] Backport GuiCamera, StringVec, TrackVisual, VideoRecord (`#241 `_) - * [ros_ign_interfaces] Add more interface definitions. - * Add converion functions for the added messages - * Update the factory factory function with the new messages - * Add new messages to docs - * Add test cases for the new messages conversions - Co-authored-by: Ivan Santiago Paunovic -* Add Dataframe message and bridging (`#239 `_) -* Factory interface needs virtual destructor (`#232 `_) -* Optional "lazy" bridge subscribers (`#225 `_) - This allows for the bridge to be created in such a way that it is "lazy". In this case "lazy" means: - * The publication (output) side of the bridge is always on and actively looking for subscriptions. - * The subscription (input) side of the bridge is only turned on in the case that there are subscriptions on the output side. -* Contributors: Carlos Agüero, Louise Poubel, Michael Carroll - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign_bridge/CMakeLists.txt b/ros_ign_bridge/CMakeLists.txt deleted file mode 100644 index 7be505b0..00000000 --- a/ros_ign_bridge/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(ros_ign_bridge) - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") -endif() - -find_package(ament_cmake REQUIRED) -find_package(ament_index_cpp REQUIRED) - -add_executable(parameter_bridge src/parameter_bridge_shim.cpp) -ament_target_dependencies(parameter_bridge ament_index_cpp) - -add_executable(static_bridge src/static_bridge_shim.cpp) -ament_target_dependencies(static_bridge ament_index_cpp) - -ament_export_dependencies(ament_index_cpp ros_gz_bridge) - -install(TARGETS - parameter_bridge - static_bridge - DESTINATION lib/${PROJECT_NAME} -) - -ament_package() diff --git a/ros_ign_bridge/README.md b/ros_ign_bridge/README.md deleted file mode 100644 index e93d8f26..00000000 --- a/ros_ign_bridge/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim package -For [ros_gz_bridge](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_bridge) diff --git a/ros_ign_bridge/package.xml b/ros_ign_bridge/package.xml deleted file mode 100644 index 9d6b3051..00000000 --- a/ros_ign_bridge/package.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - ros_ign_bridge - 0.244.12 - Shim package to redirect to ros_gz_bridge. - Brandon Ong - - Apache 2.0 - - ament_cmake - ament_index_cpp - - ros_gz_bridge - - - ament_cmake - - diff --git a/ros_ign_bridge/src/parameter_bridge_shim.cpp b/ros_ign_bridge/src/parameter_bridge_shim.cpp deleted file mode 100644 index df6882bb..00000000 --- a/ros_ign_bridge/src/parameter_bridge_shim.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Shim to redirect "ros_ign_bridge parameter_bridge" call to "ros_gz_bridge parameter_bridge" - -#include -#include -#include - -#include - - -int main(int argc, char * argv[]) -{ - std::stringstream cli_call; - - cli_call << ament_index_cpp::get_package_prefix("ros_gz_bridge") - << "/lib/ros_gz_bridge/parameter_bridge"; - - if (argc > 1) - { - for (int i = 1; i < argc; i++) - cli_call << " " << argv[i]; - } - - std::cerr << "[ros_ign_bridge] is deprecated! " - << "Redirecting to use [ros_gz_bridge] instead!" - << std::endl << std::endl; - system(cli_call.str().c_str()); - - return 0; -} diff --git a/ros_ign_bridge/src/static_bridge_shim.cpp b/ros_ign_bridge/src/static_bridge_shim.cpp deleted file mode 100644 index 4ee0fdde..00000000 --- a/ros_ign_bridge/src/static_bridge_shim.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Shim to redirect "ros_ign_bridge static_bridge" call to "ros_gz_bridge static_bridge" - -#include -#include -#include - -#include - - -int main(int argc, char * argv[]) -{ - std::stringstream cli_call; - - cli_call << ament_index_cpp::get_package_prefix("ros_gz_bridge") - << "/lib/ros_gz_bridge/static_bridge"; - - if (argc > 1) - { - for (int i = 1; i < argc; i++) - cli_call << " " << argv[i]; - } - - std::cerr << "[ros_ign_bridge] is deprecated! " - << "Redirecting to use [ros_gz_bridge] instead!" - << std::endl << std::endl; - system(cli_call.str().c_str()); - - return 0; -} diff --git a/ros_ign_gazebo/CHANGELOG.rst b/ros_ign_gazebo/CHANGELOG.rst deleted file mode 100644 index 90c00480..00000000 --- a/ros_ign_gazebo/CHANGELOG.rst +++ /dev/null @@ -1,50 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign_gazebo -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- -* Add support for Harmonic/Humble pairing (`#462 `_) -* Contributors: Addisu Z. Taddese - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- -* Fix launch substitutions for ign_args (`#309 `_) - * Fix launch substitutions for ign_args -* Merge branch 'ros2' into ports/galactic_to_ros2 -* Merge branch 'galactic' into ports/galactic_to_ros2 -* Add ROS2 version of Stopwatch (`#287 `_) -* Add debugger option in launch (`#286 `_) - * add debugger option in launch - * remove xterm dependency; rely on x-terminal-emulator from update-alternatives -* [galactic] Backport: Add std_msgs as dependency of ros_ign_gazebo (`#264 `_) - Co-authored-by: Kenji Brameld -* Contributors: Michael Carroll, andermi - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* Fix missing msgs include and packages.xml deps (`#292 `_) - * Fix missing msgs include and packages.xml deps - * Add additional conditions to support gz sim invocation - * Fix cpplint -* Add missing GZ_VERSION ticktocks (`#289 `_) -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign_gazebo/CMakeLists.txt b/ros_ign_gazebo/CMakeLists.txt deleted file mode 100644 index 52fefe61..00000000 --- a/ros_ign_gazebo/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(ros_ign_gazebo) - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") -endif() - -find_package(ament_cmake REQUIRED) -find_package(ament_index_cpp REQUIRED) - -add_executable(create - src/create_shim.cpp -) -ament_target_dependencies(create ament_index_cpp) - -ament_export_dependencies( - ament_index_cpp - ros_gz_bridge -) - -# TODO(CH3): Deprecated. Remove on tock. -if("$ENV{GZ_VERSION}" STREQUAL "" AND NOT "$ENV{IGNITION_VERSION}" STREQUAL "") - message(DEPRECATION "Environment variable [IGNITION_VERSION] is deprecated. Use [GZ_VERSION] instead.") - set(ENV{GZ_VERSION} $ENV{IGNITION_VERSION}) -endif() - -# Edifice -if("$ENV{GZ_VERSION}" STREQUAL "edifice") - find_package(ignition-gazebo5 REQUIRED) - message(STATUS "Compiling against Gazebo Edifice") -# Garden -elseif("$ENV{GZ_VERSION}" STREQUAL "garden") - find_package(gz-sim7 REQUIRED) - message(STATUS "Compiling against Gazebo Garden") -elseif("$ENV{GZ_VERSION}" STREQUAL "harmonic") - find_package(gz-sim8 REQUIRED) - message(STATUS "Compiling against Gazebo Harmonic") -# Default to Fortress -else() - find_package(ignition-gazebo6 REQUIRED) - message(STATUS "Compiling against Gazebo Fortress") -endif() - -install(FILES - "${CMAKE_CURRENT_SOURCE_DIR}/launch/ign_gazebo.launch.py" - DESTINATION share/${PROJECT_NAME}/launch -) - -install(TARGETS - create - DESTINATION lib/${PROJECT_NAME} -) - -ament_package() diff --git a/ros_ign_gazebo/README.md b/ros_ign_gazebo/README.md deleted file mode 100644 index 2df45d4a..00000000 --- a/ros_ign_gazebo/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim package -For [ros_gz_sim](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_sim) diff --git a/ros_ign_gazebo/launch/ign_gazebo.launch.py b/ros_ign_gazebo/launch/ign_gazebo.launch.py deleted file mode 100644 index e8cb5342..00000000 --- a/ros_ign_gazebo/launch/ign_gazebo.launch.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2020 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Launch Gazebo Sim with command line arguments.""" - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - -def generate_launch_description(): - ros_gz_sim_dir = get_package_share_directory('ros_gz_sim') - launch_dir = os.path.join(ros_gz_sim_dir, 'launch') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource(os.path.join(launch_dir, 'gz_sim.launch.py')) - ) - ]) diff --git a/ros_ign_gazebo/package.xml b/ros_ign_gazebo/package.xml deleted file mode 100644 index 12d7813c..00000000 --- a/ros_ign_gazebo/package.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - ros_ign_gazebo - 0.244.12 - Shim package to redirect to ros_gz_sim. - Brandon Ong - - Apache 2.0 - - ament_cmake - ament_index_cpp - - ros_gz_sim - - - ament_cmake - - diff --git a/ros_ign_gazebo/src/create_shim.cpp b/ros_ign_gazebo/src/create_shim.cpp deleted file mode 100644 index 8a6d366a..00000000 --- a/ros_ign_gazebo/src/create_shim.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Shim to redirect "ros_ign_bridge parameter_bridge" call to "ros_gz_sim parameter_bridge" - -#include -#include -#include - -#include - - -int main(int argc, char * argv[]) -{ - std::stringstream cli_call; - - cli_call << ament_index_cpp::get_package_prefix("ros_gz_sim") - << "/lib/ros_gz_sim/create"; - - if (argc > 1) - { - for (int i = 1; i < argc; i++) - cli_call << " " << argv[i]; - } - - std::cerr << "[ros_ign_gazebo] is deprecated! " - << "Redirecting to use [ros_gz_sim] instead!" - << std::endl << std::endl; - system(cli_call.str().c_str()); - - return 0; -} diff --git a/ros_ign_gazebo_demos/CHANGELOG.rst b/ros_ign_gazebo_demos/CHANGELOG.rst deleted file mode 100644 index 1e8aeaab..00000000 --- a/ros_ign_gazebo_demos/CHANGELOG.rst +++ /dev/null @@ -1,38 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign_gazebo_demos -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- -* Humbly bringing the Joy to gazebo. (`#353 `_) -* Contributors: Benjamin Perseghetti - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- -* Merge branch 'galactic' into ports/galactic_to_ros2 -* Port NavSat (`#224 `_) from ROS 1 to ROS 2 (`#268 `_) - Co-authored-by: Tyler Howell <76003804+TyHowellWork@users.noreply.github.com> -* Contributors: Michael Carroll - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign_gazebo_demos/CMakeLists.txt b/ros_ign_gazebo_demos/CMakeLists.txt deleted file mode 100644 index 68b53fed..00000000 --- a/ros_ign_gazebo_demos/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(ros_ign_gazebo_demos) - -find_package(ament_cmake REQUIRED) - -if(BUILD_TESTING) - find_package(ament_lint_auto REQUIRED) - ament_lint_auto_find_test_dependencies() -endif() - -install( - DIRECTORY - launch/ - DESTINATION share/${PROJECT_NAME}/launch -) - -ament_package() diff --git a/ros_ign_gazebo_demos/README.md b/ros_ign_gazebo_demos/README.md deleted file mode 100644 index 18ccd424..00000000 --- a/ros_ign_gazebo_demos/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim package -For [ros_gz_sim_demos](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_sim_demos) diff --git a/ros_ign_gazebo_demos/launch/air_pressure.launch.py b/ros_ign_gazebo_demos/launch/air_pressure.launch.py deleted file mode 100644 index f2e97f76..00000000 --- a/ros_ign_gazebo_demos/launch/air_pressure.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'air_pressure.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/battery.launch.py b/ros_ign_gazebo_demos/launch/battery.launch.py deleted file mode 100644 index b85a0f21..00000000 --- a/ros_ign_gazebo_demos/launch/battery.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'battery.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/camera.launch.py b/ros_ign_gazebo_demos/launch/camera.launch.py deleted file mode 100644 index 40cf2132..00000000 --- a/ros_ign_gazebo_demos/launch/camera.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'camera.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/depth_camera.launch.py b/ros_ign_gazebo_demos/launch/depth_camera.launch.py deleted file mode 100644 index 0eda5b4b..00000000 --- a/ros_ign_gazebo_demos/launch/depth_camera.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'depth_camera.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/diff_drive.launch.py b/ros_ign_gazebo_demos/launch/diff_drive.launch.py deleted file mode 100644 index aa1f70ad..00000000 --- a/ros_ign_gazebo_demos/launch/diff_drive.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'diff_drive.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/gpu_lidar.launch.py b/ros_ign_gazebo_demos/launch/gpu_lidar.launch.py deleted file mode 100644 index 49df9285..00000000 --- a/ros_ign_gazebo_demos/launch/gpu_lidar.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'gpu_lidar.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/gpu_lidar_bridge.launch.py b/ros_ign_gazebo_demos/launch/gpu_lidar_bridge.launch.py deleted file mode 100644 index d4c89975..00000000 --- a/ros_ign_gazebo_demos/launch/gpu_lidar_bridge.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'gpu_lidar_bridge.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/image_bridge.launch.py b/ros_ign_gazebo_demos/launch/image_bridge.launch.py deleted file mode 100644 index 421a1c08..00000000 --- a/ros_ign_gazebo_demos/launch/image_bridge.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'image_bridge.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/imu.launch.py b/ros_ign_gazebo_demos/launch/imu.launch.py deleted file mode 100644 index 6a580aef..00000000 --- a/ros_ign_gazebo_demos/launch/imu.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'imu.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/joint_states.launch.py b/ros_ign_gazebo_demos/launch/joint_states.launch.py deleted file mode 100644 index 004a8800..00000000 --- a/ros_ign_gazebo_demos/launch/joint_states.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'joint_states.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/magnetometer.launch.py b/ros_ign_gazebo_demos/launch/magnetometer.launch.py deleted file mode 100644 index 3b66da7c..00000000 --- a/ros_ign_gazebo_demos/launch/magnetometer.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'magnetometer.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/rgbd_camera.launch.py b/ros_ign_gazebo_demos/launch/rgbd_camera.launch.py deleted file mode 100644 index ba3e890b..00000000 --- a/ros_ign_gazebo_demos/launch/rgbd_camera.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'rgbd_camera.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/rgbd_camera_bridge.launch.py b/ros_ign_gazebo_demos/launch/rgbd_camera_bridge.launch.py deleted file mode 100644 index d7812aac..00000000 --- a/ros_ign_gazebo_demos/launch/rgbd_camera_bridge.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'rgbd_camera_bridge.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/robot_description_publisher.launch.py b/ros_ign_gazebo_demos/launch/robot_description_publisher.launch.py deleted file mode 100755 index f2158c69..00000000 --- a/ros_ign_gazebo_demos/launch/robot_description_publisher.launch.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join( - pkg_ros_gz_sim_demos, - 'launch', - 'robot_description_publisher.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/tf_bridge.launch.py b/ros_ign_gazebo_demos/launch/tf_bridge.launch.py deleted file mode 100644 index 2b6fd52f..00000000 --- a/ros_ign_gazebo_demos/launch/tf_bridge.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'tf_bridge.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/launch/triggered_camera.launch.py b/ros_ign_gazebo_demos/launch/triggered_camera.launch.py deleted file mode 100644 index b5a852c5..00000000 --- a/ros_ign_gazebo_demos/launch/triggered_camera.launch.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from ament_index_python.packages import get_package_share_directory - -from launch import LaunchDescription -from launch.actions import IncludeLaunchDescription -from launch.launch_description_sources import PythonLaunchDescriptionSource - - -def generate_launch_description(): - print('ros_ign_gazebo_demos is deprecated! Please use ros_gz_sim_demos instead!') - - pkg_ros_gz_sim_demos = get_package_share_directory('ros_gz_sim_demos') - - return LaunchDescription([ - IncludeLaunchDescription( - PythonLaunchDescriptionSource( - os.path.join(pkg_ros_gz_sim_demos, 'launch', 'triggered_camera.launch.py')), - ) - ]) diff --git a/ros_ign_gazebo_demos/package.xml b/ros_ign_gazebo_demos/package.xml deleted file mode 100644 index e72072b1..00000000 --- a/ros_ign_gazebo_demos/package.xml +++ /dev/null @@ -1,17 +0,0 @@ - - ros_ign_gazebo_demos - 0.244.12 - Shim package to redirect to ros_gz_sim_demos. - Apache 2.0 - Brandon Ong - - ament_cmake - ros_gz_sim_demos - - ament_lint_auto - ament_lint_common - - - ament_cmake - - diff --git a/ros_ign_image/CHANGELOG.rst b/ros_ign_image/CHANGELOG.rst deleted file mode 100644 index 216a751d..00000000 --- a/ros_ign_image/CHANGELOG.rst +++ /dev/null @@ -1,34 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign_image -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- -* Merge branch 'ros2' into ports/galactic_to_ros2 -* Contributors: Michael Carroll - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign_image/CMakeLists.txt b/ros_ign_image/CMakeLists.txt deleted file mode 100644 index 5fa4b91b..00000000 --- a/ros_ign_image/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(ros_ign_image) - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") -endif() - -find_package(ament_cmake REQUIRED) -find_package(ament_index_cpp REQUIRED) - -add_executable(image_bridge src/image_bridge_shim.cpp) -ament_target_dependencies(image_bridge ament_index_cpp) - -ament_export_dependencies(ament_index_cpp ros_gz_image) - -install(TARGETS - image_bridge - DESTINATION lib/${PROJECT_NAME} -) - -ament_package() diff --git a/ros_ign_image/README.md b/ros_ign_image/README.md deleted file mode 100644 index 517ccdd8..00000000 --- a/ros_ign_image/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim package -For [ros_gz_image](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_image) diff --git a/ros_ign_image/package.xml b/ros_ign_image/package.xml deleted file mode 100644 index 2ed549db..00000000 --- a/ros_ign_image/package.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - ros_ign_image - 0.244.12 - Shim package to redirect to ros_gz_image. - Brandon Ong - - Apache 2.0 - - ament_cmake - ament_index_cpp - - ros_gz_image - - - ament_cmake - - diff --git a/ros_ign_image/src/image_bridge_shim.cpp b/ros_ign_image/src/image_bridge_shim.cpp deleted file mode 100644 index 0d44a1cb..00000000 --- a/ros_ign_image/src/image_bridge_shim.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Shim to redirect "ros_ign_image image_bridge" call to "ros_gz_image image_bridge" - -#include -#include -#include - -#include - - -int main(int argc, char * argv[]) -{ - std::stringstream cli_call; - - cli_call << ament_index_cpp::get_package_prefix("ros_gz_image") - << "/lib/ros_gz_image/image_bridge"; - - if (argc > 1) - { - for (int i = 1; i < argc; i++) - cli_call << " " << argv[i]; - } - - std::cerr << "[ros_ign_bridge] is deprecated! " - << "Redirecting to use [ros_gz_image] instead!" - << std::endl << std::endl; - system(cli_call.str().c_str()); - - return 0; -} diff --git a/ros_ign_interfaces/CHANGELOG.rst b/ros_ign_interfaces/CHANGELOG.rst deleted file mode 100644 index 663c713b..00000000 --- a/ros_ign_interfaces/CHANGELOG.rst +++ /dev/null @@ -1,49 +0,0 @@ -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Changelog for package ros_ign_interfaces -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -0.244.12 (2023-12-13) ---------------------- - -0.244.11 (2023-05-23) ---------------------- - -0.244.10 (2023-05-03) ---------------------- - -0.244.9 (2022-11-03) --------------------- - -0.244.8 (2022-10-28) --------------------- - -0.244.7 (2022-10-12) --------------------- -* Merge branch 'ros2' into ports/galactic_to_ros2 -* Merge branch 'galactic' into ports/galactic_to_ros2 -* Add ParamVec and bridge from Ignition (`#261 `_) - * Introduces `ros_ign_interfaces::msg::ParamVec` for storing a list of Parameters that are int, bool, double, or string. - * Introduces bridge for `ignition::msgs::param` to `ros_ign_interfaces::msg::ParamVec` - * Introduces bridge for `ignition::msgs::param_v` to `ros_ign_interfaces::msg::ParamVec` -* Add rssi to Dataframe.msg (`#249 `_) - * Adding rssi field to ros_ign_interfaces/Dataframe.msg -* [galactic] Backport GuiCamera, StringVec, TrackVisual, VideoRecord (`#241 `_) - * [ros_ign_interfaces] Add more interface definitions. - * Add converion functions for the added messages - * Update the factory factory function with the new messages - * Add new messages to docs - * Add test cases for the new messages conversions - Co-authored-by: Ivan Santiago Paunovic -* Add Dataframe message and bridging (`#239 `_) -* Contributors: Carlos Agüero, Michael Carroll - -0.244.6 (2022-09-14) --------------------- -* Restructured directories (`#296 `_) -* Contributors: Alejandro Hernández Cordero - -0.244.5 (2022-09-12) --------------------- -* ign -> gz : ros_gz Migration (Shims) (`#281 `_) - Co-authored-by: Louise Poubel -* Contributors: methylDragon diff --git a/ros_ign_interfaces/CMakeLists.txt b/ros_ign_interfaces/CMakeLists.txt deleted file mode 100644 index b397466b..00000000 --- a/ros_ign_interfaces/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(ros_ign_interfaces) - -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -find_package(ament_cmake REQUIRED) -find_package(builtin_interfaces REQUIRED) -find_package(std_msgs REQUIRED) -find_package(geometry_msgs REQUIRED) -find_package(ros_gz_interfaces REQUIRED) -find_package(rosidl_default_generators REQUIRED) - -set(msg_files - "msg/Contact.msg" - "msg/Contacts.msg" - "msg/Entity.msg" - "msg/EntityFactory.msg" - "msg/GuiCamera.msg" - "msg/JointWrench.msg" - "msg/Light.msg" - "msg/StringVec.msg" - "msg/TrackVisual.msg" - "msg/VideoRecord.msg" - "msg/WorldControl.msg" - "msg/WorldReset.msg" -) - -set(srv_files - "srv/ControlWorld.srv" - "srv/DeleteEntity.srv" - "srv/SetEntityPose.srv" - "srv/SpawnEntity.srv" -) - -rosidl_generate_interfaces(${PROJECT_NAME} - ${msg_files} - ${srv_files} - DEPENDENCIES builtin_interfaces std_msgs geometry_msgs ros_gz_interfaces - ADD_LINTER_TESTS -) - -ament_export_dependencies(rosidl_default_runtime) -ament_package() diff --git a/ros_ign_interfaces/README.md b/ros_ign_interfaces/README.md deleted file mode 100644 index 15a7fafb..00000000 --- a/ros_ign_interfaces/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# This is a shim package -For [ros_gz_interfaces](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_interfaces) diff --git a/ros_ign_interfaces/msg/Contact.msg b/ros_ign_interfaces/msg/Contact.msg deleted file mode 100644 index 98d2cef8..00000000 --- a/ros_ign_interfaces/msg/Contact.msg +++ /dev/null @@ -1,6 +0,0 @@ -ros_gz_interfaces/Entity collision1 # Contact collision1 -ros_gz_interfaces/Entity collision2 # Contact collision2 -geometry_msgs/Vector3[] positions # List of contact position -geometry_msgs/Vector3[] normals # List of contact normals -float64[] depths # List of penetration depths -ros_gz_interfaces/JointWrench[] wrenches # List of joint wrenches including forces/torques diff --git a/ros_ign_interfaces/msg/Contacts.msg b/ros_ign_interfaces/msg/Contacts.msg deleted file mode 100644 index 40232e51..00000000 --- a/ros_ign_interfaces/msg/Contacts.msg +++ /dev/null @@ -1,2 +0,0 @@ -std_msgs/Header header # Time stamp -ros_gz_interfaces/Contact[] contacts # List of contacts diff --git a/ros_ign_interfaces/msg/Entity.msg b/ros_ign_interfaces/msg/Entity.msg deleted file mode 100644 index b785c7ed..00000000 --- a/ros_ign_interfaces/msg/Entity.msg +++ /dev/null @@ -1,13 +0,0 @@ -# Entity type: constant definition -uint8 NONE = 0 -uint8 LIGHT = 1 -uint8 MODEL = 2 -uint8 LINK = 3 -uint8 VISUAL = 4 -uint8 COLLISION = 5 -uint8 SENSOR = 6 -uint8 JOINT = 7 - -uint64 id # Entity unique identifier accross all types. Defaults to 0 -string name # Entity name, which is not guaranteed to be unique. -uint8 type # Entity type. diff --git a/ros_ign_interfaces/msg/EntityFactory.msg b/ros_ign_interfaces/msg/EntityFactory.msg deleted file mode 100644 index 4576c003..00000000 --- a/ros_ign_interfaces/msg/EntityFactory.msg +++ /dev/null @@ -1,11 +0,0 @@ -string name # New name for the entity, overrides the name on the SDF -bool allow_renaming false # Whether the server is allowed to rename the entity in case of - # overlap with existing entities. - -# Only one method is supported at a time (sdf,sdf_filename,clone_name) -string sdf # SDF description in string format -string sdf_filename # Full path to SDF file. -string clone_name # Name of entity to clone - -geometry_msgs/Pose pose # Pose where the entity will be spawned in the world. -string relative_to "world" # Pose is defined relative to the frame of this entity. diff --git a/ros_ign_interfaces/msg/GuiCamera.msg b/ros_ign_interfaces/msg/GuiCamera.msg deleted file mode 100644 index d45fd9b8..00000000 --- a/ros_ign_interfaces/msg/GuiCamera.msg +++ /dev/null @@ -1,12 +0,0 @@ -# Message for a GUI Camera. - -# Optional header data. -std_msgs/Header header - -string name -string view_controller -geometry_msgs/Pose pose -TrackVisual track - -# Type of projection: "perspective" or "orthographic". -string projection_type diff --git a/ros_ign_interfaces/msg/JointWrench.msg b/ros_ign_interfaces/msg/JointWrench.msg deleted file mode 100644 index 2da89094..00000000 --- a/ros_ign_interfaces/msg/JointWrench.msg +++ /dev/null @@ -1,8 +0,0 @@ -std_msgs/Header header # Time stamp -std_msgs/String body_1_name # Body 1 name string -std_msgs/UInt32 body_1_id # Body 1 id -std_msgs/String body_2_name # Body 2 name string -std_msgs/UInt32 body_2_id # Body 2 id - -geometry_msgs/Wrench body_1_wrench # Body 1 wrench -geometry_msgs/Wrench body_2_wrench # Body 2 wrench diff --git a/ros_ign_interfaces/msg/Light.msg b/ros_ign_interfaces/msg/Light.msg deleted file mode 100644 index 911e20bd..00000000 --- a/ros_ign_interfaces/msg/Light.msg +++ /dev/null @@ -1,29 +0,0 @@ -std_msgs/Header header # Optional header data - -string name # Light name - -# Light type: constant definition -uint8 POINT = 0 -uint8 SPOT = 1 -uint8 DIRECTIONAL = 2 - -uint8 type # Light type (from constant definitions) - -geometry_msgs/Pose pose # Light pose -std_msgs/ColorRGBA diffuse # Light diffuse emission -std_msgs/ColorRGBA specular # Light specular emission -float32 attenuation_constant # Constant variable in attenuation formula -float32 attenuation_linear # Linear variable in attenuation formula -float32 attenuation_quadratic # Quadratic variable in attenuation formula -geometry_msgs/Vector3 direction # Light direction -float32 range # Light range -bool cast_shadows # Enable/disable shadow casting -float32 spot_inner_angle # Spotlight inner cone angle -float32 spot_outer_angle # Spotlight outer cone angle -float32 spot_falloff # Falloff between inner and outer cone - -uint32 id # Unique id of the light - -uint32 parent_id # Unique id of the light's parent - -float32 intensity # Light intensity diff --git a/ros_ign_interfaces/msg/StringVec.msg b/ros_ign_interfaces/msg/StringVec.msg deleted file mode 100644 index 15a7dda9..00000000 --- a/ros_ign_interfaces/msg/StringVec.msg +++ /dev/null @@ -1,7 +0,0 @@ -# A message for a vector of string data. - -# Optional header data. -std_msgs/Header header - -# The vector of strings. -string[] data diff --git a/ros_ign_interfaces/msg/TrackVisual.msg b/ros_ign_interfaces/msg/TrackVisual.msg deleted file mode 100644 index c09f4785..00000000 --- a/ros_ign_interfaces/msg/TrackVisual.msg +++ /dev/null @@ -1,33 +0,0 @@ -# Message for a tracking a rendering::Visual with a rendering::Camera. - -# Optional header data. -std_msgs/Header header - -# Name of the visual to track. -string name - -# Id of the visual to track. -uint32 id - -# True to have the tracking camera inherit the orientation of -# the tracked visual. -bool inherit_orientation - -# Minimum follow distance. -float64 min_dist - -# Maximum follow distance. -float64 max_dist - -# If set to true, the position of the camera is fixed. -bool is_static - -# If set to true, the position of the camera is relative to the. -# model reference frame. -bool use_model_frame - -# Position of the camera. -geometry_msgs/Vector3 xyz - -# If set to true, the camera inherits the yaw rotation of the model. -bool inherit_yaw diff --git a/ros_ign_interfaces/msg/VideoRecord.msg b/ros_ign_interfaces/msg/VideoRecord.msg deleted file mode 100644 index 02bafde0..00000000 --- a/ros_ign_interfaces/msg/VideoRecord.msg +++ /dev/null @@ -1,16 +0,0 @@ -# A message that allows for control of video recording functions. - -# Optional header data. -std_msgs/Header header - -# True to start video recording. -bool start - -# True to stop video recording. -bool stop - -# Video encoding format, e.g. "mp4", "ogv". -string format - -# filename of the recorded video. -string save_filename diff --git a/ros_ign_interfaces/msg/WorldControl.msg b/ros_ign_interfaces/msg/WorldControl.msg deleted file mode 100644 index efa22fb9..00000000 --- a/ros_ign_interfaces/msg/WorldControl.msg +++ /dev/null @@ -1,7 +0,0 @@ -bool pause # Paused state. -bool step # -uint32 multi_step 0 # Paused after stepping multi_step. -ros_gz_interfaces/WorldReset reset # -uint32 seed # -builtin_interfaces/Time run_to_sim_time # A simulation time in the future to run to and - # then pause. diff --git a/ros_ign_interfaces/msg/WorldReset.msg b/ros_ign_interfaces/msg/WorldReset.msg deleted file mode 100644 index 46f5971f..00000000 --- a/ros_ign_interfaces/msg/WorldReset.msg +++ /dev/null @@ -1,3 +0,0 @@ -bool all false # Reset time and model -bool time_only false # Reset time only -bool model_only false # Reset model only diff --git a/ros_ign_interfaces/package.xml b/ros_ign_interfaces/package.xml deleted file mode 100644 index d584960a..00000000 --- a/ros_ign_interfaces/package.xml +++ /dev/null @@ -1,27 +0,0 @@ - - ros_ign_interfaces - 0.244.12 - Shim package to redirect to ros_gz_interfaces. - Apache 2.0 - Brandon Ong - Zhenpeng Ge - ament_cmake - rosidl_default_generators - - builtin_interfaces - ros_gz_interfaces - std_msgs - geometry_msgs - - builtin_interfaces - ros_gz_interfaces - std_msgs - geometry_msgs - rosidl_default_runtime - - ament_lint_common - rosidl_interface_packages - - ament_cmake - - diff --git a/ros_ign_interfaces/srv/ControlWorld.srv b/ros_ign_interfaces/srv/ControlWorld.srv deleted file mode 100644 index d8e41f24..00000000 --- a/ros_ign_interfaces/srv/ControlWorld.srv +++ /dev/null @@ -1,3 +0,0 @@ -ros_gz_interfaces/WorldControl world_control # Message to Control world in Gazebo Sim ---- -bool success # Return true if control is successful. diff --git a/ros_ign_interfaces/srv/DeleteEntity.srv b/ros_ign_interfaces/srv/DeleteEntity.srv deleted file mode 100644 index 13b3e1fd..00000000 --- a/ros_ign_interfaces/srv/DeleteEntity.srv +++ /dev/null @@ -1,3 +0,0 @@ -ros_gz_interfaces/Entity entity # Gazebo Sim entity to be deleted. ---- -bool success # Return true if deletion is successful. diff --git a/ros_ign_interfaces/srv/SetEntityPose.srv b/ros_ign_interfaces/srv/SetEntityPose.srv deleted file mode 100644 index b749488c..00000000 --- a/ros_ign_interfaces/srv/SetEntityPose.srv +++ /dev/null @@ -1,4 +0,0 @@ -ros_gz_interfaces/Entity entity # Gazebo Sim entity. -geometry_msgs/Pose pose # Pose of entity. ---- -bool success # Return true if set successfully. diff --git a/ros_ign_interfaces/srv/SpawnEntity.srv b/ros_ign_interfaces/srv/SpawnEntity.srv deleted file mode 100644 index 35d5df59..00000000 --- a/ros_ign_interfaces/srv/SpawnEntity.srv +++ /dev/null @@ -1,3 +0,0 @@ -ros_gz_interfaces/EntityFactory entity_factory # Message to create a new entity ---- -bool success # Return true if spawned successfully. diff --git a/test_ros_gz_bridge/CHANGELOG.rst b/test_ros_gz_bridge/CHANGELOG.rst new file mode 100644 index 00000000..4f295f2c --- /dev/null +++ b/test_ros_gz_bridge/CHANGELOG.rst @@ -0,0 +1,20 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package test_ros_gz_bridge +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +2.0.0 (2024-07-22) +------------------ + +1.0.1 (2024-07-03) +------------------ +* Prepare for 1.0.0 Release (`#495 `_) +* 0.244.14 +* Changelog +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) (`#506 `_) +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) +* Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero, Michael Carroll + +1.0.0 (2024-04-24) +------------------ +* Correctly export ros_gz_bridge for downstream targets (`#503 `_) +* Contributors: Michael Carroll diff --git a/test_ros_gz_bridge/CMakeLists.txt b/test_ros_gz_bridge/CMakeLists.txt new file mode 100644 index 00000000..9a3bb8a8 --- /dev/null +++ b/test_ros_gz_bridge/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.5) + +project(test_ros_gz_bridge) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") +endif() + +find_package(ament_cmake REQUIRED) +find_package(ros_gz_bridge REQUIRED) + + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() + + find_package(ament_cmake_gtest REQUIRED) + find_package(launch_testing_ament_cmake REQUIRED) + ament_find_gtest() + + ament_add_gtest(test_ros_gz_bridge src/test_ros_gz_bridge.cpp) + target_link_libraries(test_ros_gz_bridge ros_gz_bridge::ros_gz_bridge) +endif() + +ament_package() diff --git a/test_ros_gz_bridge/package.xml b/test_ros_gz_bridge/package.xml new file mode 100644 index 00000000..f9786ed0 --- /dev/null +++ b/test_ros_gz_bridge/package.xml @@ -0,0 +1,28 @@ + + + + test_ros_gz_bridge + 2.0.0 + Bridge communication between ROS and Gazebo Transport + Aditya Pande + Alejandro Hernandez + + Apache 2.0 + + Michael Carroll + + ament_cmake + + ros_gz_bridge + + ament_cmake_gtest + ament_lint_auto + ament_lint_common + launch_testing_ament_cmake + launch_ros + launch_testing + + + ament_cmake + + diff --git a/test_ros_gz_bridge/src/test_ros_gz_bridge.cpp b/test_ros_gz_bridge/src/test_ros_gz_bridge.cpp new file mode 100644 index 00000000..a32ca8e5 --- /dev/null +++ b/test_ros_gz_bridge/src/test_ros_gz_bridge.cpp @@ -0,0 +1,36 @@ +// Copyright 2024 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +class test_ros_gz_bridge : public ::testing::Test +{ +public: + static void SetUpTestCase() + { + rclcpp::init(0, nullptr); + } + + static void TearDownTestCase() + { + rclcpp::shutdown(); + } +}; + +TEST_F(test_ros_gz_bridge, SpawnNode) +{ + ros_gz_bridge::RosGzBridge node; +}