ورشة عمل ROS 2016: تحليل مهمة التحكم في الروبوت الآمن

مساء الخير عزيزي habratchiteli! يوم الجمعة الماضي في مختبرنا كانت هناك ورشة عمل عملية على منصة ROS - ورشة عمل ROS. تم تنظيم ورشة العمل لطلاب كلية تكنولوجيا المعلومات في جامعة برنو التقنية الذين يرغبون في التعرف على هذه المنصة. على عكس السنوات السابقة (عقدت ورشة العمل لمدة 4 سنوات) ، هذه المرة ركزت ورشة عمل ROS على العمل العملي المستقل. في هذه المقالة سوف أتحدث عن المهمة التي تم تعيينها للمشاركين في ورشة العمل. من يهتم ، من فضلك ، تحت القطة.

الصورة

بيان المشكلة


. — . ( ASUS Xtion turtlebot_gazebo), :

  • Safe — ,
  • Warning — , (, )
  • Danger — ,


ألاحظ على الفور أنه في ورشة العمل ، تم استخدام ROS Indigo على Ubuntu 14.04 لإكمال المهمة. لقد استخدمت أيضًا ROS Indigo للتجارب.

لذلك دعونا نبدأ! قم بإنشاء حزمة باستخدام التبعيات roscpp و pcl_ros و pcl_conversions و sensor_msgs و geometry_msgs:

cd ~/catkin_ws/src
catkin_create_pkg safety_control_cloud roscpp pcl_ros pcl_conversions sensor_msgs geometry_msgs
cd ~/catkin_ws

أضف مكتبة PCL إلى package.xml اعتمادًا على:

<build_depend>libpcll-all-dev</build_depend>
...
<run_depend>libpcl-all</run_depend>


وفي CMakeLists.txt:

find_package(PCL REQUIRED)
...
include_directories(${PCL_INCLUDE_DIRS})

أضف البرنامج النصي safety_control.cpp إلى المجلد src:

safety_control.cpp
#include "ros/ros.h"
#include "pcl_conversions/pcl_conversions.h"
#include <pcl/pcl_base.h>
#include <sstream>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/filters/passthrough.h>
#include <pcl/common/common.h>
#include <geometry_msgs/Twist.h>

typedef pcl::PointXYZ PointType;
typedef pcl::PointCloud<PointType> PointCloud;
typedef PointCloud::Ptr PointCloudPtr;

ros::Publisher pcd_pub_, cmd_vel_pub_;

void pcd_cb(const sensor_msgs::PointCloud2ConstPtr& pcd) {
    ROS_INFO_STREAM_ONCE("Point cloud arrived");
    PointCloudPtr pcd_pcl = PointCloudPtr(new PointCloud), pcd_filtered = PointCloudPtr(new PointCloud);
    PointType pt_min, pt_max;
    pcl::fromROSMsg(*pcd, *pcd_pcl);

    pcl::PassThrough<PointType> pass;
    pass.setInputCloud(pcd_pcl);
    pass.setFilterFieldName("y");
    pass.setFilterLimits(-0.25,0.20);
    pass.filter(*pcd_filtered);

    pass.setInputCloud(pcd_filtered);
    pass.setFilterFieldName("x");
    pass.setFilterLimits(-0.3,0.3);
    pass.filter(*pcd_pcl);

    pcl::getMinMax3D(*pcd_pcl, pt_min, pt_max);

    geometry_msgs::Twist vel;
    if (pt_min.z > 1.0) {
        vel.linear.x = 0.2;
        ROS_INFO_STREAM("Safe zone");
    } else if (pt_min.z > 0.5) {
        vel.linear.x = 0.1;
        ROS_INFO_STREAM("Warning zone");
    } else {
        vel.linear.x = 0.0;
        ROS_INFO_STREAM("Danger zone");
    }

    cmd_vel_pub_.publish(vel);

    sensor_msgs::PointCloud2 pcd_out;
    pcl::toROSMsg(*pcd_pcl, pcd_out);

    pcd_pub_.publish(pcd_out);
}

int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line.
   * For programmatic remappings you can use a different version of init() which takes
   * remappings directly, but for most command-line programs, passing argc and argv is
   * the easiest way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "safety_control_cloud");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  ros::Subscriber pcd_sub = n.subscribe("/camera/depth/points", 1, pcd_cb);

  pcd_pub_ = n.advertise<sensor_msgs::PointCloud2>("/output", 1);
  cmd_vel_pub_ = n.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop", 1);

  ros::spin();

  return 0;
}


قم بإضافة البرنامج النصي safety_control.cpp إلى CMakeLists.txt:

add_executable(safety_control_node src/safety_control.cpp)
target_link_libraries(safety_control_node ${catkin_LIBRARIES} ${PCL_LIBRARIES})

/camera/depth/points, , geometry_msgs/Twister /cmd_vel_mux/input/teleop.

. :


    pcl::PassThrough<PointType> pass;
    pass.setInputCloud(pcd_pcl);
    pass.setFilterFieldName("y");
    pass.setFilterLimits(-0.25,0.20);
    pass.filter(*pcd_filtered);

PassThrough 25 20 ( y).

:


pass.setInputCloud(pcd_filtered);
pass.setFilterFieldName("x");
pass.setFilterLimits(-0.3,0.3);
pass.filter(*pcd_pcl);

نقوم بقص السحابة 0.3 م (30 سم) إلى اليسار واليمين من أصل نظام إحداثيات المستشعر (المحور z). ثم نبحث عن أقرب نقطة في سحابة النقطة على طول المحور z (المحور من مركز مستشعر العمق في اتجاه العرض) - ستكون هذه نقطة أقرب كائن:


pcl::getMinMax3D(*pcd_pcl, pt_min, pt_max);

سيتم نشر السرعة أيضًا على الموضوع / mobile_base / أوامر / السرعة. تجميع الحزمة:

cd ~/catkin_ws
catkin_make
source devel/setup.bash

الاختبار في محاكي Turtle Bot في Gazebo


كانت المهمة الثانية هي اختبار منطق التحكم في الروبوت باستخدام محاكي TurtleBot في Gazebo. للقيام بذلك ، قم بتعيين turtlebot_gazebo باستخدام apt-get:

sudo apt-get install ros-indigo-turtlebot*

هنا يمكنك العثور على بعض الدروس المفيدة حول استخدام المحاكي. يمكن أن يكون جهاز المحاكاة حلاً جيدًا عندما تريد دراسة حزم التنقل في ROS ولا يوجد روبوت حقيقي في متناول اليد. قم بتشغيل المحاكي:

roslaunch turtlebot_gazebo turtlebot_world.launch

ستفتح نافذة Gazebo كما في الصورة:

الصورة

يمكننا تكبير الصورة وتصغيرها باستخدام عجلة الماوس. باستخدام زر الماوس الأيسر والمؤشر يمكننا تحريك الصورة إلى اليسار واليمين وأعلى ولأسفل. باستخدام عجلة الماوس المثبتة والمؤشر ، يمكنك تغيير زاوية العرض الرأسية. الآن أدر الروبوت بحيث ينظر مباشرة إلى الخزانة. في الصف العلوي من الأدوات أعلى نافذة عرض المحاكاة ، حدد الرمز الثالث:

الصورة

وانقر عليه. سنرى شيئًا كهذا.

الصورة

قم بإدارة الروبوت عن طريق النقر على القوس الأزرق وسحبه. نحصل على الصورة التالية:

الصورة

Run rviz:

rosrun rviz rviz

أضف عرض RobotModel ، كما هو موضح بالفعل في المقالة . أضف شاشة PointCloud2 وحدد الموضوع / الكاميرا / العمق / النقاط. ونتيجة لذلك ، نحصل على الصورة التالية:

الصورة

لعرض PointCloud2 ، حدد RGB8 لحقل Color Transformer. نحصل على سحابة ملونة:

الصورة

شغل عقدة safety_control_node الخاصة بنا:

rosrun safety_control_cloud safety_control_node

سيكون الإخراج في المحطة كما يلي:

[ INFO] [1479229421.537897080, 2653.960000000]: Point cloud arrived
[ INFO] [1479229421.572338588, 2654.000000000]: Warning zone
[ INFO] [1479229421.641967924, 2654.070000000]: Warning zone

دعونا نذكر الموضوعات:

rostopic list

من بين المواضيع سنرى:

/cmd_vel_mux/input/teleop
...
/mobile_base/commands/velocity

إظهار الرسائل في الموضوع / mobile_base / أوامر / السرعة:

rostopic echo /mobile_base/commands/velocity

احصل على سرعة الروبوت:

linear: 
  x: 0.1
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 0.0
---

سوف يتحرك الروبوت نحو مجلس الوزراء ويتوقف أخيرًا بجوار مجلس الوزراء في منطقة الخطر. في Gazebo ، سنرى نقطة توقف كاملة للروبوت:

الصورة

في إخراج عقدة safety_control_node ، سنرى الرسائل:

[ INFO] [1479229426.604300460, 2658.980000000]: Danger zone
[ INFO] [1479229426.717093096, 2659.100000000]: Danger zone

وفي الموضوع / mobile_base / الأوامر / السرعة ، سيتم الآن نشر رسالة بدون سرعة:

linear: 
  x: 0.0
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 0.0
---

PointCloud2 /output rviz. Color Transformer FlatColor Color. safety_control_node:

الصورة

, . :

الصورة

, :

الصورة

rviz :

الصورة

:

[ INFO] [1479230429.902116395, 3658.000000000]: Safe zone
[ INFO] [1479230429.992468971, 3658.090000000]: Safe zone

:

---                                                                                                                                                                                 
linear: 
  x: 0.2
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 0.0
---

: .

TurtleBot , (ASUS Xtion ROS Indigo). , Microsoft Kinect.

. — — TurtleBot Gazebo.

!

Source: https://habr.com/ru/post/ar399151/


All Articles