创建C++节点
创建模板
在这里我们创建一个c++版本的标准的 ros2 节点模板。
ros2 pkg create mynode --build-type ament_cmake --dependencies rclcpp
在标准的ros2 节点模板下,生成的 CMakeLists.txt 模板文件如下:
cmake_minimum_required(VERSION 3.8)
project(mynode)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
在标准的ros2 节点模板下,生成的 package.xml 模板文件如下:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>mynode</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="zhangxiaouse@163.com">aikejiao</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
创建入口文件
在例子中,我们依赖了一些外部消息包,并创建了完成的node节点。
#mynode.hpp
#include "rclcpp/rclcpp.hpp"
#引入sensor_msgs依赖
#include "sensor_msgs/msg/joint_state.hpp"
class MyNode : public rclcpp::Node
{
public:
MyNode();
~MyNode();
private:
rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr joint_state_sub_;
rclcpp::Publisher<sensor_msgs::msg::JointState>::SharedPtr joint_state_pub_;
void joint_state_callback(const sensor_msgs::msg::JointState::SharedPtr msg);
};
#mynode.cpp
#include "mynode/mynode.hpp"
MyNode::MyNode()
: Node("my_node")
{
RCLCPP_INFO(this->get_logger(), "Hello, world!");
}
MyNode::~MyNode()
{
RCLCPP_INFO(this->get_logger(), "Goodbye, world!");
}
void MyNode::joint_state_callback(const sensor_msgs::msg::JointState::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "Receive Joint state message");
joint_state_pub_->publish(*msg);
}
#main.cpp
#include "mynode/mynode.hpp"
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
编辑 CMakeLists.txt
与原来生成的CMakeLists.txt
模板文件,我们增加设置将节点编译为可执行文件和依赖关系。
cmake_minimum_required(VERSION 3.8)
project(mynode)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
#新增开始
#找到sensor_msgs包
find_package(sensor_msgs REQUIRED)
#新增结束
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
#新增开始
#编译为可执行文件,编译后会生成mynode可执行文件
add_executable(mynode src/main.cpp src/mynode.cpp)
#为特定目标设置包含目录,$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>为构建时的包含目录,#$<INSTALL_INTERFACE:include>为安装后的包含目录。
target_include_directories(mynode PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
#添加ROS2依赖关系,将mynode节点链接到rclcpp和sensor_msgs库。
ament_target_dependencies(mynode rclcpp sensor_msgs)
#安装文件
install(TARGETS
mynode
DESTINATION lib/${PROJECT_NAME})
#安装目录
install(DIRECTORY include/${PROJECT_NAME}
DESTINATION include)
install(DIRECTORY launch
DESTINATION share/${PROJECT_NAME})
#新增结束
ament_package()
编辑 package.xml
与原来生成的package.xml 模板文件,我们增加节点运行时的依赖关系。
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>mynode</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="zhangxiaouse@163.com">aikejiao</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
#新增开始:运行时依赖
<depend>sensor_msgs</depend>
#新增结束
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
为什么需要修改两个文件
在例子中,我们在CMakeList.txt
和package.xml
文件中都增加了对sensor_msgs
的依赖,这是因为在CMake中,通过find_package(sensor_msgs REQUIRED)
来查找这个包,而package.xml
中的依赖声明会确保在编译前正确配置依赖路径,以保证在构建时sensor_msgs
包可用。