当前位置:   article > 正文

ROS2与C++入门教程-在C++包里增加python支持_ros2 c++ 调用python程序

ros2 c++ 调用python程序

系列目录

说明:

  • 介绍如何在C++包增加Python支持,实现通过C++节点发布话题信息,通过Python节点接受话题信息
  • 一般情况下都是C++或Python都独立的包,这样对于各自管理的节点也很方便。
  • 但是有些情况也例外,如果C++包里想同时增加Python也是支持的。步骤也多一些

步骤:

  • 新建包my_cpp_py_pkg
  1. cd ~/dev_ws/src
  2. ros2 pkg create my_cpp_py_pkg --build-type ament_cmake
  • 内容如下:
  1. my_cpp_py_pkg/
  2. ├── CMakeLists.txt
  3. ├── include
  4. │ └── my_cpp_py_pkg
  5. ├── package.xml
  6. └── src
  • 增加cpp节点和头文件
  1. cd my_cpp_py_pkg/
  2. touch src/cpp_node.cpp
  3. touch include/my_cpp_py_pkg/cpp_talker.hpp
  • cpp_talker.hpp内容如下:
  1. #include <chrono>
  2. #include <memory>
  3. #include "rclcpp/rclcpp.hpp"
  4. #include "std_msgs/msg/string.hpp"
  • cpp_node.cpp需要增加引入头文件,增加如下内容cpp_talker.cpp
  1. #include "my_cpp_py_pkg/cpp_talker.hpp"
  2. using namespace std::chrono_literals;
  3. /* This example creates a subclass of Node and uses std::bind() to register a
  4. * member function as a callback from the timer. */
  5. class MinimalPublisher : public rclcpp::Node
  6. {
  7. public:
  8. MinimalPublisher()
  9. : Node("minimal_publisher"), count_(0)
  10. {
  11. publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
  12. timer_ = this->create_wall_timer(
  13. 500ms, std::bind(&MinimalPublisher::timer_callback, this));
  14. }
  15. private:
  16. void timer_callback()
  17. {
  18. auto message = std_msgs::msg::String();
  19. message.data = "Hello, world! " + std::to_string(count_++);
  20. RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
  21. publisher_->publish(message);
  22. }
  23. rclcpp::TimerBase::SharedPtr timer_;
  24. rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  25. size_t count_;
  26. };
  27. int main(int argc, char * argv[])
  28. {
  29. rclcpp::init(argc, argv);
  30. rclcpp::spin(std::make_shared<MinimalPublisher>());
  31. rclcpp::shutdown();
  32. return 0;
  33. }
  • 增加python节点和模块导入
  • 新建pyton目录
  1. mkdir my_cpp_py_pkg
  2. touch my_cpp_py_pkg/__init__.py
  3. mkdir scripts
  • 新建python文件
  1. touch my_cpp_py_pkg/module_to_import.py
  2. touch scripts/py_listener.py
  • module_to_import.py内容如下:
  1. def listener_write(data) :
  2. my_open = open("/tmp/my_write.txt", 'w')
  3. #打开/tmp路径下的my_write.txt文件,采用写入模式
  4. #若文件不存在,创建,若存在,清空并写入
  5. my_open.write(data)
  6. #在文件中写入一个字符串
  7. my_open.write('\n')
  8. my_open.close()
  • py_listener.py内容如下:
  1. #!/usr/bin/env python3
  2. import rclpy
  3. from rclpy.node import Node
  4. from std_msgs.msg import String
  5. from my_cpp_py_pkg.module_to_import import listener_write
  6. class MinimalSubscriber(Node):
  7. def __init__(self):
  8. super().__init__('minimal_subscriber')
  9. self.subscription = self.create_subscription(
  10. String,
  11. 'topic',
  12. self.listener_callback,
  13. 10)
  14. self.subscription #
  15. def listener_callback(self, msg):
  16. self.get_logger().info('I heard: "%s"' % msg.data)
  17. listener_write(msg.data)
  18. def main(args=None):
  19. rclpy.init(args=args)
  20. minimal_subscriber = MinimalSubscriber()
  21. rclpy.spin(minimal_subscriber)
  22. minimal_subscriber.destroy_node()
  23. rclpy.shutdown()
  24. if __name__ == '__main__':
  25. main()
  • 重要提示:您必须首先在 py_listener.py 文件中添加一个行:
#!/usr/bin/env python3
  • 你不增加这一行,用ros2 run运用就会出错。
  • 同时要增加执行权限
chmod +x scripts/py_listener.py
  • 如果要导入模块,可以在py_listener.py增加如下行。
from my_cpp_py_pkg.module_to_import import  listener_write
  • 最终的结构如下:
  1. my_cpp_py_pkg/
  2. # --> package info, configuration, and compilation
  3. ├── CMakeLists.txt
  4. ├── package.xml
  5. # --> Python stuff
  6. ├── my_cpp_py_pkg
  7. │ ├── __init__.py
  8. │ └── module_to_import.py
  9. ├── scripts
  10. │ └── py_listener.py
  11. # --> Cpp stuff
  12. ├── include
  13. │ └── my_cpp_py_pkg
  14. │ └── cpp_talker.hpp
  15. └── src
  16. └── cpp_talker.cpp
  • 配置package.xml
  • 内容如下:
  1. <?xml version="1.0"?>
  2. <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
  3. <package format="3">
  4. <name>my_cpp_py_pkg</name>
  5. <version>0.0.0</version>
  6. <description>TODO: Package description</description>
  7. <maintainer email="your@email.com">Name</maintainer>
  8. <license>TODO: License declaration</license>
  9. <buildtool_depend>ament_cmake</buildtool_depend>
  10. <buildtool_depend>ament_cmake_python</buildtool_depend>
  11. <depend>rclcpp</depend>
  12. <depend>rclpy</depend>
  13. <depend>std_msgs</depend>
  14. <test_depend>ament_lint_auto</test_depend>
  15. <test_depend>ament_lint_common</test_depend>
  16. <export>
  17. <build_type>ament_cmake</build_type>
  18. </export>
  19. </package>
  • 增加<buildtool_depend>ament_cmake_python</buildtool_depend>行和rclpy,支持python使用。
  • 注意:在标准的 Python 包中,你应该有 ament_python,而不是 ament_cmake_python。 确保不要混合使用这 2 个。
  • 使用 ament_cmake_python 意味着我们将能够使用 cmake 设置我们的 Python 内容。
  • 配置CMakeLists.txt
  • 内容如下:
  1. cmake_minimum_required(VERSION 3.5)
  2. project(my_cpp_py_pkg)
  3. # Default to C++14
  4. if(NOT CMAKE_CXX_STANDARD)
  5. set(CMAKE_CXX_STANDARD 14)
  6. endif()
  7. if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  8. add_compile_options(-Wall -Wextra -Wpedantic)
  9. endif()
  10. # Find dependencies
  11. find_package(ament_cmake REQUIRED)
  12. find_package(ament_cmake_python REQUIRED)
  13. find_package(rclcpp REQUIRED)
  14. find_package(rclpy REQUIRED)
  15. find_package(std_msgs REQUIRED)
  16. # Include Cpp "include" directory
  17. include_directories(include)
  18. # Create Cpp executable
  19. add_executable(cpp_talker src/cpp_talker.cpp)
  20. ament_target_dependencies(cpp_executable rclcpp)
  21. # Install Cpp executables
  22. install(TARGETS
  23. cpp_talker
  24. DESTINATION lib/${PROJECT_NAME}
  25. )
  26. # Install Python modules
  27. ament_python_install_package(${PROJECT_NAME})
  28. # Install Python executables
  29. install(PROGRAMS
  30. scripts/py_listener.py
  31. DESTINATION lib/${PROJECT_NAME}
  32. )
  33. ament_package()
  • 注意其中三个部分: 依赖部分,CPP部分和Python部分
  • 依赖部分
  1. # Find dependencies
  2. find_package(ament_cmake REQUIRED)
  3. find_package(ament_cmake_python REQUIRED)
  4. find_package(rclcpp REQUIRED)
  5. find_package(rclpy REQUIRED)
  6. find_package(std_msgs REQUIRED)
  • CPP部分
  1. # Include Cpp "include" directory
  2. include_directories(include)
  3. # Create Cpp executable
  4. add_executable(cpp_talker src/cpp_talker.cpp)
  5. ament_target_dependencies(cpp_talker rclcpp)
  6. # Install Cpp executables
  7. install(TARGETS
  8. cpp_talker
  9. DESTINATION lib/${PROJECT_NAME}
  10. )
  • python部分
  1. # Install Python modules
  2. ament_python_install_package(${PROJECT_NAME})
  3. # Install Python executables
  4. install(PROGRAMS
  5. scripts/py_listener.py
  6. DESTINATION lib/${PROJECT_NAME}
  7. )
  • 使用 ament_python_install_package(${PROJECT_NAME}) 安装任何 Python 模块(在此示例中:my_cpp_py_pkg/ 文件夹下的文件),以便您可以从这个或另一个包中找到它们。

  • 然后,我们安装 scripts/py_listener.py 文件。 我们将此文件放在 install lib/ 文件夹中,该文件夹与 ROS2 Cpp 节点的文件夹相同。 因此,所有 Cpp/Python 可执行文件都将位于同一位置。

  • 对于您需要安装的任何新 Python 脚本,只需在此处添加新行。

  • 编译包

  1. cd ~/dev_ws/
  2. colcon build --symlink-install --packages-select my_cpp_py_pkg
  • 执行cpp发布话题信息
 ros2 run my_cpp_py_pkg cpp_talker
  • 效果如下:
  1. $ ros2 run my_cpp_py_pkg cpp_talker
  2. [INFO] [1651803573.152324876] [minimal_publisher]: Publishing: 'Hello, world! 0'
  3. [INFO] [1651803573.652296360] [minimal_publisher]: Publishing: 'Hello, world! 1'
  4. [INFO] [1651803574.152555806] [minimal_publisher]: Publishing: 'Hello, world! 2'
  5. [INFO] [1651803574.652385533] [minimal_publisher]: Publishing: 'Hello, world! 3'
  6. [INFO] [1651803575.152389750] [minimal_publisher]: Publishing: 'Hello, world! 4'
  • 执行python接受话题信息
ros2 run my_cpp_py_pkg py_listener.py
  • 效果如下:
  1. $ ros2 run my_cpp_py_pkg py_listener.py
  2. [INFO] [1651803635.112644593] [minimal_subscriber]: I heard: "Hello, world! 8"
  3. [INFO] [1651803635.597138764] [minimal_subscriber]: I heard: "Hello, world! 9"
  4. [INFO] [1651803636.097224630] [minimal_subscriber]: I heard: "Hello, world! 10"
  5. [INFO] [1651803636.597222975] [minimal_subscriber]: I heard: "Hello, world! 11"
  6. [INFO] [1651803637.096938082] [minimal_subscriber]: I heard: "Hello, world! 12"
  7. [INFO] [1651803637.596770711] [minimal_subscriber]: I heard: "Hello, world! 13"
  • 重要提示:如果您希望使用 --symlink-install 选项进行编译(这样您就可以修改和重新运行脚本而无需重新编译),您必须使用 chmod +x 使您的脚本可执行。
  • 否则当你尝试运行你的节点时,你会得到这个错误:“No executable found”。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/766131
推荐阅读
相关标签
  

闽ICP备14008679号