ROS学习笔记(一)

#打算从今天开始持续发一些自己的学习笔记

ROS开发环境配置

ROS和安卓

ROS:一般运行在电脑or树莓派上,通过USB转串口与单片机连接 -> 在ROS上运行能够进行串口通信的node与单片机进行数据交换

node:节点,可以类比于安卓下的APP

ROS类比于安卓,有了不同的APP(node),就可以运行不同的功能

比如

  • 运行了GMapping的机器人:扫描建图机器人

  • 运行了Move_base的机器人:自主导航机器人

类似于安卓,通过在应用商店下载不同的APP,可以新增很多功能;ROS可以通过在APT源和Github下载不同的软件包增加新的功能。同时,给ROS开发功能,也同安卓编写APP一样,不需要对整个程序进行重写,只需要按照接口规范,编写相应的功能节点。

参考

https://www.bilibili.com/video/BV1BP4y1o7pw/?spm_id_from=333.337.search-card.all.click&vd_source=0ce5764b2d43320613b1dd7bc3ee3031

Ubuntu

  • Source xxx.sh 启动.sh脚本

  • Edit 终端程序的初始化脚本

(在.bashrc最末尾加上指令,则该指令会在终端一打开时就随着初始化执行)

  • 下载

sudo apt install xxx

sudo管理员权限运行;apt软件源

ROS安装

apt源:index.ros.org

ROS的官方应用商店,可以查看各种软件包的功能、name、源码、最新版发行日期等等

软件包安装

从APT商店安装应用

在新窗口启动roscore

启动mrpt_sensors(第一个是包的名称,第二个是节点的名称)

程序界面

使用ROS的仿真程序对以上机器人控制程序进行测试

修改速度发送的主体名称

Github

除了可以在APT应用商店进行ROS软件的下载,还可以利用Github进行源代码的下载。但是Github下载之后的软件包需要经过编译,因此需要建立一定的工作空间,即目录结构(编译器会按照这个目录结构去检索源代码,从而完成编译)

克隆编译

为Github项目创建目录结构,以及克隆源代码

Scripts:通常用于放置脚本文件、Python程序(用来完成一些使用频率不高的操作,比如安装依赖包、为实体机器人映射端口,这一类操作一般只进行一次)

本项目Scripts中放置了三个安装依赖包的脚本文件(.sh文件),分别针对kinetic、melodic、noetic三个版本

运行noetic版本的脚本安装noetoc版本依赖包

回到入口目录,对src目录里的所有源代码工程进行编译(该编译命令需要在根目录下运行)

运行包中的功能

首先使用source指令,载入工作空间的环境设置,使得运行指令能够找到软件包

然后可以使用roslaunch运行编译好的ros程序(同样要在根目录下进行)

此时出现的三维界面即仿真环境Gazebo

左侧的”铁架子”即一个仿真的机器人模型

可以用刚刚装的速度软件驱动它运动

将前面刚刚加的对象(选中部分)删掉,就可以控制界面中的铁架子机器人运动

之后自己编写的代码也可以放在catkin_ws工作空间中

可以把设置工作空间环境参数的source指令放到终端的初始化脚本中(~/.bashrc)

Linux环境vscode配置

运行安装包安装vscode(最后可以直接用TAB键补全)

启动

File -> add folder to workspace添加工作空间目录,将catkin_ws下的src目录添加进去(将src作为根目录,因为之后Github克隆下来的功能代码及其编辑都在src内)

在vscode中安装ros插件。可以对vscode的设置功能进行扩充,添加ros专用的菜单项

安装bracket插件,使得不同层级的大括号能够成对地显示不同的颜色

vscode的快捷键修改

  • control+shift+B,编译

多窗口终端Terminator

安装

control+alt+t启动terminator

control+shift+o分窗口(上下)

control+shift+e分窗口(左右)(这里分不出来是该快捷键被占用了,可以搜索一下怎么修改该快捷键然后就可以使用该功能了)

节点创建

Initial

#include <ros/ros.h>

int main(int argc, char *argv[])//这里自动补全打main第二个参数中需要删掉const(以符合ros::int函数中参数打要求)
{
    ros::init(argc, argv, "ultrasonic_node");//初始化节点,与ros系统产生联系,从而能够调用ros核心打各项功能(ros类下的init函数)
    printf("nice day\n");
    while(ros::ok())//如果这里打while条件改成true,则终端不会响应任何外部信息,即control+c也无法退出循环,这里可以使用这个ok函数,防止关不掉终端
    {
        printf("nice day\n");
    }
    
    /* code */
    return 0;
}

发布者节点

#include <ros/ros.h>
#include <std_msgs/String.h>//下面使用std_msgs定义的string类型前面需要include这个包

int main(int argc, char *argv[])//这里自动补全打main第二个参数中需要删掉const(以符合ros::int函数中参数打要求)
{
    ros::init(argc, argv, "ultrasonic_node");//初始化节点,与ros系统产生联系,从而能够调用ros核心打各项功能(ros类下的init函数)
    printf("nice day\n");

    ros::NodeHandle nh;//创建一个nodehandle对象,帮忙做事(相当于publisher可以使用的一个工具)
    ros::Publisher pub = nh.advertise<std_msgs::String>("How_are_you", 10);//创建一个Publisher对象。Publisher打数据来源:nodehandle对象打advertise函数,借用std_msg类下的String类型
    //上一行代码括号内的参数:话题名称,接受排队的包数

    ros::Rate loop_rate(10);//定义用于控制发布消息频率的对象


    while(ros::ok())//如果这里打while条件改成true,则终端不会响应任何外部信息,即control+c也无法退出循环,这里可以使用这个ok函数,防止关不掉终端
    {
        printf("nice day\n");
        std_msgs::String msg;//定义string类型的变量msg
        msg.data = "sunny day";//设置msg中的内容
        pub.publish(msg);//在配置好打pub中将msg进行发布

        loop_rate.sleep();//调用上面定义好参数打loop_rate对象,并调用其sleep函数使得循环频率与设定值一致
    }
    
    /* code */
    return 0;
}

使用python实现发布者节点

使用python开发发布者节点不需要编译

python节点不再存放在src目录下,而是在包目录下新建一个scripts文件夹用于存放python文件

使用python创建发布者节点,实际上步骤和c++一致,只是管理者由NodeHandle变为了rospy,步骤如下:

  • 召唤rospy

  • 向rospy申请初始化节点

  • 告诉rospy需要发布的话题名称,并向他索要能够发送消息包的发布对象pub

  • 开启一个while循环,不停地用pub对象发布消息包

    #!/usr/bin/env python3
    #coding=utf-8
    
    import rospy #引入管理者rospy
    from std_msgs.msg import String #从std_msgs.msg引入要发布的消息类型
    
    if __name__ == '__main__': #引入python的主函数
        rospy.init_node("ultrasonic_node") #使用init_node向rospy申请初始化节点
        rospy.logwarn("I'm here") #初始化后调用logwarn函数输出登场台词,表明节点初始化完成
    
        pub = rospy.Publisher("always", String, queue_size=10) #告诉rospy要发布的话题名称,并索要发布对象,给到pub。queue_size:发布端的消息包缓冲长度
    
        rate = rospy.Rate(10) #定义发送频率的控制对象(也是向rospy索要的)
    
        while not rospy.is_shutdown(): #while循环的条件:ros节点没有被关闭
            rospy.loginfo("Coming!") #告知下一步动作
            msg = String()
            msg.data = "with you"
            pub.publish(msg) #将msg的消息pub出去
            rate.sleep()

另外,ubuntu中新建的文件,出于安全考虑,通常不带有执行权限,因此要给新建的.py文件赋予执行权限

在.py文件所在的文件夹启动命令行,输入

Chmod +x ultrasonic_node.py

即change mode(改变文件权限模式),x即execute执行

运行py节点和c++操作方式相同

这里注意几个点

  • 要先在catkin_ws目录下运行catkin_make进行编译才能运行.py(仅在第一次需要编译,之后再运行保存过的文件或者新创建的py文件都不需要再进行编译)

  • 如果通过复制方法建立了第二个py节点,则实际上连同执行权限一起复制过去了,不需要再进行添加

  • 代码第一行:#指定解释器为python3

  • 代码第二行:#指定运行环境的编码为utf-8

  • 代码的第一行、第二行之后不能使用#添加注释,不然会报错

订阅者节点

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

void ultra_callback(std_msgs::String msg)//在main函数前定义一个回调函数,传入的参数msg即最新获取到的消息包内容
{
    //printf(msg.data.c_str());//调用data的c_str函数,从string类型转换成字符数组从而能够由printf展示出来
    //printf("\n");
    ROS_INFO(msg.data.c_str());
}
void mcu_callback(std_msgs::String msg)//定义第二个回调函数用于接受MCU_node消息时的回调
{
    ROS_WARN(msg.data.c_str());
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "sub_node");

    ros::NodeHandle nh;//同样定义一个nodehandle对象
    ros:: Subscriber sub = nh.subscribe("How_are_you", 10, ultra_callback);//subscriber函数的第二个参数也是允许排队的消息包个数
    ros:: Subscriber sub2 = nh.subscribe("MCU_here", 10, mcu_callback);

    while(ros::ok())
    {
        ros::spinOnce();//查看是否有新的消息包到来

    }
    /* code */
    return 0;
}

利用ratgraph命令查看话题订阅者关联关系

订阅者节点的python实现

同样在atr_pkg中新建scripts文件夹用于存放py文件,然后在其中新建sub_node.py

#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String

def imu_callback(msg):
    rospy.loginfo(msg.data)

def ultra_callback(msg):
    rospy.loginfo(msg.data)

if __name__ == '__main__':
    rospy.init_node("sub_node")

    sub = rospy.Subscriber("always", String, imu_callback, queue_size=10)
    sub_2 = rospy.Subscriber("hello", String, ultra_callback, queue_size=10)

    rospy.spin()

使用.launch文件启动python节点

同样在launch文件夹下新建.launch文件

<launch>

    <node pkg="ssr_pkg" type="ultrasonic_node.py" name="ultrasonic_node"/>
    <node pkg="ssr_pkg" type="imu_node.py" name="imu_node"/>
    <node pkg="atr_pkg" type="sub_node.py" name="sub_node" launch-prefix="gnome-terminal -e"/>

</launch>

#这里第三行<node>标签的最后一个参数是新开了一个终端窗口用于给订阅者节点进行刷屏

注意这里节点处要加上.py后缀(不是跟c++node一样需要编译生成可执行文件,而是直接运行py脚本)

而后面的name不加.py

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值