From ba4e7cf0489c7dec6ea5f5aa3607744a48b4bcf3 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 7 Dec 2022 02:12:37 -0800 Subject: [PATCH] [drake_ros_tf2] Add BUILD.bazel and WORKSPACE (#200) Use rmw_isolation Use legacy_create_init to workaround https://github.com/bazelbuild/bazel/issues/7386 Add TODO about ODR violations Use C++17 --- drake_ros_tf2/.bazelrc | 6 ++ drake_ros_tf2/BUILD.bazel | 107 ++++++++++++++++++++++ drake_ros_tf2/CMakeLists.txt | 5 + drake_ros_tf2/WORKSPACE | 59 ++++++++++++ drake_ros_tf2/test/test_tf_broadcaster.cc | 17 ++++ 5 files changed, 194 insertions(+) create mode 100644 drake_ros_tf2/.bazelrc create mode 100644 drake_ros_tf2/BUILD.bazel create mode 100644 drake_ros_tf2/WORKSPACE diff --git a/drake_ros_tf2/.bazelrc b/drake_ros_tf2/.bazelrc new file mode 100644 index 00000000..e9ed6f2d --- /dev/null +++ b/drake_ros_tf2/.bazelrc @@ -0,0 +1,6 @@ +# Use C++17. +build --cxxopt=-std=c++17 +build --host_cxxopt=-std=c++17 + +# Put ROS logs into /tmp +build --action_env=ROS_HOME=/tmp/.ros diff --git a/drake_ros_tf2/BUILD.bazel b/drake_ros_tf2/BUILD.bazel new file mode 100644 index 00000000..7d4ef1cc --- /dev/null +++ b/drake_ros_tf2/BUILD.bazel @@ -0,0 +1,107 @@ +# 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. + +load("@ros2//:ros_cc.bzl", "ros_cc_test") +load("@ros2//:ros_py.bzl", "ros_py_test") +load( + "@drake//tools/skylark:pybind.bzl", + "pybind_py_library", +) + +PYBIND_EXCLUDES = [ + "**/*_py.cc", + "**/*_pybind.h", +] + +# TODO(sloretz) more granular targets for static linking +cc_library( + name = "drake_ros_tf2", + srcs = glob( + [ + "src/*.cc", + "src/*.h", + ], + exclude = PYBIND_EXCLUDES, + ), + hdrs = glob( + ["include/**/*.h"], + exclude = PYBIND_EXCLUDES, + ), + strip_include_prefix = "include", + visibility = ["//visibility:public"], + deps = [ + "@drake//geometry:scene_graph_inspector", + "@drake//multibody/plant", + "@drake_ros_core", + "@ros2//:geometry_msgs_cc", + "@ros2//:rclcpp_cc", + "@ros2//:tf2_ros_cc", + ], +) + +ros_cc_test( + name = "test_tf_broadcaster", + size = "small", + srcs = ["test/test_tf_broadcaster.cc"], + rmw_implementation = "rmw_cyclonedds_cpp", + deps = [ + ":drake_ros_tf2", + "@com_google_googletest//:gtest_main", + "@drake//common", + "@drake//systems/primitives", + "@ros2//:geometry_msgs_cc", + "@ros2//:rclcpp_cc", + "@ros2//:tf2_ros_cc", + "@ros2//resources/rmw_isolation:rmw_isolation_cc", + ], +) + +cc_library( + name = "python_bindings_internal_hdrs", + hdrs = glob(["include/**/*_pybind.h"]), + strip_include_prefix = "include/", +) + +pybind_py_library( + name = "drake_ros_tf2_py", + cc_deps = [ + # TODO(sloretz) - depend on a shared library target + # This links statically, and so can lead to ODR violations if the + # python and C++ libraries are depended upon by the same python target. + ":drake_ros_tf2", + ":python_bindings_internal_hdrs", + ], + cc_so_name = "drake_ros_tf2", + cc_srcs = glob(["src/**/*_py.cc"]), + py_deps = [ + "@drake_ros_core//:drake_ros_core_py", + ], + py_imports = ["src"], + py_srcs = glob(["src/drake_ros_tf2/**/*.py"]), + visibility = ["//visibility:public"], +) + +ros_py_test( + name = "test_tf_broadcaster_py", + srcs = ["test/test_tf_broadcaster.py"], + legacy_create_init = False, + main = "test/test_tf_broadcaster.py", + deps = [ + ":drake_ros_tf2_py", + "@drake//bindings/pydrake", + "@ros2//:rclpy_py", + "@ros2//:tf2_ros_py_py", + "@ros2//resources/rmw_isolation:rmw_isolation_py", + ], +) diff --git a/drake_ros_tf2/CMakeLists.txt b/drake_ros_tf2/CMakeLists.txt index 64a16eb1..e68d5f37 100644 --- a/drake_ros_tf2/CMakeLists.txt +++ b/drake_ros_tf2/CMakeLists.txt @@ -109,6 +109,11 @@ if(BUILD_TESTING) tf2_ros::tf2_ros ${geometry_msgs_TARGETS} ) + target_compile_definitions(test_tf_broadcaster + PRIVATE + # We do not expose `rmw_isoliation` via CMake. + _TEST_DISABLE_RMW_ISOLATION + ) ament_add_pytest_test(test_tf_broadcaster_py test/test_tf_broadcaster.py) diff --git a/drake_ros_tf2/WORKSPACE b/drake_ros_tf2/WORKSPACE new file mode 100644 index 00000000..e0a89587 --- /dev/null +++ b/drake_ros_tf2/WORKSPACE @@ -0,0 +1,59 @@ +workspace(name = "drake_ros_tf2") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "com_google_googletest", + sha256 = "5cf189eb6847b4f8fc603a3ffff3b0771c08eec7dd4bd961bfd45477dd13eb73", # noqa + strip_prefix = "googletest-609281088cfefc76f9d0ce82e1ff6c30cc3591e5", + urls = ["https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip"], # noqa +) + +# Use the ROS 2 bazel rules +local_repository( + name = "bazel_ros2_rules", + path = "../bazel_ros2_rules", +) + +load("@bazel_ros2_rules//deps:defs.bzl", "add_bazel_ros2_rules_dependencies") + +add_bazel_ros2_rules_dependencies() + +load("@bazel_ros2_rules//ros2:defs.bzl", "ros2_archive") + +# Use ROS 2 +ros2_archive( + name = "ros2", + include_packages = [ + "geometry_msgs", + "rclcpp", + "tf2_ros", + "tf2_ros_py", + ], + sha256_url = "https://repo.ros2.org/ci_archives/drake-ros-underlay/ros2-humble-linux-focal-amd64-ci-CHECKSUM", # noqa + strip_prefix = "ros2-linux", + url = "http://repo.ros2.org/ci_archives/drake-ros-underlay/ros2-humble-linux-focal-amd64-ci.tar.bz2", # noqa +) + +# Depend on Drake +DRAKE_TAG = "v1.10.0" + +DRAKE_CHECKSUM = "78bd251bcfb349c988ee9225175a803a50cc53eaacdeb3bba200dfc82dcea305" # noqa + +http_archive( + name = "drake", + sha256 = DRAKE_CHECKSUM, + strip_prefix = "drake-{}".format(DRAKE_TAG.lstrip("v")), + urls = [ + "https://github.com/RobotLocomotion/drake/archive/refs/tags/{}.tar.gz".format(DRAKE_TAG), # noqa + ], +) + +load("@drake//tools/workspace:default.bzl", "add_default_workspace") + +add_default_workspace() + +local_repository( + name = "drake_ros_core", + path = "../drake_ros_core", +) diff --git a/drake_ros_tf2/test/test_tf_broadcaster.cc b/drake_ros_tf2/test/test_tf_broadcaster.cc index da876d1b..7e1c1faf 100644 --- a/drake_ros_tf2/test/test_tf_broadcaster.cc +++ b/drake_ros_tf2/test/test_tf_broadcaster.cc @@ -137,3 +137,20 @@ TEST(SceneTfBroadcasting, NominalCase) { EXPECT_TRUE(drake_ros_core::shutdown()); } + +// Only available in Bazel. +#ifndef _TEST_DISABLE_RMW_ISOLATION +#include "rmw_isolation/rmw_isolation.h" + +int main(int argc, char* argv[]) { + const char* TEST_TMPDIR = std::getenv("TEST_TMPDIR"); + if (TEST_TMPDIR != nullptr) { + std::string ros_home = std::string(TEST_TMPDIR) + "/.ros"; + setenv("ROS_HOME", ros_home.c_str(), 1); + ros2::isolate_rmw_by_path(argv[0], TEST_TMPDIR); + } + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +#endif