★ROS创建功能包
$ cd %TOP_DIR_YOUR_CATKIN_WS%/src
$ catkin_create_pkg robot_setup_tf roscpp tf geometry_msgs
★TF变换
https://www.ncnynl.com/archives/201702/1329.html
tf_broadcaster.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
int main(int argc, char** argv){
ros::init(argc, argv, "robot_tf_publisher");
ros::NodeHandle n;
ros::Rate r(100);
tf::TransformBroadcaster broadcaster;
//创建一个tf::TransformBroadcaster类的实例,用来广播 base_link → base_laser的变换关系
while(n.ok()){
broadcaster.sendTransform(
tf::StampedTransform(
tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.1, 0.0, 0.2)),
ros::Time::now(),"base_link", "base_laser"));//Quaternion四元数来存储旋转变换的参数,第二个参数是坐标的位移变换,第三个参数是时间戳,第四个参数是母节点存储的参考系,即base_link,最后一个参数是子节点存储的参考系,即base_laser
r.sleep();
}
}
tf_listener.cpp
#include <ros/ros.h>
#include <geometry_msgs/PointStamped.h>
#include <tf/transform_listener.h>//一个TransformListener对象自动订阅了ROS变换消息话题和管理所有的进入的转换数据
void transformPoint(const tf::TransformListener& listener){
//创建一个函数,给定TransformListener,在“base_laser”坐标系中取一个点,并将其转换为“base_link”坐标系
geometry_msgs::PointStamped laser_point;//创建一个点作为geometry_msgs::PointStamped,这里“Stamped”只是意味着它包含一个头,允许我们将时间戳和frame_id与消息相关联
laser_point.header.frame_id = "base_laser";//因为我们在“base_laser”坐标系中创建一个点
//we'll just use the most recent transform available for our simple example
laser_point.header.stamp = ros::Time();
//just an arbitrary point in space
laser_point.point.x = 1.0;
laser_point.point.y = 0.2;
laser_point.point.z = 0.0;
try{
geometry_msgs::PointStamped base_point;
listener.transformPoint("base_link", laser_point, base_point);//参数为我们想要将点转换为的坐标系的名称,我们正在转换的点,存储变换点
//TransformListener对象d transformPoint()函数就是用来变换的
ROS_INFO("base_laser: (%.2f, %.2f. %.2f) -----> base_link: (%.2f, %.2f, %.2f) at time %.2f",
laser_point.point.x, laser_point.point.y, laser_point.point.z,
base_point.point.x, base_point.point.y, base_point.point.z, base_point.header.stamp.toSec());
}
catch(tf::TransformException& ex){
ROS_ERROR("Received an exception trying to transform a point from \"base_laser\" to \"base_link\": %s", ex.what());
}//打印错误
}
int main(int argc, char** argv){
ros::init(argc, argv, "robot_tf_listener");
ros::NodeHandle n;
tf::TransformListener listener(ros::Duration(10));
//we'll transform a point once every second
ros::Timer timer = n.createTimer(ros::Duration(1.0), boost::bind(&transformPoint, boost::ref(listener)));
ros::spin();
}
★ joint_state_publisher包
sudo apt-get install ros-kinetic-joint-state-publisher
在launch文件里加入下面这句,用来描述机器人各个关节状态的主题
<node name="joint_state_publisher" pkg="learning_urdf" type="joint_state_publisher" />
★robot_state_publisher包
sudo apt-get install ros-kinetic-robot-state-publisher
在launch文件里加入下面这句,用来加载robot状态发布节点
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
"robot_state_publisher"就是一个tf广播器, 它是一个C++的程序,订阅了"joint_states"主题,计算各个坐标系之间的变换关系,并将之广播出去
主题的发布者只有joint_state_publisher,订阅者是robot_state_publisher。
★保存地图
rosrun map_server map_saver -f map(地图名称)