Momenta Challenge


软件功能

深度学习 & 图像识别
ROS
路径规划
行为决策
控制

硬件部分

Turtlebot3
树莓派
Camera
控制器与电机
  • OpenCR Arduino IDE

ROS Navigation Stack

attachment:overview_tf.png


导航核心模块

  • move_base ( 规划、避障与控制 )
  • gmapping ( 激光SLAM$\to$地图 ) $\to$
  • $\to$ amcl ( 基于地图的定位 ) 替代方案:fake_localization
  • robot_pose_ekf ( /odom_combined ) $\to$ odom_ekf.py

注意事项

EKF 需要协方差矩阵

static_transform_publisher from /map $\to$ /odom

tf from /odom or /odom_combined $\to$ /base_link or /base_footprint

导航推测 ( dead reckoning )

参考程序:ros_exploring

<launch>

    <param name="use_sim_time" value="false" />

    <!-- 设置地图的配置文件 -->
    <arg name="map" default="gmapping_map.yaml" />

    <!-- 运行地图服务器,并且加载设置的地图-->
    <node name="map_server" pkg="map_server" type="map_server" args="$(find mrobot_navigation)/maps/$(arg map)"/>

    <!-- 运行move_base节点 -->
    <include file="$(find mrobot_navigation)/launch/fake_move_base.launch" />

    <!-- 运行虚拟定位,兼容AMCL输出 -->
    <node pkg="fake_localization" type="fake_localization" name="fake_localization" output="screen" />

    <!-- 对于虚拟定位,需要设置一个/odom与/map之间的静态坐标变换 -->
    <node pkg="tf" type="static_transform_publisher" name="map_odom_broadcaster" args="0 0 0 0 0 0 /map /odom 100" />

    <!-- 运行rviz -->
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find mrobot_navigation)/rviz/nav.rviz"/>

</launch>
ROS 同时接收多话题与发布
  • Class 类结构
  • 多线程
#include <ros/ros.h>  
#include "std_msgs/String.h"
#include <boost/thread.hpp>
#include <sstream>

class SubscribeAndPublish  
{  
public:  
  SubscribeAndPublish()  
  {  
    count = 0;
    //Topic you want to publish  
    pub_ = n_.advertise<std_msgs::String>("/chatter_pub", 1000);  

    //Topic1 you want to subscribe  
    sub_ = n_.subscribe("chatter1", 10, &SubscribeAndPublish::callback1, this); 
    //Topic2 you want to subscribe  
    sub2_ = n_.subscribe("chatter2", 10, &SubscribeAndPublish::callback2, this);  
  }  

  void callback1(const std_msgs::String::ConstPtr& msg1)  
  {  
    ROS_INFO("I heard: [%s]", msg1->data.c_str()); 
    //.... do something with the input and generate the output...
    std::stringstream ss;
    ss << "Pub: hello world " << count;
    output.data = ss.str();
    pub_.publish(output);
    ROS_INFO("%s", output.data.c_str()); 
    ++count; 
  }  
  void callback2(const std_msgs::String::ConstPtr& msg2); 

private:  
  ros::NodeHandle n_;   
  ros::Publisher pub_;  
  ros::Subscriber sub_;
  ros::Subscriber sub2_; 
  std_msgs::String output;
  int count; 

};//End of class SubscribeAndPublish  

int main(int argc, char **argv)  
{  
  //Initiate ROS  
  ros::init(argc, argv, "subscribe_and_publish");  

  //Create an object of class SubscribeAndPublish that will take care of everything  
  SubscribeAndPublish test;  
  //ros::spin();
  ros::MultiThreadedSpinner s(2);  //多线程
  ros::spin(s);  

  return 0;  
}  

void SubscribeAndPublish::callback2(const std_msgs::String::ConstPtr& msg2)
{
  ROS_INFO("I heard: [%s]", msg2->data.c_str());
  ros::Rate loop_rate(0.5);//block chatterCallback2() 0.5Hz
  loop_rate.sleep();
}

References

  1. ROS机器人开发实践
  2. ROS By Example