ROS操作系统学习

1 工程结构

1.1 Catkin工作空间与编译系统

1.1.1 创建工作空间catkin_ws

$ mkdir -p ~/catkin_ws/src     # mkdir -p 可以一次创建多级文件夹
$ cd ~/catkin_ws/
$ catkin_make                  # 建立工作空间

1.1.2 编译

$ cd ~/catkin_ws            # 回到工作空间
$ catkin_make
$ source -/catkin_ws/devel/setup.bash      # 把新建的工作空间刷新到环境变量中

1.1.3 工作空间下级文件夹

  src: package源代码

  build: cmake&catkin缓存和中间文件

  devel: 目标文件 { 头文件、动态链接库、静态链接库、可执行文件

1.2 Package组成

1.2.1 最精简结构:CMakeList.txt  和  package.xml

  CMakeList.txt:规定catkin编译的规则,例如 源文件、依赖项、目标文件

  具体语法介绍参考:https://blog.csdn.net/afei__/article/details/81201039

  package.xml:如果要更改只需要<build_depend>(编译时的依赖),<run_depend>(运行时的依赖)

1.2.2 代码文件

scripts:python文件( *.py),shell文件( *.sh)

include:C++头文件( *h.)

src:C++源文件( *.cpp),python modle(可被import的python文件)

1.2.3 自定义通信格式

新建 srv 文件夹:存放 *.srv 文件

新建 msg 文件夹:存放 *.msg 文件

新建 action 文件夹:存放 *.action 文件

1.2.4 launch以及配置文件

*.launch 文件:同时运行多个可执行文件,放在package下的launch路径中

*.yaml 配置文件:配置文件,放在package下的config路径中

1.3 常用指令

1. rospack

  $ rospack find package_name:查找某个pkg的地址

  $ rospack list:列出本地所有pkg

2. rosch

  $ rosch package_name:跳转到某个pkg路径下

3. rosls

  $ rosls package_name:列举某个pkg下的文件信息

4. rosed

  $ rosed package_name file_name:编辑pkg中的文件

5. catkin_create_pkg

  $ catkin_create_pkg<pkg_name>:创建一个pkg

6. rosdep

  $ rosdep install [pkg_name]:安装某个pkg所需的依赖

2 通信架构

2.1 Master和Node

Master:每个Node启动时都要向Master注册;管理各Node之间的通信

$ roscore:启动Master(节点管理器),同时启动 rosout(日志输出)、parameter server(参数服务器)

--------------------

Node:ROS的进程;pkg里的可执行文件运行的实例

$ rosrun [pkf_name] [node_name]:启动一个node

$ rosnode list:列出当前运行node信息

$ rosnode info [node_name]:显示某个node的详细信息

$ rosnode kill [node_name]:结束某个node

--------------------

$roslaunch [pkg_name] [file_name.launch]:启动master 和多个node

2.2 通信方式

Topic(主题) Service(服务) Parameter Server(参数服务器) Actionlib(动作库)

2.2.1 Topic和Msg

Topic 是ROS中的异步通信方式。Node通过 publish—subscribe机制,以Topic为中转站的方式进行通信。

--------------------

Message 是topic中内容的数据类型,定义在 *.msg 文件中。

--------------------

$ rostopic list:列出当前所有topic

$ rostopic info [topic_name]:显示某个topic的属性信息

$ rostopic echo [topic_name]:显示某个topic的内容

$ rostopic pub [topic_name]:向某个topic发布内容

$ rosmag list:列出系统上所有的msg

$ rosmag show [msg_name]:显示某个msg内容

2.2.2 Service和srv

Service 是ROS种的同步通信方式,Node之间可以通过 reques—reply 方式通信

--------------------

srv 是Service通信的数据格式,定义在 *.srv文件中

--------------------

$ rosservice list:列出当前所有活跃的service

$ rosservice info [service_name]:显示某个service的属性信息

$ rosservice call [service_name] [args]:调用某个service参数

$ rossrv list:列出系统上所有的srv

$ rossrv show [srv_name]:显示某个srv的内容

Topic VS Service

  Topic Service 通信方式 异步通信 同步通信 实现原理 TCP / IP TCP / IP 通信模型 Publish - Subscribe Request - Reply   多对多 多对一   接收者收到数据会回调 (Callback) 远程过程调用(RPC)服务器端的服务 应用场景 连续、高频的数据发布 偶尔调用的功能/具体的任务 举例 激光雷达、里程计发布数据 开关传感器、拍照、逆解计算

2.2.3 Parameter Server

Parameter Server 是存储各个参数的字典,可用命令行,launch文件和node(API)读写

Key/rosistro/rosversion/use_sim_time....
Value'kinetic''1.12.7'true....
$ rosparam list:列出当前所有参数

$ rosparam get [param_key]:显示某个参数的值

$ rosparam set [param_key] [param_value]:设置某个参数的值

$ rosparam dump [file_name]:保存参数到文件

$ rosparam load [file_name]:从文件读取参数

$ rosparam delete [file_name]:删除参数

在launch文件中:

<param>:<param name=" **** " value=" **** ">或<param name=" **** " command=" **** ">

<rosparam>:<rosparam file = "$指定yaml文件" command=" **** ">

2.2.4 Action

Action 类似于Service,是一种带有状态反馈的通信方式。通常用在长时间、可抢占的任务中。

--------------------

action 通信得数据格式,定义在 *.action文件中。

举例:

./action/DoDishes.action

# Define the goal
uint32 dishwasher_id
# Specify which dishwasher we want to use
---
# Define the result
uint32 total_dishes_cleaned
---
# Define a feedback message
float32 percent_complete
move_base_msgs/action/MoveBase.action

# Define the goal
geometry_msgs/PoseStamped target_pose
---
# Define the result

---
# Define a feedback message
geometry_msgs/PoseStamped base_position

3 常用工具

3.1 Gazebo

  应用于机器人仿真工具,ODE物理引擎,用于动力学、导航、感知等任务的模拟

3.2 RViz

  The Robot Visualization tool 机器人可视化工具。可方便监控和调试

3.3 rqt

可视化工具,常用于rqt_graph(显示通信架构),rqt_plot(绘制曲线),rqt_console(查看日志)

3.4 RosBag

 ROS命令行工具,记录和回放数据流

# 记录某些topic到bag中
$ rosbag record [topic_name]

# 记录所有的topic到bag中
$ rosbag record -a

# 回放bag
$ rosbag play [bag_files]

4 roscpp

4.1 Client Library 与 roscpp

  roscpp 是ROS为机器人开发者们提供了不同语言的编程接口,其中C++接口叫做roscpp。

  Client Libaray 是提供ROS编程的库。例如建立node,发布消息,调用服务。

void ros::init(); # 解析ROS参数,为该node命名。利用限定符“::”表示该命名实在ROS这个限定空间中的
ros::NodeHandle Class      //类

//常用成员函数
# 创建topic的publisher
ros::Publisher advertise(const string &topic,uint32_t queue_size);

# 创建topic的subscriber
ros::Subscriber subscriber(const string &topic,uint32_t queue_size,void(*)(M));

# 创建服务的server
ros::ServiceServer advertiseService(const string &service,bool(*srv_func)(Mreq &,Mres &));

# 创建服务的client
ros::ServiceClient serviceClient(cont string &service_name,bool persistent=false);

# 查询某个参数的值
bool getParam(const string &key,void &val);

# 给参数赋值
bool setparam(const string &key,void val);
ros::master Namespace

//常用函数
# 检查master是否启动
bool check();

# 返回master所处的hostname
const string& getHost();

# 从master返回已知的node名称列表
bool getNodes(V_string &nodes);

# 返回所有正在被发布的topic列表
bool getTopic(V_Topiclnfo &topics);

# 返回到master的URI地址
bool getURI();

# 返回master运行在的端口
uint32_t getPort();
ros::this_node Namespace 

//常用函数
# 返回本node发布的topic
void getAdvertisedTopics(V_string &topics);

# 返回当前node的名称
const string &getName();

# 返回当前node的命名空间
const string &getNamespace();

#返回当前node订阅的topic
void getSubscribedTopics();
ros::service Namespace

常用函数
# 调用一个RPC服务
bool call(const string &service,Service &service);

# 创建一个服务的client
serviceClient createClient(const string& service_name,bool persistent=false);

# 确认服务可调用
boll exists(const string &service_name,bool print_failure_reason);

# 等待一个服务,直到他可调用
bool waitForService(const string &service_name,int32_t timeout);
ros::names Namespace

//常用函数
# 追加名称
string append(const std::string &lefy,const std::string &right)

# 清除图资源名称:删除双斜杠、结尾斜杠等
string clean(const string &name);

# 返回重映射remapping
const M_string &getRemappings();

# 解析出名称的全名
string resolve(const string &name,bool remap=ture);

# 验证名称
bool validate(const string &name,string &error);

4.2 topic_demo

  功能描述:两个node,一个用于发布模拟的GPS消息(格式为自定义,包括坐标和工作状态),另一个接收并处理该信息(计算到原点的距离)。

  步骤:①package ②msg ③talker.cpp ④listener.cpp ⑤CMakeList.txt & package.xml

①package包含我们所有的源代码 

$ cd ~/catkin_ws/src
$ catkin_create_pkg topic_demo roscpp rospy std_msgs  
//在使用catkin_create_pkg时,一些依赖的功能包需要提供出来,这些直接(一级)依赖关系可以通过命令工具rospack查看:"rospack depends1 beginner_tutorials"

②msg是我们自定义的消息格式 

$ cd topic_demo/
$ mkdir msg
$ cd msg
$ vi gps.msg

 gps.msg

# 坐标
float32 x
float32 y
# 定义工作状态
string state

然后需要对该文件进行编译。编译完成后会在~/catkin_ws/devel/include/topic_demo下创建gps.h文件

③④我们将两个node分别放在两个cpp文件中。

talker.cpp

#include <ros/ros.h>
#include <topic_demo/gps.h>

int main(int argc,char **argv)
{
    ros::init(argc,argv,"talker");  //解析参数,将node命名为talker
    ros::NodeHandle nh;            //创建句柄,实例化node
    
    topic_demo::gps.msg;            //创建gps消息
    msg.x = 1.0;                    //初始化
    msg.y = 1.0;
    msg.state = "working";
    
    ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info",1);  //创建publisher,命名为gps_info
    pub.publish(msg);               //发布消息
    ros::Rate loop_rate(1.0);        //定义循环发布的频率1Hz
    while(ros::ok())                //判断程序是否还在运转
    {
        msg.x = 1.03 * msg.x;       //以指数增长,每次间隔1s
        msg.y = 1.03 * msg.y;
        ROS_INFO( "Talker:GPS:x=%f,y=%f",msg.x,msg.y);                 //显示当前msg
    
        pub.publish(msg);           //发布信息
        loop_rate.sleep();          //控制程序休眠,从而达到以一定频率发布
    }
    return 0;
}

listener.cpp

#include <ros/ros.h>
#include <topic_demo/gps.h>
#include <std_msgs/Float32.h>

void gpsCallback(const topic_demo::gps::ConstPtr &msg)    //长指针ConstPtr
{
    std_msgs::Float32 distance;
    distance.data = sqrt(pow(msg->x,2),pow(msg->y,2));
    ROS_INFO("Listener:Distance to otingin = %f,state = %s",distance.data,msg->state.c_str());
}

int main(int argc,char **argv)
{
    ros::init(argc,argv,"listener");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("gps_info",1,gpsCallback);  //创建subscriber
    
    ros::spin();            //反复调用当前可触发的回调函数,阻塞函数
    return 0;
}

⑤修改CMakeList.txt & package.xml提示编译系统去编译这些文件

CMakeList.txt

package.xml

4.3 service_demo

  功能描述:两个node,一个发布请求(格式自定义),另一个接收处理该信息,并返回信息。

  步骤:①package ②srv ③server.cpp ④client.cpp ⑤CMakeList.txt & package.xml

①package包含我们所有的源代码 

$ cd ~/catkin_ws/src
$ catkin_create_pkg service_demo roscpp rospy std_msgs  
//在使用catkin_create_pkg时,一些依赖的功能包需要提供出来,这些直接(一级)依赖关系可以通过命令工具rospack查看:"rospack depends1 beginner_tutorials"

②msg是我们自定义的消息格式 

$ cd service_demo/
$ mkdir srv
$ cd srv
$ vi Greeting.srv

Greeting.srv

#服务请求的数据
string name
int32 age
---
#服务回传的内容
string feedback

然后需要对该文件进行编译。

编译完成后会在~/catkin_ws/devel/include/service_demo下创建Greeting.h  GreetingRequest.h  GreetingResponse.h  文件

server.cpp

#include <ros/ros.h>
#include <service_demo/Greeting.h>

bool handle_function(service::demo::Greeting::Request &req,service::demo::Greeting::Response &res)  //传入的参数包含两部分,这两种都是在编译Greeting.srv时编译器自动生成的
{
    //显示请求信息
    ROS_INFO(“Request from %s with age %d”,req.name.c_str(),req.age); //string转化成const char*
    //处理请求,并将结果写入response
    res.feedback = "HI" + req.name + "I am server!";
    //返回true,正确处理了请求
    return true;
}

int main(int argc,char **argv)
{
    ros::init(argc,argv,"Greetings_server");
    ros::NodeHandle nh;
    ros::ServiceServer service = nh.advertiseService("greetings",handle_function);  //服务处理函数
    ros:spin();
    return();
}

client.cpp

#include <ros/ros.h>
#include <service_demo/Greeting.h>

int main(int argc,char **argv)
{
    ros::init(argc,argv,"greetings_server");
    ros::NodeHandle nh;
    ros::ServiceClient client = nh.serviceClient<service_demo::Greeting>("greetings");
    // 定义service客户端,service名字为“greetings”,service类型为Service_demo

    service_demo::Greeting srv;
    srv.request.name = "HAN";
    srv.request.age = "20";    
    
    if (client.call(srv))
    {
        ROS_INFO("Feedback from server: %s.",srv.response.feedback);
    }
    else
    {
        ROS_EEROR("Failed to call service greetings.");
        return 1;
    }
    return 0;
}

4.4 param_demo

param_demo.cpp

#include <ros/ros.h>

int main(int argc,char **argv)
{
    ros::init(argc,argv,"greetings_server");
    ros::NodeHandle nh;
    int parameter1,parameter2, parameter3,parameter4,parameter5;

    //获取参数的不同方式
    ros::param::get("param1",parameter1);
    nh,getParam("param2",parameter2);
    nh.param("param3",parameter3,100);    //将parameter3的值赋值给param3,如果parameter3中没有值,将默认值100赋值给param3
    //设置参数
    ros::param::set("param4",parameter4);
    nh.setParam("param5",parameter5);
    //检查参数是否存在
    ros::param::has("param5");
    nh.hasParam("param6");
    //删除参数
    ros::param::del("parma5");
    nh.deleteParam("param6");

    return 0;
}

param_demo_cpp.launch

<launch>   //开始

<!--Param标签设置单个参数-->
<param name = "param1" value="1" />
<param name = "robot_description" command="$(find xacro)/xacro.py $(find demo)/urdf/robot.urdf" />

<!--rosparam标签设置多个参数-->
<rosparam>
    param3:3
    param4:4
    param10:helloworld!
</rosparam>

<rosparam file="$(find param_demo)/config/myparam.yaml" command="load" />

<node pkg="param_demo" type="param_demo" name="param_demo" output="screen" />

</launch>   //结束

 

5 rospy

5.1 rospy介绍

5.1.1 rospy-Node相关

函数:

类型函数名注释
 init_node(name)注册和初始化node
MasterProxyget_master()获取master的句柄
boolis_shutdown()返回是否关闭
 on_shutdown(fn)在node关闭时调用函数
strget_node_uri()返回节点的URI
strget_name()返回本节点的全名
strget_namespace()返回本节点的名字空间

5.1.2 rospy-Topic相关

函数:

[[str,str]]get_published_topics()返回正在被发布的所有topic_name(str)和topic_type(str)
Messagewait_for_message(topic,topic_type,time_out=None)等待指定topic的一个message
 spin()出发topic或service的处理,会阻塞直到关闭

Publisher类:

__init__(self,name,data_class,queue_size=None)构造函数
publish(self,msg)成员函数 发布消息
unregister(self)成员函数 停止发布

Subscriber类:

__init__(self,name,data_class,call_back=None,queue_size=None)构造函数
unregister(self)成员函数 停止订阅

5.1.3 rospy_Service相关

函数:

wait_for_service(service,timeout = None)阻塞直到服务可用

Service类(server):

__init__(self,name,service_class,hanlder)构造函数 提供服务
shutdown(self)成员函数 关闭服务

 ServiceProxy类(client):

 __init__(self,name,service_class)构造函数 服务的请求方
Responsecall(self,*args,**kwds)调用服务
Response__call__(self,*args,**kwds)调用服务

5.1.4 rospy_Param相关

函数:

XmlRpclegalValueget_param(param_name,default = _unspecified)获取参数的值
[str]get_param_names()获取参数的名称
 set_param(param_name,param_value)设置参数的值(key,value)
 delete_param(param_name)删除参数
boolhas_param(param_name)参数是否存在于参数服务器上
strsearch_param()搜索参数

5.1.5 rospy_Time相关

Time类:

 __init__(self,secs=0,nsecs=0)构造函数
Timenow()静态方法 返回当前时刻的Time对象

函数:

Timeget_rostime()当前时刻的Time对象
floatget_time返回当前时间,返回float(单位 秒)
 sleep(duration)执行挂起

Rate类:

 __init__(self,frequency)构造函数
 sleep(self)挂起 考虑上一次的rate.sleep()时间
Timeremaining(self)成员函数 剩余sleep实践

Duration类:

__init__(self,secs=0,nsecs=0)构造函数 秒和纳秒

5.2 topic_demo

  功能描述:两个node,一个用于发布模拟的GPS消息(格式为自定义,包括坐标和工作状态),另一个接收并处理该信息(计算到原点的距离)。

  步骤:①package ②msg ③talker.py ④listener.py ⑤CMakeList.txt & package.xml

gps.msg

# 坐标
float32 x
float32 y
# 定义工作状态
string state

  然后需要对该文件进行编译。编译完成后会在~/catkin_ws/devel/lib/python2.7/dist-pacakges/topic_demo/msg/下创建__init__.py文件和msg文件夹(包含__init__.py文件 和 _gps.py)。

  可以 from topic_demo. msg import gps

pylistener.py

import rospyn
import math
from topic_demo.msg import gps

def callback(gps):
    distance = math.sqrt(math.pow(gps.x,2)+math.pow(gps.y,2))
    rospy,loginfo('Listener:GPS distance = %f,state :%s',distance,gps.state)  //输出

def listener():
    rospy.init_node('pylistener')
    rospy.Subscriber('gps_info',gps,callback)  //订阅消息的名称,订阅消息的类型(上面import的类型),收到消息后执行的函数
    ros.spin()

if __name__ == '__main__':
    listener()

pytalker.py

import rospy
from topic_demo.msg import gps

def talker():
    pub = rospy.Publisher('gps_info',gps,queue_size=10)
    rospy.init_node('pytalker',anonymous = Ture)
    rate = rospy.Rate(1)
    x = 1.0
    y = 2.0
    state = 'working'

    while not rospy is shutdown():
        rospy.loginfo('Talker: GPS: X = %f,y = %f')
        pub.publish(gps(state,x,y))
        x = 1.03 * x
        y = 1.03 * y
        rate.sleep()

if __name__ == '__main__':
    talker()

5.3 service_demo

  功能描述:两个node,一个发布请求(格式自定义),另一个接收处理该信息,并返回信息。

  步骤:①package ②srv ③server.cpp ④client.cpp ⑤CMakeList.txt & package.xml

Greeting.srv

#服务请求的数据
string name
int32 age
---
#服务回传的内容
string feedback

然后需要对该文件进行编译。

编译完成后会在~/catkin_ws/devel/lib/python2.7/dis-pacakages/service_demo/srv/下创建__init__.py Greeting.py GreetingRequest.py  GreetingResponse.py  文件

可以 from service_demo.srv import *(表明import该文件夹下所有文件)

③server_demo.py

import rospy
from service_demo.srv import *

def server_srv():
    rospy.init_node('greeting_server')
    s = rospy.Service('greetings',Greeting,handle_function)  //name,type,函数
    rospy.loginfo('Ready to handle the request:')
    rospy.spin()   //需要这一句来触发所有的service

def handle_function(req):
    rospy.loginfo('Request from',req.name,'with age',req.age)
    return GreetingResponse('Hi %s.I am server!',%req.name)

if __name__ == '__main__'
    server_srv()

④client_demo.py

import rospy
form service_demo.srv import *

def client_srv():
    rospy.init_node('greeting_client')
    rospy.wait_for_service('greetings')    //通过rospy.wait_for_service()函数来阻塞直到服务有效。
    try:
        greeting_client = rospy.ServiceProxy('greetings',Greeting)    //通过 rospy.ServiceProxy函数指定服务名来调用服务。
        rosp = greetings_client('HAN',20)
        rospy_loginfo('Message From Server: %s',%rosp.feedback)
    except rospy.ServiceException, e:
        rospy.logwarn('Service call failed: %s', %e)


if __name__ = '__main__':
    client_srv()

6 TF & URDF

6.1 TransForm(TF)

    TF 是坐标变换(位置+姿态),坐标系数据维护的工具。坐标转换的标准(tree)、话题(topic)、工具、接口。

    ROS中机器人模型包含大量的部件,这些部件统称之为link,每一个link上面对应着一个frame, 即一个坐标系.link和frame概念是绑定在一起的。每一个圆圈代表一个frame,对应着机器人上的一个link,任意的两个frame之间都必须是联通的,如果出现某一环节的断裂,就会引发error系统报错.所以完整的tf tree不能有任何断层的地方,这样我们才能查清楚任意两个frame之间的关系。每两个frame之间都有一个broadcaster,这就是为了使得两个frame之间能够正确连通,中间都会有一个Node来发布消息。broadcaster就是一个publisher,如果两个frame之间发生了相对运动,broadcaster就会发布相关消息。

6.2 TransformStamped.msg (TF消息)

    TransformStamped.msg 是两个 frame 之间的通信格式。

std_msgs/Header header
    uint32 seq            //序号
    time stamp            //时间
    string frame_id       //父坐标系
string child_frame_id     //子坐标系
geometry_msgs/Transform transform        //父子坐标系之间的变换关系
    geometry_msgs/Vector3 translation    //三维向量 表示平移
        float64 x
        float64 y
        float64 z
    geometry_msgs/Quaternion rotation    //四元数组 表示旋转
        float64 x
        float64 y
        float64 z
        float64 w

    tf/tfMessage.msg 或者 tf2_msgs/TFMessage 表示 TF tree 的通信格式。

geometry_msgs/TransformStamped[] tranforms   //将 TransformStamped 变成一个数组之后发给TF
    std_msgs/Header header
        uint32 seq            //序号
        time stamp            //时间
        string frame_id       //父坐标系
    string child_frame_id     //子坐标系
    geometry_msgs/Transform transform        //父子坐标系之间的变换关系
        geometry_msgs/Vector3 translation    //三维向量 表示平移
            float64 x
            float64 y
            float64 z
        geometry_msgs/Quaternion rotation    //四元数组 表示旋转
            float64 x
            float64 y
            float64 z
            float64 w

一个 TransformStamped 描述的是两个坐标系之间的关系,一个 TransformStamped数组 描述的就是一个 TF tree 之间的关系。

6.3 TF in C++

6.3.1 TF相关数据类型

向量tf::Vector
tf::Point
四元数tf::Quaternion
3*3矩阵tf::Matrix3*3
位姿tf::Pose
变换tf::Transform
带时间戳的以上类型tf::Stamped<T>
带时间戳的变换tf::StampedTransform

6.3.2 tf::TransformBroadcaster类

void sendTransform (const StampedTransform &transform)
void sendTransform (const std::vector<StampedTransform> &transforms)
void sendTransform (const geometry_msgs::TransformStamped &transform)
void sendTransform (const std::vector<geometry_msgs::TransformStamped> &transform)

6.3.3 tf::TransformListener类

void lookupTransform(const std::string &target_frame,    //目标坐标系
                     const std::string &source_frame,    //原坐标系
                     const ros::Time &time,              //查询具体哪一时刻的转换关系
                     StampedTransform &transform)const   //将查询的转换关系存放在第四个参数中
bool canTransform()            //Transform是否联通
bool waitForTransform()const   //等待Transform联通

6.4 tf in Python

  https://docs.ros.org/api/tf/html/python/tf_python.html#

  python 中存在 tf库,即使用时可以 import tf。

6.4.1 tf.transformations

  tf.transformations中包含基本数学运算函数。

euler_matrix(ai,aj,ak,axes='sxyz') # 欧拉角到矩阵
euler_form_matrix(matrix,axes='sxyz')  # 矩阵到欧拉角
euler_form_quanternion(quaternion,axes='sxyz')  # 四元数到欧拉角
quaternion_form_euler(ai,aj,ak,axes='sxyz')  # 欧拉角到四元数
quaternion_matrix(quaternion)  # 四元数到矩阵
quaternion_form_matrix(matrix)  # 矩阵到四元数

6.4.2 tf.TransformLister类

# frame是否相通
canTransform(self,traget_frame,source_frame,time)
# 阻塞直到frame相通
waitForTransform(self,target_frame,source_frame,time,timeout)
# 查看相对的tf,返回(trans,quat)
lookupTransform(self,target_frame,source_frame,time)

6.4.3 tf.TransformBroadcaster类

# 向 /tf (topic)发布消息
sendTransform(translation,rotation,time,child,parent)

sendTransformMessage(transform)

6.4.4 tf 指令

# 根据当前的tf树创建一个PDF图
$ rosrun tf view_frames

# 查看当前的tf树
$ rosrun rqt_tf_tree rqt_tf_tree

# 查看两个frame之间的变换关系
$ rosrun tf tf_echo [reference_frame][target_frame]

6.5 urdf

urdf 是指 Unified Robot Description Format 统一机器人描述格式。

 

7 SLAM(Simutaneous Localization And Mapping 同步定位和制图)

7.1 SLAM 与 Map

std_msgs/Header     header
    uint32    seq            # 序号    
    time    stamp            # 时间戳
    string    frame_id       # map
nav_msgs/MapMetaData     info        # 存储地图相关信息
    time    map_load_time            # 地图加载时间
    float32    resolution            # 地图分辨率(m/pixd)(每个像素点实际是多少米,通常选择0.05或者0.02)
    uint32    width                  # 单位 pixd
    uint32    height
    geometry_msgs/Pose     origin(初始化时地图相对于frame:map的位置与朝向)
        geometry_msgs/Point     position
            float64 x
            float64 y
            float64 z
        geometry_msgs/Quaternion     orientation
            float64 x
            float64 y
            float64 z
            float64 w
int8[]    data               # cost,即机器人走到这一个需要消耗的成本。
                             # 数组长度:width * height

7.2 Gmapping SLAM包

7.2.1 Gmapping Topic

Odom:encoder(轮子上的编码器,来测轮子的转速),visual(摄像头),imu

输入的Topic: 1. /tf 和 /tf_static。必须包含odom到base之间的转换关系,即里程计到机器人地盘之间的关系。

                     2. /scan。激光雷达

输出的Topic: 1.  /tf。map(frame 坐标系)到Odom之间的转换关系。即将map与底盘base连通

                     2. /map_metadata。将地图相关信息单独作为一个topic发布出去

                     3. /map。是一个Topic,也是一个图片。将每一次建图的结果发布到这个topic上,以此达到更新地图的目的。

                     4. /slam_gmapping/entropy。浮点型,建图精度。

7.2.2 Gmapping Service

Service: /dynamic_map

Type: nav_msgs/GetMap

nav_msgs/GetMap.srv

#Get the map as a nav_msgs/OccupancyGrid
---
nav_msgs/OccupancyGrid map

7.3 Karto SLAM包

8 Navigation

8.1 Navigation Stack

https://wiki.ros.org/navigation

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值