1.launch启动文件
基本元素
启动文件Launch File是ROS中一种同时启动多个节点的途径。可以自动启动ROS Master并实现多个节点的各种配置,为多个节点的操作提供了很大便利。
先来看一个简单的.launch文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <launch> <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/> <param name="scale_linear" value="2" type="double"/> <param name="scale_angular" value="2" type="double"/>
<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" /> <node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" />
</launch>
|
其中:
参数设置
变量声明,由param和arg两种标签元素,它们的作用是不同的
重映射机制(重要)
ROS提供一种重映射机制,便于将社区中其他人的功能包提供的接口进行重映射,而不是直接修改。
例如乌龟控制节点发布的控制话题可能是/turtlebot/cmd_vel,但是我们机器人订阅的话题是/cmd_vel,此时只需要重映射,我们的机器人就能收到话题消息了
1
| <remap from="/turtlebot/cmd_vel" to="/com_vel"/>
|
2.TF变换
TF功能包使用树形数据结构,可以让用户跟踪多个坐标系,以时间为轴跟踪这些坐标系(默认10s内),并允许开发者请求如下数据:
- 5s前,机器人头部坐标系相对于全局坐标系是怎样的?
- 机器人夹取的物体相对于机器人中心坐标系的位置在哪?
- 机器人中心坐标系相对于全局坐标系的位置在哪?
想要使用TF功能包,总体来说要以下两个步骤:
- 监听TF变换,接收并缓存系统中发布的所有坐标数据,并查询需要的坐标变换关系
- 广播TF变换,向系统广播坐标变换关系
乌龟例程中的TF
该环境若出现问题可看linux、ROS杂 | 小董的BLOG
- 准备库环境:
sudo apt-get install ros-noetic-turtle-tf
- 启动launch文件进行实验:
roslaunch turtle_tf turtle_tf_dmeo.launch
- 开启键盘控制:
rosrun turtlesim turtle_teleop_key
可得到两只乌龟,一只会跟踪另一只
rosrun tf view_frames后可在用户根目录下找到frames.pdf。可得当前系统中存在三个坐标系:world、turtle1、turtle2,其中world为TF树的根节点。
rosrun tf tf_echo turtle1 turtle2可实时查看当前turtle2跟随turtle1所需的坐标变换
得到坐标变换后,便可以计算两乌龟间的距离和角度。
创建TF广播器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <ros/ros.h> #include <tf/transform_broadcaster.h> #include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg) { static tf::TransformBroadcaster br;
tf::Transform transform; transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) ); tf::Quaternion q; q.setRPY(0, 0, msg->theta); transform.setRotation(q);
br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name)); }
int main(int argc, char** argv) { ros::init(argc, argv, "my_tf_broadcaster"); if (argc != 2) { ROS_ERROR("need turtle name as argument"); return -1; }; turtle_name = argv[1];
ros::NodeHandle node; ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
ros::spin();
return 0; };
|
创建TF监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <ros/ros.h> #include <tf/transform_listener.h> #include <geometry_msgs/Twist.h> #include <turtlesim/Spawn.h>
int main(int argc, char** argv) { ros::init(argc, argv, "my_tf_listener");
ros::NodeHandle node;
ros::service::waitForService("spawn"); ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("spawn"); turtlesim::Spawn srv; add_turtle.call(srv);
ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
tf::TransformListener listener;
ros::Rate rate(10.0); while (node.ok()) { tf::StampedTransform transform; try { listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0)); listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform); } catch (tf::TransformException &ex) { ROS_ERROR("%s",ex.what()); ros::Duration(1.0).sleep(); continue; }
geometry_msgs::Twist vel_msg; vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(), transform.getOrigin().x()); vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) + pow(transform.getOrigin().y(), 2)); turtle_vel.publish(vel_msg);
rate.sleep(); } return 0; };
|
通过launch文件运行这些节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <launch> <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" /> <node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" />
<node pkg="learning_tf" type="turtle_tf_listener" name="listener" />
</launch>
|