机器人原理与实践ROS学习笔记

Posted 与光同程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器人原理与实践ROS学习笔记相关的知识,希望对你有一定的参考价值。

常用命令

启动ROS: roscore

获取节点信息:
rosnode list 列出所有正在运行的节点
rosnode info xxx 列出节点信息
rosnode ping
rosnode machine
rosnode kill

运行节点
rosrun XXX

创建ROS功能包:roscreate-pkg XXX std_msgs rospy roscpp

编译功能包 :rosmake xxx

查找路径:rospack find xxx

查看依赖关系 :rospack depends XXX

查看功能包内容:rosls

更改包路径 :roscd

显示观察话题:rostopic list
rostopic echo xxx -n x

放码过来

Python 编程

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32

rospy.init_node('topic_publisher')
pub=rospy.Publisher('PS2',Int32)
rate=rospy.Rate(2)
count=0
while not rospy.is_shutdown():
    pub.publish(count)
    count+=1
    rate.sleep()

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32

def callback(msg):
    print(msg.data)

rospy.init_node('subsribe')
sub=rospy.Subscriber('PS2',Int32,callback)
rospy.spin()

C++编程

ROS的Hello World

消息发布者

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
int main(int argc,char ** argv)
{
    //启动节点并设置名称
    ros::init(argc,argv,"ps2");
    //节点句柄
    ros::NodeHandle n;
    ROS_INFO_STREAM("PS2 NODE INIT");
    //设置节点为发布者,并将发布的主题类型告知节点管理器
    //参数1:消息名称
    //参数2:缓冲区大小
    ros::Publisher pub=n.advertise<std_msgs::String>("PS2",1000);
    //一秒发送10次
    ros::Rate loop_rate(10);
    while(ros::ok()){
        std_msgs::String msg;
        std::stringstream ss;
        ss<<"I am PS node";
        msg.data=ss.str();
        //发布消息
        pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

消息订阅者

#include <ros/ros.h>
#include <std_msgs/String.h>

void callBack(const std_msgs::String::ConstPtr& msg)
{
    ROS_INFO("GetPS2 I head that: [%s]",msg->data.c_str());
}

int main(int argc ,char** argv)
{
    ros::init(argc,argv,"GetPS2");
    ros::NodeHandle n;
    ros::Subscriber sub=n.subscribe("PS2",1000,callBack);
    ros::spin();
    return 0;
}


就像上面说的,ros::spin() 在调用后不会再返回,也就是你的主程序到这儿就不往下执行了,而 ros::spinOnce() 后者在调用后还可以继续执行之后的程序。
其实看函数名也能理解个差不多,一个是一直调用;另一个是只调用一次,如果还想再调用,就需要加上循环了。
这里一定要记住,ros::spin()函数一般不会出现在循环中,因为程序执行到spin()后就不调用其他语句了,也就是说该循环没有任何意义,还有就是spin()函数后面一定不能有其他语句(return 0 除外),有也是白搭,不会执行的。ros::spinOnce()的用法相对来说很灵活,但往往需要考虑调用消息的时机,调用频率,以及消息池的大小,这些都要根据现实情况协调好,不然会造成数据丢包或者延迟的错误。

这里需要特别强调一下,如果大兄弟你的程序写了相关的消息订阅函数,那千万千万千万不要忘了在相应位置加上ros::spin()或者ros::spinOnce()函数,不然你是永远都得不到另一边发出的数据或消息的,博主血的教训,万望紧记。。。

创建msg与srv文件

msg与src勇于定义传输数据的类型与数据值的文件。ROS会根据这些文件内容自动的为我们创建所需的代码。
使用ROS创建自定义消息

在功能包文件夹下创建msg文件夹,然后在msg文件夹中创建.msg文件 输入
int32 A
int32 B
int32 C

编辑CMakeList.txt

显示消息情况
rosmsg show arm/PS2

显示服务情况
rossrv show arm/PS_2

使用srv与msg

#include <ros/ros.h>
#include "arm/PS2.h"
#include <sstream>
int main(int argc,char** argv)
{
    ros::init(argc,argv,"sendMsg");
    ros::NodeHandle n;
    ros::Publisher pub=n.advertise<arm::PS2>("PS2",1000);
    ros::Rate loop_rate(10);
    while(ros::ok())
    {
        arm::PS2 msg;
        msg.A=1;
        msg.B=1;
        msg.C=1;
        pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

#include <ros/ros.h>
#include "arm/PS2.h"

void callBack(const arm::PS2::ConstPtr& msg )
{
    ROS_INFO("I Heard :[%d][%d][%d]",msg->A,msg->B,msg->C);
}

int main(int argc ,char** argv)
{
    ros::init(argc,argv,"getMsg");
    ros::NodeHandle n;
    ros::Subscriber sub =n.subscribe("PS2",1,callBack);
    ros::spin();
    return 0;
}

以上是关于机器人原理与实践ROS学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

《ROS理论与实践》学习笔记机器人语音交互

《ROS理论与实践》学习笔记机器人自主导航

《ROS理论与实践》学习笔记机器人自主导航

《ROS理论与实践》学习笔记机器人SLAM建图

《ROS理论与实践》学习笔记机器人SLAM建图

《ROS理论与实践》学习笔记构建机器人仿真平台