足球机器人
软件功能
深度学习 & 图像识别
ROS
路径规划
行为决策
控制
硬件部分
Turtlebot3
树莓派
Camera
控制器与电机
- OpenCR Arduino IDE
ROS Navigation Stack
导航核心模块
- 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
- ROS机器人开发实践
- ROS By Example