飞道的博客

ROS2机器人编程简述humble-第四章-BASIC DETECTOR .3

379人阅读  评论(0)

书中程序适用于turtlebot、husky等多种机器人,配置相似都可以用的。

支持ROS2版本foxy、humble。

基础检测效果如下:

由于缺¥,所有设备都非常老旧,都是其他实验室淘汰或者拼凑出来的设备。机器人控制笔记本是2010年版本。

但是依然可以跑ROS1、ROS2。

book_ros2/br2_tf2_detector目录:


   
  1. .
  2. ├── CMakeLists.txt
  3. ├── include
  4. │ └── br2_tf2_detector
  5. │ ├── ObstacleDetectorImprovedNode.hpp
  6. │ ├── ObstacleDetectorNode.hpp
  7. │ └── ObstacleMonitorNode.hpp
  8. ├── launch
  9. │ ├── detector_basic.launch.py
  10. │ ├── detector_improved.launch.py
  11. │ ├── turtlebot_detector_basic.launch.py
  12. │ └── turtlebot_detector_improved.launch.py
  13. ├── package.xml
  14. └── src
  15. ├── br2_tf2_detector
  16. │ ├── ObstacleDetectorImprovedNode.cpp
  17. │ ├── ObstacleDetectorNode.cpp
  18. │ ├── ObstacleMonitorNode (copy).cpp
  19. │ └── ObstacleMonitorNode.cpp
  20. ├── detector_improved_main.cpp
  21. └── detector_main.cpp
  22. 5 directories, 15 files

里面有两个部分basic和improved。

CMakelist(lib):


   
  1. cmake_minimum_required(VERSION 3.5)
  2. project(br2_tf2_detector)
  3. set(CMAKE_CXX_STANDARD 17)
  4. # find dependencies
  5. find_package(ament_cmake REQUIRED)
  6. find_package(rclcpp REQUIRED)
  7. find_package(tf2_ros REQUIRED)
  8. find_package(geometry_msgs REQUIRED)
  9. find_package(sensor_msgs REQUIRED)
  10. find_package(visualization_msgs REQUIRED)
  11. set(dependencies
  12. rclcpp
  13. tf2_ros
  14. geometry_msgs
  15. sensor_msgs
  16. visualization_msgs
  17. )
  18. include_directories(include)
  19. add_library( ${PROJECT_NAME} SHARED
  20. src/br2_tf2_detector/ObstacleDetectorNode.cpp
  21. src/br2_tf2_detector/ObstacleMonitorNode.cpp
  22. src/br2_tf2_detector/ObstacleDetectorImprovedNode.cpp
  23. )
  24. ament_target_dependencies( ${PROJECT_NAME} ${dependencies})
  25. add_executable(detector src/detector_main.cpp)
  26. ament_target_dependencies(detector ${dependencies})
  27. target_link_libraries(detector ${PROJECT_NAME})
  28. add_executable(detector_improved src/detector_improved_main.cpp)
  29. ament_target_dependencies(detector_improved ${dependencies})
  30. target_link_libraries(detector_improved ${PROJECT_NAME})
  31. install(TARGETS
  32. ${PROJECT_NAME}
  33. detector
  34. detector_improved
  35. ARCHIVE DESTINATION lib
  36. LIBRARY DESTINATION lib
  37. RUNTIME DESTINATION lib/ ${PROJECT_NAME}
  38. )
  39. install(DIRECTORY launch DESTINATION share/ ${PROJECT_NAME})
  40. if(BUILD_TESTING)
  41. find_package(ament_lint_auto REQUIRED)
  42. ament_lint_auto_find_test_dependencies()
  43. endif()
  44. ament_package()

障碍物识别节点


   
  1. // Copyright 2021 Intelligent Robotics Lab
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <memory>
  15. #include "br2_tf2_detector/ObstacleDetectorNode.hpp"
  16. #include "sensor_msgs/msg/laser_scan.hpp"
  17. #include "geometry_msgs/msg/transform_stamped.hpp"
  18. #include "rclcpp/rclcpp.hpp"
  19. namespace br2_tf2_detector
  20. {
  21. using std::placeholders::_1;
  22. ObstacleDetectorNode:: ObstacleDetectorNode()
  23. : Node( "obstacle_detector")
  24. {
  25. scan_sub_ = create_subscription<sensor_msgs::msg::LaserScan>(
  26. "input_scan", rclcpp:: SensorDataQoS(),
  27. std:: bind(&ObstacleDetectorNode::scan_callback, this, _1));
  28. tf_broadcaster_ = std:: make_shared<tf2_ros::StaticTransformBroadcaster>(* this);
  29. }
  30. void
  31. ObstacleDetectorNode::scan_callback (sensor_msgs::msg::LaserScan::UniquePtr msg)
  32. {
  33. double dist = msg->ranges[msg->ranges. size() / 2];
  34. if (!std:: isinf(dist)) {
  35. geometry_msgs::msg::TransformStamped detection_tf;
  36. detection_tf.header = msg->header;
  37. detection_tf.child_frame_id = "detected_obstacle";
  38. detection_tf.transform.translation.x = msg->ranges[msg->ranges. size() / 2];
  39. tf_broadcaster_-> sendTransform(detection_tf);
  40. }
  41. }
  42. } // namespace br2_tf2_detector

主要就是回调函数完成大部分功能。具体参考源代码即可。

障碍物监控节点:


   
  1. // Copyright 2021 Intelligent Robotics Lab
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <tf2/transform_datatypes.h>
  15. #include <tf2/LinearMath/Quaternion.h>
  16. #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
  17. #include <memory>
  18. #include "br2_tf2_detector/ObstacleMonitorNode.hpp"
  19. #include "geometry_msgs/msg/transform_stamped.hpp"
  20. #include "rclcpp/rclcpp.hpp"
  21. namespace br2_tf2_detector
  22. {
  23. using namespace std::chrono_literals;
  24. ObstacleMonitorNode:: ObstacleMonitorNode()
  25. : Node( "obstacle_monitor"),
  26. tf_buffer_(),
  27. tf_listener_(tf_buffer_)
  28. {
  29. marker_pub_ = create_publisher<visualization_msgs::msg::Marker>( "obstacle_marker", 1);
  30. timer_ = create_wall_timer(
  31. 500ms, std:: bind(&ObstacleMonitorNode::control_cycle, this));
  32. }
  33. void
  34. ObstacleMonitorNode::control_cycle ()
  35. {
  36. geometry_msgs::msg::TransformStamped robot2obstacle;
  37. try {
  38. robot2obstacle = tf_buffer_. lookupTransform(
  39. "odom", "detected_obstacle", tf2::TimePointZero);
  40. } catch (tf2::TransformException & ex) {
  41. RCLCPP_WARN( get_logger(), "Obstacle transform not found: %s", ex. what());
  42. return;
  43. }
  44. double x = robot2obstacle.transform.translation.x;
  45. double y = robot2obstacle.transform.translation.y;
  46. double z = robot2obstacle.transform.translation.z;
  47. double theta = atan2(y, x);
  48. RCLCPP_INFO(
  49. get_logger(), "Obstacle detected at (%lf m, %lf m, , %lf m) = %lf rads",
  50. x, y, z, theta);
  51. visualization_msgs::msg::Marker obstacle_arrow;
  52. obstacle_arrow.header.frame_id = "odom";
  53. obstacle_arrow.header.stamp = now();
  54. obstacle_arrow.type = visualization_msgs::msg::Marker::ARROW;
  55. obstacle_arrow.action = visualization_msgs::msg::Marker::ADD;
  56. obstacle_arrow.lifetime = rclcpp:: Duration( 1s);
  57. geometry_msgs::msg::Point start;
  58. start.x = 0.0;
  59. start.y = 0.0;
  60. start.z = 0.0;
  61. geometry_msgs::msg::Point end;
  62. end.x = x;
  63. end.y = y;
  64. end.z = z;
  65. obstacle_arrow.points = {start, end};
  66. obstacle_arrow.color.r = 1.0;
  67. obstacle_arrow.color.g = 0.0;
  68. obstacle_arrow.color.b = 0.0;
  69. obstacle_arrow.color.a = 1.0;
  70. obstacle_arrow.scale.x = 0.02;
  71. obstacle_arrow.scale.y = 0.1;
  72. obstacle_arrow.scale.z = 0.1;
  73. marker_pub_-> publish(obstacle_arrow);
  74. }
  75. } // namespace br2_tf2_detector

代码和原始版本稍微有些不同。

重要部分:


   
  1. try {
  2. robot2obstacle = tf_buffer_. lookupTransform(
  3. "odom", "detected_obstacle", tf2::TimePointZero);
  4. } catch (tf2::TransformException & ex) {
  5. RCLCPP_WARN( get_logger(), "Obstacle transform not found: %s", ex. what());
  6. return;
  7. }
  8. double x = robot2obstacle.transform.translation.x;
  9. double y = robot2obstacle.transform.translation.y;
  10. double z = robot2obstacle.transform.translation.z;
  11. double theta = atan2(y, x);
  12. RCLCPP_INFO(
  13. get_logger(), "Obstacle detected at (%lf m, %lf m, , %lf m) = %lf rads",
  14. x, y, z, theta);

如果tf不能正常工作,会报错Obstacle transform not found:

例如odom没有

[detector-1] [WARN] [1676266943.177279939] [obstacle_monitor]: Obstacle transform not found: "odom" passed to lookupTransform argument target_frame does not exist.

例如detected_obstacle没有

[detector-1] [WARN] [1676267019.166991316] [obstacle_monitor]: Obstacle transform not found: "detected_obstacle" passed to lookupTransform argument source_frame does not exist. 

需要思考并解决问题哦^_^

如果都ok!那么"Obstacle detected at (%lf m, %lf m, , %lf m) = %lf rads":

机器人在运动中所以角度和距离会不断变化。

此时如果查看:

rqt

其中检测tf是由激光传感器测距给出的。

节点主题图:

这个代码主程序!


   
  1. // Copyright 2021 Intelligent Robotics Lab
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <memory>
  15. #include "br2_tf2_detector/ObstacleDetectorNode.hpp"
  16. #include "br2_tf2_detector/ObstacleMonitorNode.hpp"
  17. #include "rclcpp/rclcpp.hpp"
  18. int main(int argc, char * argv[])
  19. {
  20. rclcpp:: init(argc, argv);
  21. auto obstacle_detector = std:: make_shared<br2_tf2_detector::ObstacleDetectorNode>();
  22. auto obstacle_monitor = std:: make_shared<br2_tf2_detector::ObstacleMonitorNode>();
  23. rclcpp::executors::SingleThreadedExecutor executor;
  24. executor. add_node(obstacle_detector-> get_node_base_interface());
  25. executor. add_node(obstacle_monitor-> get_node_base_interface());
  26. executor. spin();
  27. rclcpp:: shutdown();
  28. return 0;
  29. }

这里需要注意!


   
  1. rclcpp::executors::SingleThreadedExecutor executor;
  2. executor. add_node(obstacle_detector-> get_node_base_interface());
  3. executor. add_node(obstacle_monitor-> get_node_base_interface());

如果C++掌握一般推荐看一看:

蓝桥ROS机器人之现代C++学习笔记7.1 并行基础

多线程是如何实现的。

整个程序要跑起来:

终端1-gazebo仿真:ros2 launch turtlebot3_gazebo empty_world.launch.py


   
  1. ros2 launch turtlebot3_gazebo empty_world.launch.py
  2. [INFO] [launch]: All log files can be found below /home/zhangrelay/.ros/log/2023-02-13-13-43-10-244500-Aspire4741-10860
  3. [INFO] [launch]: Default logging verbosity is set to INFO
  4. urdf_file_name : turtlebot3_burger.urdf
  5. [INFO] [gzserver-1]: process started with pid [10862]
  6. [INFO] [gzclient -2]: process started with pid [10864]
  7. [INFO] [ros2-3]: process started with pid [10868]
  8. [INFO] [robot_state_publisher-4]: process started with pid [10870]
  9. [robot_state_publisher-4] [WARN] [1676266991.467830827] [robot_state_publisher]: No robot_description parameter, but command-line argument available. Assuming argument is name of URDF file. This backwards compatibility fallback will be removed in the future.
  10. [robot_state_publisher-4] Parsing robot urdf xml string.
  11. [robot_state_publisher-4] Link base_link had 5 children
  12. [robot_state_publisher-4] Link caster_back_link had 0 children
  13. [robot_state_publisher-4] Link imu_link had 0 children
  14. [robot_state_publisher-4] Link base_scan had 0 children
  15. [robot_state_publisher-4] Link wheel_left_link had 0 children
  16. [robot_state_publisher-4] Link wheel_right_link had 0 children
  17. [robot_state_publisher-4] [INFO] [1676266991.472337172] [robot_state_publisher]: got segment base_footprint
  18. [robot_state_publisher-4] [INFO] [1676266991.472419811] [robot_state_publisher]: got segment base_link
  19. [robot_state_publisher-4] [INFO] [1676266991.472444636] [robot_state_publisher]: got segment base_scan
  20. [robot_state_publisher-4] [INFO] [1676266991.472465018] [robot_state_publisher]: got segment caster_back_link
  21. [robot_state_publisher-4] [INFO] [1676266991.472485972] [robot_state_publisher]: got segment imu_link
  22. [robot_state_publisher-4] [INFO] [1676266991.472505808] [robot_state_publisher]: got segment wheel_left_link
  23. [robot_state_publisher-4] [INFO] [1676266991.472525491] [robot_state_publisher]: got segment wheel_right_link
  24. [ros2-3] Set parameter successful
  25. [INFO] [ros2-3]: process has finished cleanly [pid 10868]
  26. [gzserver-1] [INFO] [1676266994.292818234] [turtlebot3_imu]: <initial_orientation_as_reference> is unset, using default value of false to comply with REP 145 (world as orientation reference)
  27. [gzserver-1] [INFO] [1676266994.417396256] [turtlebot3_diff_drive]: Wheel pair 1 separation set to [0.160000m]
  28. [gzserver-1] [INFO] [1676266994.417528534] [turtlebot3_diff_drive]: Wheel pair 1 diameter set to [0.066000m]
  29. [gzserver-1] [INFO] [1676266994.420616206] [turtlebot3_diff_drive]: Subscribed to [/cmd_vel]
  30. [gzserver-1] [INFO] [1676266994.425994254] [turtlebot3_diff_drive]: Advertise odometry on [/odom]
  31. [gzserver-1] [INFO] [1676266994.428920116] [turtlebot3_diff_drive]: Publishing odom transforms between [odom] and [base_footprint]
  32. [gzserver-1] [INFO] [1676266994.460852885] [turtlebot3_joint_state]: Going to publish joint [wheel_left_joint]
  33. [gzserver-1] [INFO] [1676266994.461009035] [turtlebot3_joint_state]: Going to publish joint [wheel_right_joint]

终端2-障碍物检测:

ros2 launch br2_tf2_detector turtlebot_detector_basic.launch.py

终端3-rqt:rqt

终端4-rviz2:rviz2

windows端也可以获取信息。

补充:

四元数是方向的4元组表示,它比旋转矩阵更简洁。四元数对于分析涉及三维旋转的情况非常有效。四元数广泛应用于机器人、量子力学、计算机视觉和3D动画。

可以在维基百科上了解更多关于基础数学概念的信息。还可以观看一个可探索的视频系列,将3blue1brown制作的四元数可视化。

官方教程将指导完成调试典型tf2问题的步骤。它还将使用许多tf2调试工具,如tf2_echo、tf2_monitor和view_frames。

TF2完整教程提纲:

tf2

许多tf2教程都适用于C++和Python。这些教程经过简化,可以完成C++曲目或Python曲目。如果想同时学习C++和Python,应该学习一次C++教程和一次Python教程。

目录

工作区设置

学习tf2

调试tf2

将传感器消息与tf2一起使用

工作区设置

如果尚未创建完成教程的工作空间,请遵循本教程。

学习tf2

tf2简介。

本教程将让了解tf2可以为您做什么。它在一个多机器人的例子中展示了一些tf2的力量,该例子使用了turtlesim。这还介绍了使用tf2_echo、view_frames和rviz。

编写静态广播(Python)(C++)。

本教程教如何向tf2广播静态坐标帧。

编写广播(Python)(C++)。

本教程教如何向tf2广播机器人的状态。

编写监听器(Python)(C++)。

本教程教如何使用tf2访问帧变换。

添加框架(Python)(C++)。

本教程教如何向tf2添加额外的固定帧。

使用时间(Python)(C++)。

本教程教使用lookup_transform函数中的超时来等待tf2树上的转换可用。

时间旅行(Python)(C++)。

本教程向介绍tf2的高级时间旅行功能。

调试tf2

四元数基本原理。

本教程介绍ROS 2中四元数的基本用法。

调试tf2问题。

本教程向介绍调试tf2相关问题的系统方法。

将传感器消息与tf2一起使用

对tf2_ros::MessageFilter使用标记数据类型。

本教程教您如何使用tf2_ros::MessageFilter处理标记的数据类型。


转载:https://blog.csdn.net/ZhangRelay/article/details/129007417
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场