launch文件

rosrun每次只能启动一个ros节点,然而通常一个ros功能包当中包括很多个节点,如果一个一个的去启动会很麻烦,ros提供了launch文件来解决这个问题。

launch文件可以通过一系列的配置来同时启动多个ros节点。launch文件通过XML语言来编写,其中包含了一系列的标签,每个标签中又包含了很多属性。所以我们使用launch文件之前需要了解那些标签的含义以及属性的内容。

launch文件还有一个重要的功能,就是它可以自动启动ros master,省去了我们通过roscore开启节点管理器的步骤。

launch文件的使用方式roslaunch pkg-name launchfile-name  eg:

roslaunch a testlaunch.launch

也可以在launch文件所在目录下直接使用:roslaunch launchfile-name 来直接启动launch文件。

roslaunch testlaunch.launch

launch文件的写法

1、<launch>标签是launch文件的根元素,所有其他的标签和属性都需要定义在其中。

2、<node>标签的作用是启动ros当中的一个节点。基本格式为:

<node  pkg="package-name"  type="executable-name"  name="node-name"/>

pkg、type和name为<node>标签最基本的属性。其中:

pkg 表示节点所在的功能包名称

type 表示节点的可执行文件名称

name 表示节点名称(注意!!!这里定义的节点名字会覆盖我们源代码中定义的节点名,所以如果不想为节点改名字的话记得与源文件中的名字一致)

此外<node>标签还有output控制节点内部的输出信息和日志信息是否要打印到屏幕或者文件、respawn控制节点启动失败后是否重新启动、required表示当前节点为必须启动的节点,如果启动失败则整个launch文件无法启动、ns表示节点的命名空间、args定义节点需要的输入参数(多个输入参数之间用空格隔开即可)等属性。

3、<param>标签或者<rosparam>标签的作用是设置ROS中运行的全局参数,存储在参数服务中。

<param>标签的使用格式为:

<param  name="param-name"  value="param-value" />

其中:

name 表示参数名

value 表示参数值

对于某些节点需要加载大量的参数,比如加载机器人模型,使用<param>标签一个一个的设置未免太过麻烦。我们可以把所有的参数集中保存到.yaml格式的参数文件中,ros中提供了<rosparam>标签来批量加载参数文件中的多个参数。使用格式为:

<rosparam  file="params.yaml"  command="load"  ns="params" />

其中:

file 表示参数文件

command 表示加载命令

ns 表示为加载进来的参数创建的命名空间,以免与已有的参数产生命名上的冲突

4、<arg>标签的作用为设置launch文件内部的局部变量,这些变量仅限于本launch文件使用。

使用格式为:

<arg  name="arg-name"  default="arg-value" />

其中:

name 表示变量名

default 表示变量值

变量的调用方法:$(arg arg-name)  eg:

在设置全局参数时

<param  name="x"  value="$(arg arg-name) " />  

或者设置节点输入参数时

<node  name="node-name"  pkg="pkg-name"  type="executable-name"  args="$(arg arg-name1)   $(arg arg-name2)  ... " />

5、<remap>标签的作用是重映射ros计算图资源的命名(如话题名)。通常我们使用别人做好的功能包时,接口可能并不符合我们预留的接口,我们可以使用重映射来更改接口的名称来对接我们的工程。但是要注意,使用重映射之后,因为计算图中的名称已经更改,所有其他依赖原接口名称的功能都将不能工作。

使用格式为:

<remap  from="old_name"  to="new_name" />

其中:

from 表示源文件中定义的原资源名称

to 表示经过重映射后的新名称

6、<include>标签的作用是嵌套其他的launch文件。

使用格式为:

<include   file="$(launchfile-path)/launchfile.launch" />

其中,file表示被嵌套的launch文件路径。

 

有关launch文件更详细的写法参见官方文档:http://wiki.ros.org/roslaunch/XML

 

TF树

TF功能包主要提供对机器人各个部件局部坐标系与全局坐标系之间的坐标变换关系的管理。比如机器人夹取的物体相对于机器人底座的坐标位置在哪里?

TF坐标变换的信息在ros中以树形结构来保存。我们可以通过以下两个部分来完成两个坐标系之间的坐标转换:

1、广播TF变换

通过广播,将已知的坐标变换关系插入的树形结构当中。

2、监听TF变换

监听树形结构的数据,通过TF树获取我们需要的任意两个坐标系之间的变换关系。

TF广播器的c++实现

实现步骤大致如下:

1、定义TF广播器

2、创建坐标变换关系

3、发布坐标变换

#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广播器
    // 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
    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];
    // 订阅乌龟的pose信息
    ros::NodeHandle node;
    ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
 
    ros::spin();
    return 0;
};

TF监听器的c++实现

实现步骤大致如下:

1、定义TF监听器

2、查找坐标变换

#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;
 
    // 通过服务调用,产生第二只乌龟turtle2
    ros::service::waitForService("spawn");
    ros::ServiceClient add_turtle =
    node.serviceClient<turtlesim::Spawn>("spawn");
    turtlesim::Spawn srv;
    add_turtle.call(srv);
 
    // 定义turtle2的速度控制发布器
    ros::Publisher turtle_vel =
    node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
    
    tf::TransformListener listener;  // tf监听器
    ros::Rate rate(10.0);
    while (node.ok())
    {
        tf::StampedTransform transform;
        try
        {
            // 查找turtle2与turtle1的坐标变换
            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;
        }
 
        // 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
        // 并发布速度控制指令,使turtle2向turtle1移动
        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;
};

修改CMakeLists.txt文件

1)、添加要编译的文件

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)

2)、设置链接库

target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

编译功能包

回到工作空间,运行catkin_make对功能包进行编译。

 

Qt工具

ros当中有很多基于Qt开发的可视化工具,简称为Qt工具。包括:

rqt_console  日志输出图形界面工具

rqt_graph  计算图可视化工具

rqt_plot  数据曲线绘图工具

rqt_reconfigure  全局参数动态配置图形界面工具等等。

 

rviz数据三维可视化工具

同样是基于Qt开发的,但是功能要比上面介绍的几个Qt工具要强大的多。

其工作界面如下:

0   表示3d视图区,可视化的数据就显示在此区域

1   工具栏区域

2   显示项设置列表区

3   观察视角设置区

4   时间显示区域

rviz还提供了插件机制,我们可以结合Qt开发一些适用于自己项目的插件。

 

gazebo三维物理仿真平台

gazebo是一个开源免费的软件。它具有强大的物理引擎,与ros良好兼容的接口。主要用于物理仿真,测试机器人算法,设计机器人结构等。

工作界面如下:

0   代表3d视图区域,用来显示仿真环境

1   工具栏区域

2   显示机器人各部分模型的列表区

3   模型属性设置区

4   时间显示区域