diff --git a/rosbag2/CMakeLists.txt b/rosbag2/CMakeLists.txt index 407d502b35..2645bc1149 100644 --- a/rosbag2/CMakeLists.txt +++ b/rosbag2/CMakeLists.txt @@ -1,5 +1,50 @@ cmake_minimum_required(VERSION 3.5) project(rosbag2) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_components REQUIRED) +find_package(rosbag2_transport REQUIRED) + +# Library for Rosbag2 composable nodes +add_library(${PROJECT_NAME}_nodes SHARED + src/rosbag2/composable_player.cpp + src/rosbag2/composable_recorder.cpp +) +target_include_directories(${PROJECT_NAME}_nodes PUBLIC + $ + $) + +ament_target_dependencies(${PROJECT_NAME}_nodes rclcpp rclcpp_components rosbag2_transport) + +rclcpp_components_register_node(${PROJECT_NAME}_nodes PLUGIN "rosbag2::Player" EXECUTABLE player) + +rclcpp_components_register_node(${PROJECT_NAME}_nodes PLUGIN "rosbag2::Recorder" EXECUTABLE recorder) + +install(DIRECTORY include/ + DESTINATION include/${PROJECT_NAME} +) + +install( + TARGETS ${PROJECT_NAME}_nodes + EXPORT export_${PROJECT_NAME}_nodes + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +# Export modern CMake targets +ament_export_targets(export_${PROJECT_NAME}_nodes) + ament_package() diff --git a/rosbag2/include/rosbag2/composable_player.hpp b/rosbag2/include/rosbag2/composable_player.hpp new file mode 100644 index 0000000000..7a82097b5d --- /dev/null +++ b/rosbag2/include/rosbag2/composable_player.hpp @@ -0,0 +1,56 @@ +// 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. + +/* This header must be included by all rclcpp headers which declare symbols + * which are defined in the rclcpp library. When not building the rclcpp + * library, i.e. when using the headers in other package's code, the contents + * of this header change the visibility of certain symbols which the rclcpp + * library cannot have, but the consuming code must have inorder to link. + */ + +#ifndef ROSBAG2__COMPOSABLE_PLAYER_HPP_ +#define ROSBAG2__COMPOSABLE_PLAYER_HPP_ + +#include + +#include "rclcpp/node_options.hpp" +#include "rosbag2/visibility_control.hpp" +#include "rosbag2_transport/player.hpp" + +namespace rosbag2 +{ +class Player : public rosbag2_transport::Player { +public: + /// \brief Constructor and entry point for the composable player. + /// Will call Player(node_name, node_options) constructor with node_name = "rosbag2_player". + /// \param node_options Node options which will be used during construction of the underlying + /// node. + ROSBAG2_PUBLIC + explicit Player(const rclcpp::NodeOptions & node_options); + + /// \brief Default constructor and entry point for the composable player. + /// Will construct Player class and initialize play_options, storage_options from node + /// parameters. At the end will call Player::play() to automatically start playback in a + /// separate thread. + /// \param node_name Name for the underlying node. + /// \param node_options Node options which will be used during construction of the underlying + /// node. + ROSBAG2_PUBLIC + explicit Player( + const std::string & node_name = "rosbag2_player", + const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions()); +}; +} // namespace rosbag2 + +#endif // ROSBAG2__COMPOSABLE_PLAYER_HPP_ diff --git a/rosbag2/include/rosbag2/composable_recorder.hpp b/rosbag2/include/rosbag2/composable_recorder.hpp new file mode 100644 index 0000000000..930554bc18 --- /dev/null +++ b/rosbag2/include/rosbag2/composable_recorder.hpp @@ -0,0 +1,56 @@ +// Copyright 2025 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. + +/* This header must be included by all rclcpp headers which declare symbols + * which are defined in the rclcpp library. When not building the rclcpp + * library, i.e. when using the headers in other package's code, the contents + * of this header change the visibility of certain symbols which the rclcpp + * library cannot have, but the consuming code must have inorder to link. + */ + +#ifndef ROSBAG2__COMPOSABLE_RECORDER_HPP_ +#define ROSBAG2__COMPOSABLE_RECORDER_HPP_ + +#include + +#include "rclcpp/node_options.hpp" +#include "rosbag2/visibility_control.hpp" +#include "rosbag2_transport/recorder.hpp" + +namespace rosbag2 +{ +class Recorder : public rosbag2_transport::Recorder { +public: + /// \brief Constructor and entry point for the composable recorder. + /// Will call Recorder(node_name, node_options) constructor with node_name = "rosbag2_recorder". + /// \param node_options Node options which will be used during construction of the underlying + /// node. + ROSBAG2_PUBLIC + explicit Recorder(const rclcpp::NodeOptions & node_options); + + /// \brief Default constructor and entry point for the composable recorder. + /// Will construct Recorder class and initialize play_options, storage_options from node + /// parameters. At the end will call Recorder::play() to automatically start playback in a + /// separate thread. + /// \param node_name Name for the underlying node. + /// \param node_options Node options which will be used during construction of the underlying + /// node. + ROSBAG2_PUBLIC + explicit Recorder( + const std::string & node_name = "rosbag2_recorder", + const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions()); +}; +} // namespace rosbag2 + +#endif // ROSBAG2__COMPOSABLE_RECORDER_HPP_ diff --git a/rosbag2/include/rosbag2/visibility_control.hpp b/rosbag2/include/rosbag2/visibility_control.hpp new file mode 100644 index 0000000000..6070ae721f --- /dev/null +++ b/rosbag2/include/rosbag2/visibility_control.hpp @@ -0,0 +1,56 @@ +// 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. + +/* This header must be included by all rclcpp headers which declare symbols + * which are defined in the rclcpp library. When not building the rclcpp + * library, i.e. when using the headers in other package's code, the contents + * of this header change the visibility of certain symbols which the rclcpp + * library cannot have, but the consuming code must have inorder to link. + */ + +#ifndef ROSBAG2__VISIBILITY_CONTROL_HPP_ +#define ROSBAG2__VISIBILITY_CONTROL_HPP_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ + #define ROSBAG2_EXPORT __attribute__ ((dllexport)) + #define ROSBAG2_IMPORT __attribute__ ((dllimport)) + #else + #define ROSBAG2_EXPORT __declspec(dllexport) + #define ROSBAG2_IMPORT __declspec(dllimport) + #endif + #ifdef ROSBAG2_BUILDING_LIBRARY + #define ROSBAG2_PUBLIC ROSBAG2_EXPORT + #else + #define ROSBAG2_PUBLIC ROSBAG2_IMPORT + #endif + #define ROSBAG2_PUBLIC_TYPE ROSBAG2_PUBLIC + #define ROSBAG2_LOCAL +#else +#define ROSBAG2_EXPORT __attribute__ ((visibility("default"))) +#define ROSBAG2_IMPORT +#if __GNUC__ >= 4 +#define ROSBAG2_PUBLIC __attribute__ ((visibility("default"))) +#define ROSBAG2_LOCAL __attribute__ ((visibility("hidden"))) +#else +#define ROSBAG2_PUBLIC + #define ROSBAG2_LOCAL +#endif +#define ROSBAG2_PUBLIC_TYPE +#endif + +#endif // ROSBAG2__VISIBILITY_CONTROL_HPP_ diff --git a/rosbag2/package.xml b/rosbag2/package.xml index 70c4d62527..34202a1aae 100644 --- a/rosbag2/package.xml +++ b/rosbag2/package.xml @@ -12,12 +12,15 @@ ament_cmake + rclcpp + rclcpp_components + rosbag2_transport + ros2bag rosbag2_compression rosbag2_cpp rosbag2_py rosbag2_storage - rosbag2_transport rosbag2_compression_zstd diff --git a/rosbag2/src/rosbag2/composable_player.cpp b/rosbag2/src/rosbag2/composable_player.cpp new file mode 100644 index 0000000000..37bcb90f40 --- /dev/null +++ b/rosbag2/src/rosbag2/composable_player.cpp @@ -0,0 +1,39 @@ +// 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. + +/* This header must be included by all rclcpp headers which declare symbols + * which are defined in the rclcpp library. When not building the rclcpp + * library, i.e. when using the headers in other package's code, the contents + * of this header change the visibility of certain symbols which the rclcpp + * library cannot have, but the consuming code must have inorder to link. + */ + +#include "rclcpp_components/register_node_macro.hpp" +#include "rosbag2/composable_player.hpp" + +namespace rosbag2 +{ +Player::Player(const rclcpp::NodeOptions & node_options) +: Player("rosbag2_player", node_options) {} + +Player::Player( + const std::string & node_name, + const rclcpp::NodeOptions & node_options) +: rosbag2_transport::Player(node_name, node_options) {} +} // namespace rosbag2 + +// Register the component with class_loader. +// This acts as an entry point, allowing the component to be +// discoverable when its library is being loaded into a running process. +RCLCPP_COMPONENTS_REGISTER_NODE(rosbag2::Player) diff --git a/rosbag2/src/rosbag2/composable_recorder.cpp b/rosbag2/src/rosbag2/composable_recorder.cpp new file mode 100644 index 0000000000..0f0d65489d --- /dev/null +++ b/rosbag2/src/rosbag2/composable_recorder.cpp @@ -0,0 +1,39 @@ +// Copyright 2025 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. + +/* This header must be included by all rclcpp headers which declare symbols + * which are defined in the rclcpp library. When not building the rclcpp + * library, i.e. when using the headers in other package's code, the contents + * of this header change the visibility of certain symbols which the rclcpp + * library cannot have, but the consuming code must have inorder to link. + */ + +#include "rclcpp_components/register_node_macro.hpp" +#include "rosbag2/composable_recorder.hpp" + +namespace rosbag2 +{ +Recorder::Recorder(const rclcpp::NodeOptions & node_options) +: Recorder("rosbag2_recorder", node_options) {} + +Recorder::Recorder( + const std::string & node_name, + const rclcpp::NodeOptions & node_options) +: rosbag2_transport::Recorder(node_name, node_options) {} +} // namespace rosbag2 + +// Register the component with class_loader. +// This acts as an entry point, allowing the component to be +// discoverable when its library is being loaded into a running process. +RCLCPP_COMPONENTS_REGISTER_NODE(rosbag2::Recorder) diff --git a/rosbag2_transport/CMakeLists.txt b/rosbag2_transport/CMakeLists.txt index 3183672554..e3670d7c6a 100644 --- a/rosbag2_transport/CMakeLists.txt +++ b/rosbag2_transport/CMakeLists.txt @@ -72,9 +72,11 @@ target_link_libraries(${PROJECT_NAME} PRIVATE yaml-cpp::yaml-cpp ) +# rosbag2_transport::Player composable node is deprecated. Please use rosbag2::Player instead rclcpp_components_register_node( ${PROJECT_NAME} PLUGIN "rosbag2_transport::Player" EXECUTABLE player) +# rosbag2_transport::Recorder composable node is deprecated. Please use rosbag2::Recorder instead rclcpp_components_register_node( ${PROJECT_NAME} PLUGIN "rosbag2_transport::Recorder" EXECUTABLE recorder) diff --git a/rosbag2_transport/include/rosbag2_transport/player.hpp b/rosbag2_transport/include/rosbag2_transport/player.hpp index d240d72761..27dbbcf415 100644 --- a/rosbag2_transport/include/rosbag2_transport/player.hpp +++ b/rosbag2_transport/include/rosbag2_transport/player.hpp @@ -86,11 +86,14 @@ class Player : public rclcpp::Node /// Will call Player(node_name, node_options) constructor with node_name = "rosbag2_player". /// \param node_options Node options which will be used during construction of the underlying /// node. + [[deprecated("The rosbag2_transport::Player constructor for the composable player is deprecated." + "Please use rosbag2::Player constructor instead")]] ROSBAG2_TRANSPORT_PUBLIC explicit Player(const rclcpp::NodeOptions & node_options); /// \brief Default constructor and entry point for the composable player. - /// Will construct Player class and initialize play_options, storage_options from node + /// \note Used from the rosbag2::Player constructor which is registered with ament resource index. + /// \details Will construct Player class and initialize play_options, storage_options from node /// parameters. At the end will call Player::play() to automatically start playback in a /// separate thread. /// \param node_name Name for the underlying node. diff --git a/rosbag2_transport/include/rosbag2_transport/recorder.hpp b/rosbag2_transport/include/rosbag2_transport/recorder.hpp index 6755fd5ff6..57c1872ca9 100644 --- a/rosbag2_transport/include/rosbag2_transport/recorder.hpp +++ b/rosbag2_transport/include/rosbag2_transport/recorder.hpp @@ -61,12 +61,16 @@ class Recorder : public rclcpp::Node /// Will call Recorder(node_name, node_options) constructor with node_name = "rosbag2_recorder". /// \param node_options Node options which will be used during construction of the underlying /// node. + [[deprecated("The rosbag2_transport::Recorder constructor for the composable recorder is " + "deprecated. Please use rosbag2::Recorder constructor instead")]] ROSBAG2_TRANSPORT_PUBLIC explicit Recorder(const rclcpp::NodeOptions & node_options); /// \brief Default constructor and entry point for the composable recorder. - /// Will construct Recorder class and initialize record_options, storage_options from node - /// parameters. At the end will call Recorder::record() to automatically start recording in a + /// \note Used from the rosbag2::Recorder constructor which is registered with + /// ament resource index. + /// \details Will construct Recorder class and initialize record_options, storage_options from + /// node parameters. At the end will call Recorder::record() to automatically start recording in a /// separate thread. /// \param node_name Name for the underlying node. /// \param node_options Node options which will be used during construction of the underlying diff --git a/rosbag2_transport/src/rosbag2_transport/player.cpp b/rosbag2_transport/src/rosbag2_transport/player.cpp index 1547eba4d3..2efbb358a9 100644 --- a/rosbag2_transport/src/rosbag2_transport/player.cpp +++ b/rosbag2_transport/src/rosbag2_transport/player.cpp @@ -1689,7 +1689,12 @@ const rosbag2_transport::PlayOptions & PlayerImpl::get_play_options() // Player public interface Player::Player(const rclcpp::NodeOptions & node_options) -: Player("rosbag2_player", node_options) {} +: Player("rosbag2_player", node_options) +{ + RCLCPP_WARN(this->get_logger(), + "The rosbag2_transport::Player composable node is deprecated." + " Please use rosbag2::Player instead"); +} Player::Player(const std::string & node_name, const rclcpp::NodeOptions & node_options) : rclcpp::Node(node_name, node_options) diff --git a/rosbag2_transport/src/rosbag2_transport/recorder.cpp b/rosbag2_transport/src/rosbag2_transport/recorder.cpp index d5d1f0b0e5..4b7b7c4104 100644 --- a/rosbag2_transport/src/rosbag2_transport/recorder.cpp +++ b/rosbag2_transport/src/rosbag2_transport/recorder.cpp @@ -741,7 +741,12 @@ void RecorderImpl::warn_if_new_qos_for_subscribed_topic(const std::string & topi // Recorder public interface Recorder::Recorder(const rclcpp::NodeOptions & node_options) -: Recorder("rosbag2_recorder", node_options) {} +: Recorder("rosbag2_recorder", node_options) +{ + RCLCPP_WARN(this->get_logger(), + "The rosbag2_transport::Recorder composable node is deprecated." + " Please use rosbag2::Recorder instead"); +} Recorder::Recorder( const std::string & node_name,