精华内容
下载资源
问答
  • ros入门
    2022-07-19 09:18:37


    老师在B站的原视频链接: 【古月居】古月·ROS入门21讲 | 一学就会的ROS机器人入门教程

    1.VMware+Ubuntu18.04+ROS安装

    环境是令人头疼的问题,尤其Ubuntu+ROS,对新手来说是难度叠buff了,这篇大佬的博客总结很好,很适合新手入门
    链接: VMware+Ubuntu18.04+ROS安装总结
    万事开头难,搭环境可能会遇到各种各样的问题,但也只需要一次,所以按照博客步骤一步一步来,有问题在评论区讨论哟~

    2.Linux命令

    ros的开发环境主要是在Linux系统,Linux系统现在图像界面已经很方便,但是也要习惯采用终端命令行的操作方式。Linux命令有很多,但常用的就那几个。我经常记不住,所以等要用再去搜索也不迟,在使用中慢慢掌握。可以直接在CSDN中搜索Linux命令大全,有很多总结的很好的文章。这里只列出常用的:

    命令英文解释用法
    lslist查看当前文件夹下所包含内容列表
    pwdprint work directory查看当前所在文件夹
    cd [文件路径]changge directory切换文件夹,中间要加空格
    touch [文件名]touch如果文件不存在,新建文件
    mkdir [文件路径]make directory创建文件夹
    rm [文件路径]remove删除指定文件
    cpcopy复制
    mvmove剪切
    clearclear清屏
    sudo获得root权限
    • 打开命令行终端快捷键:Ctrl+Alt+T
    • 常使用tab键补全命令
    • 安装g++编译器: sudo apt-get install g++
    • 安装python解析器:sudo apt-get install python

    3.ROS是什么

    ROS是为了提高机器人研发中的软件复用率
    ROS=通信机制+开发工具+应用功能+生态系统

    ROS中的通信机制

    松耦合分布式通信
    在这里插入图片描述

    ROS的开发工具

    命令行&编译器 : 通过终端输入一系列命令快速调试你的机器人,看到数据传输的内容

    可视化工具
    TF坐标变换:完成坐标变化的管理工具
    QT工具箱:一系列基于QT的可视化工具箱
    Rviz:机器人可视化工具
    Gazebo:仿真工具

    ROS的应用功能

    Navigation:导航
    SLAM:同步定位与地图绘制
    Movelt!:机械臂运动规划

    ROS中的生态系统

    1.发行版(Distribution):ROS发行版本包括一系列版本号、可以直接安装的功能包
    2.软件源(Repository):ROS依赖于共享网络上的开源代码,不同的组织机构可以开发或者共享自己的机器人软件
    3.ROS wiki:记录ROS信息文档的主要论坛。记录可能比较零散,老师建议直接在Google搜索需要的资源,可能可以直接搜到相关的主页。链接: ROS wiki
    4.邮件列表(Mailing list):交流ROS更新的主要渠道,同时也可以交流ROS开发的各种疑问
    5.ROS Answers:咨询ROS相关问题的网站 链接: ROS Answers
    6.博客(blog):发布ROS社区中的新闻、图片、视频(http://www.ros.org/news)
    但是这个博客好像在2020年已经停用,其中提到了的ROS Discourse链接: ROS Discourse
    在这里插入图片描述
    ROS代码与功能包的组织形式类似于包含关系,不同的功能包完成各自的功能
    在这里插入图片描述

    更多相关内容
  • 古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门21讲古月居ros入门...
  • 古月居 · ROS入门21讲-含视频、课件与源码
  • 第六课 ROS是什么 ROS=通信机制+开发工具+应用功能+生态系统 通信机制 松耦合分布式通信 开发工具 命令行&编译器 TF坐标变换 QT工具箱 Rviz Gazebo 应用功能 SLAM Navigation Movelt! 关注接口,输入输出就行,其次...
  • 第九课 创建工作空间课功能包 工作空间 src:代码空间。xml文件 build:编译空间,基本不用关心 devel:开发空间, install:安装空间 创建工作空间 mkdir -p ~/catkin_ws/src ...echo $ROS_PACKAGE_PAT
  • ROS入门与实战

    2018-09-22 16:43:48
    ROS入门与实战》深入浅出地介绍了ROS的特点、基本使用方法以及实际应用,内容涉及移动机器人自主导航、视觉识别、机械臂运动规划等,可帮助不同领域的机器人开发人员了解并熟练使用ROS。  《ROS入门与实战》内容...
  • ROS By Example(ROS入门实例)代码详细解读
  • ROS入门21讲课件&源码.zip
  • ros入门实例

    2019-03-30 14:40:16
    ros入门实例
  • ROS入门21讲》课件&源码.zip
  • ROS是面向机器人的开源的元操作系统,本书主要机器人操作系统的入门级介绍
  • ROS入门学习指南.docx

    2019-06-19 10:07:17
    ROS入门学习指南.docx
  • 本资源免费下载,希望对您有帮助,一起加油吧
  • ROS 入门实例 中文版

    2017-12-22 14:48:31
    ROS 入门实例,Do it by yourself, 教程清晰,步骤详细
  • ROS入门基础(1).pdf

    2020-04-25 15:14:35
    主要包含以下内容 一、ROS介绍 1.ROS发展与现状 2.ROS系统安装 3.ROS简单介绍 二、 ROS基础 1.常用命令行 2.通信机制 3.关键组件 三、 ROS编程实例 例1.简单话题 例2.简单服务 例3.简单调试
  • 本书是一个ROS机器人编程指南,它基于我们从TurtleBot3,OpenCR和OpenManipulator等ROS项目积累的经验。我们试图使这个全面的指南涵盖ROS的初学者所需的所有方面。包括嵌入式系统,移动机器人和用ROS编程的机器人...
  • 古月居ROS入门课件&代码
  • ROS入门级教程

    2022-07-21 15:37:47
    本文讲述ROS入门级教程,介绍ROS的安装,ROS程序的主体架构、核心概念、已有程序的编译与使用、常用的调试工具和一些指令。

    目录

    前言

    一、ROS简介与安装

    二、ROS文件系统

    三、ROS核心概念

    1.节点

    2.话题

    3.通讯机制

    四、ROS的编译与简单使用

    五、调试工具

    1.Rviz和Gazebo

    2.rqt工具

     3.rosbag

    六、常用指令

    1.常用的文件系统命令实践

    2.节点(Nodes)相关的命令

    3.Topic 相关的命令

    4.Message 相关的命令

    5.Service 相关的命令

    6.参数服务器相关的命令

    总结


    前言

            本文讲述ROS的入门级教程,介绍ROS的安装,ROS程序的主体架构、核心概念、已有程序的编译与使用、常用的调试工具和一些指令。


    提示:系统配置:ubuntu18.04 + ROS Melodic

    一、ROS简介与安装

            Robot Operating System (ROS) 机器人操作系统的官方定义:
            ROS 是面向机器人的开源的元操作系统(meta-operating system),它能够提供与传统操作系统类似的诸多功能,如硬件抽象、底层设备控制、常用功能实现、进程间消息传递和程序包管理等。此外,它还提供相关工具和库,用于获取、编辑、编译代码,以及在多台计算机上运行程序,实现分布式计算。

            第一代ROS仅支持安装于ubuntu系统,第二代ROS2也支持windows等系统。ROS的版本受制于系统版本,如ubuntu18.04仅支持ROS Melodic,ubuntu20.04仅支持ROS Noetic。以下是具体安装步骤:

            1.安装ubuntu系统,具体步骤略,以下以ubuntu18.04为例。

            2.安装ROS(Melodic)

                    2.1安装ROS源文件,打开终端输入:

    sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

    #或者选用国内的软件源,提高下载速度

    sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list'

                    2.2设置公钥,继续在终端输入:

    sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

                    2.3更新最新可用软件包列表,继续在终端输入:

    sudo apt update

                    2.4安装ROS,继续在终端输入,建议安装完整版:

    sudo apt install ros-melodic-desktop-full

                    2.5初始化 rosdep,继续在终端输入,这里使用不知名高手的方法有效规避墙:

    sudo rosdepc init

    rosdepc update

                    2.6设置环境,继续在终端输入:

    echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc

    source ~/.bashrc

            3.测试,运行小海龟和rviz

            3.1.1打开终端输入

    roscore

            3.1.2再打开一个终端输入

    rosrun turtlesim turtlesim_node

            3.1.3出现了一个小海龟,再打开一个终端输入

    rosrun turtlesim turtle_teleop_key

            让光标在第三个打开的终端中闪烁,此时就可以通过方向键控制小乌龟移动了

            3.2.1运行rviz

            打开终端输入

    rosocre

            3.2.2再打开一个终端输入

    rosrun rviz rviz (或者rviz)

             出现这个画面说明rviz等组件安装成功

             4.退出ROS程序(进程)

    将光标放入对应终端内,按Ctrl+C,适用于几乎所有ROS程序

    二、ROS文件系统

            ROS 文件系统的主要目的是使创建的工程集中化,同时提供足够的灵活性使依赖关系分散化。

     

            Catkin 是 ROS定制的编译构建系统,对CMake的扩展。总之,Catkin就是用来编译ROS程序的。Catkin工作空间,就是一个文件夹。,组织和管理功能包的文件夹,以catkin工具编译。对它的创建,克隆修改之类的,都在这个文件夹中完成。

            Build:里面放的是c_make和catkin的缓存信息和中间文件。

            Devel:存放目标文件,比如:头文件,动态链接库,静态链接库,可执行文件。

            Src:是我们真正写代码的地方。我们只需要专注于src就可以了。

            Package 是catkin编译的基本单元。Catkin编译的对象就是一个一个的package。Catkin在编译的时候是在src目录下,以递归形式查找每一个package,所以也可以将多个package放在一个folder下面。

    三、ROS核心概念

    1.节点

            节点(Node)是ROS程序的运行实例(可执行文件的实例化),也可以理解为几乎相互独立的程序,不同节点实现不同功能,节点通过ROS节点管理器(Master)注册信息,并且多个节点可同时运行。(另一角度定义,ROS 程序的运行实例,即一个进程,称为节点。)

    2.话题

            话题(Topic)是节点之间通讯的桥梁,节点将消息发布到话题,同时也可以订阅话题以接收消息。

    3.通讯机制

            ROS通讯采用分布式网络结构,使用基于TCP(俗称3次握手)的通信方式,实现模块间点对点的连接。其通讯方式有以下几种。

            3.1基于话题(Topic)的通信

            

            ①Talker(节点1)向Master(节点管理器)注册发布者的信息,包含发布消息的话题名(此处为"bar",地址为"1234"),Master会将其储存到注册列表,等待接受此话题的Listener(节点2)。

            ②Listener向Master注册接收者的信息,包含订阅的话题名"bar"。

            ③Master根据Listener订阅的话题在注册列表寻找与之匹配的话题。如果没有找到匹配的发布者,则等待发布者的加入,如果找到可以与之匹配的发布者信息,则向Listener发送Talker的地址信息"1234"。

            ④⑤⑥Listener接收到Talker的地址信息,就尝试向Talker发送连接许可,当Talker与Listener互相确认信息后就建立连接(3次握手)。

            ⑦等连接成功后,Talker才向Listener发送消息(地址为"2345")。可以发现,话题在两节点通讯之间用于相互验证身份,起到桥梁作用。

            需要注意的是,这两个节点可以以任意顺序开始、结束,不会导致任何错误,他们是相互独立的。

            3.2基于服务(Service)的通信

     

            服务调用(service calls)是ROS另一种通信方法。它与话题通信的区别是:服务允许Client(节点1:客户端)发送请求(request)到Server(节点2:服务器) 并获得一个响应(response),服务调用是双向的,且实现的是一对一的通信;对于话题,消息发布的节点不知道是否有其他节点订阅了这个消息,而订阅的节点也不知道是否有其他节点会发布这个消息,且同一个话题可以有很多个发布者和订阅者。

            服务的描述定义了ROS中需求和响应的数据结构,同消息类型一样,服务数据类型也是由一系列域构成的。唯一的区别就在于服务数据类型分为两部分,分别表示请求和响应。

            3.3基于参数(Parameter)的通信

            通过使用参数服务器(parameter server)来维护变量集的值,包括整数、浮点数、字符串以及其他数据类型。参数服务器允许节点主动查询所需参数的值它们适用于配置那些不会随时间频繁变更的信息。

    四、ROS的编译与简单使用

    (这里只讲述如何使用别人开发的ROS功能包,暂不讲述如何自己开发)

    1.创建一个workspace(工作空间)

    打开终端依次执行:

    #在/home/你的用户名目录/目录下,新建一个文件夹

    mkdir -p ~/catkin_ws/src

    #进入到 ~/catkin_ws/src目录下

    cd ~/catkin_ws/src

    #初始化workspace,执行完该命令后,src目录下会多出一个 CMakeLists.txt 文件。

    catkin_init_workspace

    2.编译package,生成可执行文件

    #返回到上层目录

    cd ~/catkin_ws/

    #编译,执行完该命令后,发现工作空间catkin_ws中有三个目录: build devel src,其中,src是我们创建工作空间时创建的目录,另外两个是执行完 catkin_make 后生成的。

    catkin_make

    3.运行ROS节点

    #将对应的工作空间的路径加入环境变量ROS_PACKAGE_PATH中。

    source devel/setup.bash

    #运行package功能包的node节点

    rosrun package_name node_name

    五、调试工具

    1.Rviz和Gazebo

    Rviz是一款3D可视化工具,强调把已有的数据可视化显示。

    Gazebo是3D物理仿真平台,强调的是创建一个虚拟的仿真环境。

     Rviz需要已有的数据,而Gazebo可以创造数据。

    我们可以在Gazebo中创建一个机器人世界,不仅可以仿真机器人的运动功能,还可以仿真机器人的传感器数据,而这些数据就可以放到Rviz中显示,所以使用gazebo的时候,经常也会和rviz配合使用。

    2.rqt工具

    ①rqt_graph:查看节点之间的发布-订阅关系。

     ②rqt_plot:实时显示一个发布到某个话题上的数据变化图形。

     3.rosbag

            包文件由 ROS 生成,可用于保存话题(Topic)和服务(Service)等传输的信息,采用 *.bag 文件格式。通常用于实验数据的记录和算法调试。

    ①录制

    #如果要记录所有的topic,则可以直接使用-a来记录

    rosbag record -a

    #如果仅记录某些感兴趣的topic的话,这可以使用下面这个命令样式来进行记录

    rosbag record <topic_name> <topic_name>....

    #如果要指定录制文件名字的话,则使用-O/-o参数

    rosbag record -O bagname.bag <topic_name> <topic_name>... #为文件命名
    rosbag record -o bagname <topic_name> <topic_name>... #为文件名字做前缀

    #其他录制命令如下

    rosbag record --duration=30 /topic_name #持续30s录制,还可以指定m,h,和--split类似
    rosbag record --split --size=1024 /topic_name1 #空间达到1024M后分文件存储
    rosbag record --split --duration=30 /topic_name1 #持续时间到30s后分文件存储
    rosbag record --split --duration=5m /topic_name1 #持续时间到5m后分文件存储
    rosbag record --split --duration=2h /topic_name1#持续时间到2h后分文件存储
    rosbag record -l 1000 /topic_name1  # 录制该主题1000个消息限制

     ②查看

    当录制好bag以后,可以利用info参数来查看bag的相关信息

    rosbag info filename.bag

    ③播放

    #当录制好bag以后,可以利用play参数让bag播放,回放bag中的topic

    rosbag play <bagfile>

    #如果想改变消息的发布速率,可以用下面的命令,-r 后面的数字对应播放速率

    rosbag play -r 2 <bagfile>

    #利用参数-l则可实验循环播放

    rosbag play -l <bagfile>

    #如果只播放感兴趣的 topic ,则用命令

    rosbag play bag_name.bag --topics /topic_name1 /topic_name2

    #开始播放立刻暂停,按空格继续

    rosbag play --pause bag_name.bag

    #指定播放起始点

    rosbag play bag_name.bag -s 5 #从5s的地方开始播放

    #指定播放时长

    rosbag play bag_name.bag -u 250 #播放250s信息

    #发布时钟,默认/clock话题是没有消息的

    rosbag play --clock bag_name.bag #默认/clock的话题频率100hz
    rosbag play --clock --hz 200 bag_name.bag #指定/clock的时钟为200hz

    ④其他

    #rosbag 重新索引是一个命令行工具,用于修复破损的袋文件如果某个包由于任何原因没有清洁地关闭,则索引信息可能已损坏。使用此工具重新读取消息数据并重新生成索引。

    rosbag reindex old.bag

    #重新录制rostopic filter

    #过滤单个topic

    #生成的tf.bag仅包含/tf这一个topic

    rosbag filter input.bag only-tf.bag "topic == '/tf'"   

    #生成的output.bag包含‘/velodyne_point_cloud、/visensor/imu、/visensor/left/image_raw‘这三个topic

    rosbag filter input.bag output.bag "topic == '/velodyne_point_cloud' or topic =='/visensor/imu' or topic == '/visensor/left/image_raw'"  
     

    #根据时间过滤:

    rosbag filter input.bag output.bag "t.to_sec() <= 1284703931.86"

    六、常用指令

    1.常用的文件系统命令实践

    rospack find turtlesim
    rosstack find ros_comm
    rosls turtlesim
    roscd turtlesim
    pwd                            # 显示当前所在目录
    cd | cd ~ | cd - | cd ..    # 目录跳转
    ls | ll            # 列出目录和文件
    ps -ef            # 以完整格式显示所有进程信息
    kill <pid>    # 杀死指定进程
    grep -rn 'publish' ./    # 递归搜索当前目录下包含#"publish"字符串的文件

    2.节点(Nodes)相关的命令

    rosrun <package-name> <executable-name>
    rosnode help
    rosnode list
    rosnode info <node1> <node2> …
    rosnode machine <machine-name>
    rosnode ping <node-name>
    rosnode kill <node-name>
    rosnode cleanup

    3.Topic 相关的命令

    rostopic help
    rostopic list
    rostopic echo <topic-name>        # eg. /turtle1/pose
    rostopic hz <topic-name>            # eg. /turtle1/pose
    rostopic bw <topic-name>        # eg. /turtle1/pose
    rostopic info <topic-name>        # eg. /turtle1/cmd_vel
    rostopic type <topic-name>        # eg. /turtle1/cmd_vel
    rostopic find <message-type-name>

    4.Message 相关的命令

    rosmsg help
    rosmsg list
    rosmsg info <message-type>   # eg. turtlesim/Pose

    # 显示指定软件包中定义的所有消息
    rosmsg package <package-name>

    # 显示定义了消息的所有软件包
    rosmsg packages

    5.Service 相关的命令

    rosservice help
    rosservice list
    rosnode info <node-name>            # eg. /turtlesim
    rosservice node <service-name>    # eg. /clear
    rosservice info <service-name>    # eg. /clear
    rossrv info <service-type-name>
    rosservice call <service-name> [args …]
    eg. rosservice call /clear    # 清除运行轨迹

    6.参数服务器相关的命令

    rosparam help
    rosparam list
    rosparam get <param-name>    # eg. background_b
    rosparam set <param-name> <value>
    rosservice call /clear    #使背景色生效


    总结

    本篇介绍了ROS基本入门操作,只涉及ROS的安装和使用已有的程序,暂未考虑开发。

    展开全文
  • 蓝桥ROS机器人之古月居ROS入门21讲

    千次阅读 2022-03-26 21:51:22
    ROS1入门经典课程,在其官网和B站等都有详细介绍和视频讲解。 古月居校园行 直接在蓝桥云课下载就可以学习和使用啦。 文档部分: 源码等: 将源码复制到demo_ws/src下,并编译后使用: catkin build ...

    ROS1入门经典课程,在其官网和B站等都有详细介绍和视频讲解。


    古月居校园行

     


    直接在蓝桥云课下载就可以学习和使用啦。

    文档部分:

     

    源码等:

    将源码复制到demo_ws/src下,并编译后使用:

    catkin build 


    ros1 kinetic(1) or ros2 ardent(2)?
    1
    shiyanlou:Code/ $ git clone https://gitcode.net/ZhangRelay/ros_book.git
    \u6b63\u514b\u9686\u5230 'ros_book'...
    remote: Enumerating objects: 15, done.
    remote: Counting objects: 100% (15/15), done.
    remote: Compressing objects: 100% (15/15), done.
    remote: Total 15 (delta 3), reused 0 (delta 0), pack-reused 0
    \u5c55\u5f00\u5bf9\u8c61\u4e2d: 100% (15/15), \u5b8c\u6210.
    \u68c0\u67e5\u8fde\u63a5... \u5b8c\u6210\u3002
    shiyanlou:Code/ $ unzip ros_book/ros_21_tutorials-master.zip         [13:45:05]
    Archive:  ros_book/ros_21_tutorials-master.zip
    a5296958c8b73476ebffe12d2aa4c8049e6c177f
       creating: ros_21_tutorials-master/
      inflating: ros_21_tutorials-master/README.md  
       creating: ros_21_tutorials-master/docs/
     extracting: ros_21_tutorials-master/docs/poster.png  
      inflating: ros_21_tutorials-master/docs/poster2.png  
      inflating: ros_21_tutorials-master/docs/schedule.png  
       creating: ros_21_tutorials-master/docs/slides/
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_1.\u8bfe\u7a0b\u4ecb\u7ecd.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_10.\u53d1\u5e03\u8005Publisher\u7684\u7f16\u7a0b\u5b9e\u73b0.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_11.\u8ba2\u9605\u8005Subscriber\u7684\u7f16\u7a0b\u5b9e\u73b0.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_12.\u8bdd\u9898\u6d88\u606f\u7684\u5b9a\u4e49\u4e0e\u4f7f\u7528.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_13.\u5ba2\u6237\u7aefClient\u7684\u7f16\u7a0b\u5b9e\u73b0.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_14.\u670d\u52a1\u7aefServer\u7684\u7f16\u7a0b\u5b9e\u73b0.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_15.\u670d\u52a1\u6570\u636e\u7684\u5b9a\u4e49\u4e0e\u4f7f\u7528.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_16.\u53c2\u6570\u7684\u4f7f\u7528\u4e0e\u7f16\u7a0b\u65b9\u6cd5.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_17.ROS\u4e2d\u7684\u5750\u6807\u7cfb\u7ba1\u7406\u7cfb\u7edf.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_18.tf\u5750\u6807\u7cfb\u5e7f\u64ad\u4e0e\u76d1\u542c\u7684\u7f16\u7a0b\u5b9e\u73b0.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_19.launch\u542f\u52a8\u6587\u4ef6\u7684\u4f7f\u7528\u65b9\u6cd5.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_2.Linux\u7cfb\u7edf\u4ecb\u7ecd\u53ca\u5b89\u88c5.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_20.\u5e38\u7528\u53ef\u89c6\u5316\u5de5\u5177\u7684\u4f7f\u7528.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_21.\u8bfe\u7a0b\u603b\u7ed3\u4e0e\u8fdb\u9636\u653b\u7565.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_3.Linux\u7cfb\u7edf\u57fa\u7840\u64cd\u4f5c.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_4.\u7f16\u7a0b\u6781\u7b80\u57fa\u7840.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_5.\u5b89\u88c5ROS\u7cfb\u7edf.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_6.ROS\u662f\u4ec0\u4e48.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_7.ROS\u7684\u6838\u5fc3\u6982\u5ff5.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_8.ROS\u547d\u4ee4\u884c\u5de5\u5177\u7684\u4f7f\u7528.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_9.\u521b\u5efa\u5de5\u4f5c\u7a7a\u95f4\u4e0e\u529f\u80fd\u5305.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_\u52a01.\u5b66\u5b8c21\u8bb2\uff0c\u8be5\u5b66\u4ec0\u4e48.pdf  
      inflating: ros_21_tutorials-master/docs/slides/\u53e4\u6708 · ROS\u5165\u95e821\u8bb2_\u52a02.ROS\u5728\u673a\u5668\u4eba\u4e2d\u662f\u5982\u4f55\u8fd0\u884c\u7684.pdf  
       creating: ros_21_tutorials-master/learning_launch/
      inflating: ros_21_tutorials-master/learning_launch/CMakeLists.txt  
       creating: ros_21_tutorials-master/learning_launch/config/
      inflating: ros_21_tutorials-master/learning_launch/config/param.yaml  
       creating: ros_21_tutorials-master/learning_launch/launch/
      inflating: ros_21_tutorials-master/learning_launch/launch/simple.launch  
      inflating: ros_21_tutorials-master/learning_launch/launch/start_tf_demo_c++.launch  
      inflating: ros_21_tutorials-master/learning_launch/launch/start_tf_demo_py.launch  
      inflating: ros_21_tutorials-master/learning_launch/launch/turtlesim_parameter_config.launch  
      inflating: ros_21_tutorials-master/learning_launch/launch/turtlesim_remap.launch  
      inflating: ros_21_tutorials-master/learning_launch/package.xml  
       creating: ros_21_tutorials-master/learning_parameter/
      inflating: ros_21_tutorials-master/learning_parameter/CMakeLists.txt  
       creating: ros_21_tutorials-master/learning_parameter/config/
      inflating: ros_21_tutorials-master/learning_parameter/config/turtle_param.yaml  
      inflating: ros_21_tutorials-master/learning_parameter/package.xml  
       creating: ros_21_tutorials-master/learning_parameter/scripts/
      inflating: ros_21_tutorials-master/learning_parameter/scripts/parameter_config.py  
       creating: ros_21_tutorials-master/learning_parameter/src/
      inflating: ros_21_tutorials-master/learning_parameter/src/parameter_config.cpp  
       creating: ros_21_tutorials-master/learning_service/
      inflating: ros_21_tutorials-master/learning_service/CMakeLists.txt  
      inflating: ros_21_tutorials-master/learning_service/package.xml  
       creating: ros_21_tutorials-master/learning_service/scripts/
      inflating: ros_21_tutorials-master/learning_service/scripts/person_client.py  
      inflating: ros_21_tutorials-master/learning_service/scripts/person_server.py  
      inflating: ros_21_tutorials-master/learning_service/scripts/turtle_command_server.py  
      inflating: ros_21_tutorials-master/learning_service/scripts/turtle_spawn.py  
       creating: ros_21_tutorials-master/learning_service/src/
      inflating: ros_21_tutorials-master/learning_service/src/person_client.cpp  
      inflating: ros_21_tutorials-master/learning_service/src/person_server.cpp  
      inflating: ros_21_tutorials-master/learning_service/src/turtle_command_server.cpp  
      inflating: ros_21_tutorials-master/learning_service/src/turtle_spawn.cpp  
       creating: ros_21_tutorials-master/learning_service/srv/
      inflating: ros_21_tutorials-master/learning_service/srv/Person.srv  
       creating: ros_21_tutorials-master/learning_tf/
      inflating: ros_21_tutorials-master/learning_tf/CMakeLists.txt  
       creating: ros_21_tutorials-master/learning_tf/launch/
      inflating: ros_21_tutorials-master/learning_tf/launch/start_tf_demo_c++.launch  
      inflating: ros_21_tutorials-master/learning_tf/launch/start_tf_demo_py.launch  
      inflating: ros_21_tutorials-master/learning_tf/package.xml  
       creating: ros_21_tutorials-master/learning_tf/scripts/
      inflating: ros_21_tutorials-master/learning_tf/scripts/turtle_tf_broadcaster.py  
      inflating: ros_21_tutorials-master/learning_tf/scripts/turtle_tf_listener.py  
       creating: ros_21_tutorials-master/learning_tf/src/
      inflating: ros_21_tutorials-master/learning_tf/src/turtle_tf_broadcaster.cpp  
      inflating: ros_21_tutorials-master/learning_tf/src/turtle_tf_listener.cpp  
       creating: ros_21_tutorials-master/learning_topic/
      inflating: ros_21_tutorials-master/learning_topic/CMakeLists.txt  
       creating: ros_21_tutorials-master/learning_topic/msg/
      inflating: ros_21_tutorials-master/learning_topic/msg/Person.msg  
      inflating: ros_21_tutorials-master/learning_topic/package.xml  
       creating: ros_21_tutorials-master/learning_topic/scripts/
      inflating: ros_21_tutorials-master/learning_topic/scripts/person_publisher.py  
      inflating: ros_21_tutorials-master/learning_topic/scripts/person_subscriber.py  
      inflating: ros_21_tutorials-master/learning_topic/scripts/pose_subscriber.py  
      inflating: ros_21_tutorials-master/learning_topic/scripts/velocity_publisher.py  
       creating: ros_21_tutorials-master/learning_topic/src/
      inflating: ros_21_tutorials-master/learning_topic/src/person_publisher.cpp  
      inflating: ros_21_tutorials-master/learning_topic/src/person_subscriber.cpp  
      inflating: ros_21_tutorials-master/learning_topic/src/pose_subscriber.cpp  
      inflating: ros_21_tutorials-master/learning_topic/src/velocity_publisher.cpp  
       creating: ros_21_tutorials-master/linux/
      inflating: ros_21_tutorials-master/linux/c++_class.cpp  
      inflating: ros_21_tutorials-master/linux/c++_for.cpp  
      inflating: ros_21_tutorials-master/linux/c++_while.cpp  
      inflating: ros_21_tutorials-master/linux/python_class.py  
      inflating: ros_21_tutorials-master/linux/python_for.py  
      inflating: ros_21_tutorials-master/linux/python_while.py  
      inflating: ros_21_tutorials-master/\u300aROS\u5165\u95e821\u8bb2\u300b\u6559\u7a0b\u8865\u5145\u8d44\u6599.pdf  
    shiyanlou:Code/ $ cd demo_ws                                         [13:45:43]
    shiyanlou:demo_ws/ $ catkin build                                    [13:46:49]
    -----------------------------------------------------------------
    Profile:                     default
    Extending:             [env] /opt/ros/kinetic
    Workspace:                   /home/shiyanlou/Code/demo_ws
    -----------------------------------------------------------------
    Build Space:        [exists] /home/shiyanlou/Code/demo_ws/build
    Devel Space:        [exists] /home/shiyanlou/Code/demo_ws/devel
    Install Space:      [unused] /home/shiyanlou/Code/demo_ws/install
    Log Space:         [missing] /home/shiyanlou/Code/demo_ws/logs
    Source Space:       [exists] /home/shiyanlou/Code/demo_ws/src
    DESTDIR:            [unused] None
    -----------------------------------------------------------------
    Devel Space Layout:          linked
    Install Space Layout:        None
    -----------------------------------------------------------------
    Additional CMake Args:       None
    Additional Make Args:        None
    Additional catkin Make Args: None
    Internal Make Job Server:    True
    Cache Job Environments:      False
    -----------------------------------------------------------------
    Buildlisted Packages:        None
    Skiplisted Packages:         None
    -----------------------------------------------------------------
    Workspace configuration appears valid.
    
    NOTE: Forcing CMake to run for each package.
    -----------------------------------------------------------------
    [build] Found '5' packages in 0.0 seconds.                                     
    [build] Updating package table.                                                
    Starting  >>> catkin_tools_prebuild                                            
    Finished  <<< catkin_tools_prebuild                [ 2.3 seconds ]             
    Starting  >>> learning_launch                                                  
    Starting  >>> learning_parameter                                               
    Starting  >>> learning_service                                                 
    Starting  >>> learning_tf                                                      
    Finished  <<< learning_launch                      [ 10.8 seconds ]            
    Starting  >>> learning_topic                                                   
    Finished  <<< learning_parameter                   [ 24.6 seconds ]            
    Finished  <<< learning_tf                          [ 47.4 seconds ]            
    Finished  <<< learning_service                     [ 56.3 seconds ]            
    Finished  <<< learning_topic                       [ 46.4 seconds ]            
    [build] Summary: All 6 packages succeeded!                                     
    [build]   Ignored:   None.                                                     
    [build]   Warnings:  None.                                                     
    [build]   Abandoned: None.                                                     
    [build]   Failed:    None.                                                     
    [build] Runtime: 59.6 seconds total.                                           
    [build] Note: Workspace packages have changed, please re-source setup files to use them.
    Exception ignored in: <bound method BaseEventLoop.__del__ of <_UnixSelectorEventLoop running=False closed=True debug=False>>
    Traceback (most recent call last):
      File "/usr/lib/python3.5/asyncio/base_events.py", line 431, in __del__
      File "/usr/lib/python3.5/asyncio/unix_events.py", line 58, in close
      File "/usr/lib/python3.5/asyncio/unix_events.py", line 139, in remove_signal_handler
      File "/usr/lib/python3.5/signal.py", line 47, in signal
    TypeError: signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object
    shiyanlou:demo_ws/ $ source devel/setup.bash                         [13:47:55]
    devel/setup.bash:.:8: \u6ca1\u6709\u90a3\u4e2a\u6587\u4ef6\u6216\u76ee\u5f55: /home/shiyanlou/Code/demo_ws/setup.sh
    shiyanlou:demo_ws/ $ source devel/setup.zsh                          [13:48:31]
    shiyanlou:demo_ws/ $ roslaunch learning_launch start_tf_demo_c++.launch 
    ... logging to /home/shiyanlou/.ros/log/8ba90254-ad0b-11ec-bf40-0242c0a82a04/roslaunch-5a0e7854a36d-30370.log
    Checking log directory for disk usage. This may take awhile.
    Press Ctrl-C to interrupt
    Done checking log file disk usage. Usage is <1GB.
    
    started roslaunch server http://5a0e7854a36d:36559/
    
    SUMMARY
    ========
    
    PARAMETERS
     * /rosdistro: kinetic
     * /rosversion: 1.12.17
    
    NODES
      /
        listener (learning_tf/turtle_tf_listener)
        sim (turtlesim/turtlesim_node)
        teleop (turtlesim/turtle_teleop_key)
        turtle1_tf_broadcaster (learning_tf/turtle_tf_broadcaster)
        turtle2_tf_broadcaster (learning_tf/turtle_tf_broadcaster)
    
    auto-starting new master
    process[master]: started with pid [30380]
    ROS_MASTER_URI=http://localhost:11311
    
    setting /run_id to 8ba90254-ad0b-11ec-bf40-0242c0a82a04
    process[rosout-1]: started with pid [30393]
    started core service [/rosout]
    process[sim-2]: started with pid [30396]
    process[teleop-3]: started with pid [30407]
    process[turtle1_tf_broadcaster-4]: started with pid [30409]
    process[turtle2_tf_broadcaster-5]: started with pid [30418]
    process[listener-6]: started with pid [30422]
    Reading from keyboard
    ---------------------------
    Use arrow keys to move the turtle.
    
    


    展开全文
  • 此条目包含 MATLAB 和 Simulink Robotics Arena 的“MATLAB 和 ROS 入门”、“Simulink 和 ROS 入门”、“将算法部署到 ROS”和“使用 ROS 设计分布式系统”的文件。 您将找到 MATLAB 和 Simulink 模板,以帮助您...
  • 在上一篇文章中简单了解了ROS话题通信机制,但是它内部的通信过程,很多人都是不知道的,今天我看了 胡春旭的书籍——《ROS机器人开发实践》,又加深了对ROS话题通信的理解,打算接着讲解一下其过程是怎么样的。...
  • ROS入门mooc课程.zip

    2021-12-31 15:47:34
    ros机器人操作系统入门学习资料,包括代码和讲义,欢迎对机器人,slam感兴趣的朋友下载
  • ROS入门的相关知识点总结 以及 记录的坑 ros学习的知识点笔记参照来源主要是古月老师的入门21讲,古月老师的ros入门与实践,mooc中机器人操作系统课程的电子书,以及我对其中相关知识点搜索度娘后的补充。 ros学习...
  • 古月居ROS入门21讲笔记

    万次阅读 多人点赞 2019-07-18 00:05:05
    ROS入门21讲笔记——古月居 1 C++&Python极简基础 1.1 安装编译/解析器 1.2 for循环 1.3 while循环 1.4 面向对象 2. ROS基础 2.1 ROS概念 2.2 创建工作空间与功能包 2.3 发布者Publisher的编程实现 2.4 订阅者...

    1 C++&Python极简基础

    1.1 安装编译/解析器

    sudo apt-get install g++
    sudo apt-get install python
    

    1.2 for循环

    • Python
    for a in range(5,10):
    	if a< 10:
    		print 'a = ',a
    		a+=1
    	else:
    		break
    

    使用Python解析器运行py程序

    python fileName.py
    

    • C++

    使用g++编译*.cpp文件

    g++  fileName.cpp  -o  exeFileName
    

    运行编译后的二进制文件

    ./exeFileName
    

    1.3 while循环

    • C++

    • Python

    a = 5
    while a < 10:
    	print 'a = ' , a
    	a += 1 
    
    

    1.4 面向对象

    • C++
    #include <iostream>
    
    class A
    {
    	public:
    		int i;
    		void test()
    		{
    			std::cout << i <<std::endl;
    		}
    };
    
    int main()
    {
    	A a;
    	a.i = 10;
    	a.test();
    	return 0;
    }
    
    • Python
    class A:
    	i = 10
    	def test(self)
    		print self.i
    a = A()
    a.test()
    

    配置ROS软件源时,更新软件包容易出现下载失败的情况,跟使用的网络有关.
    古月大神总结:使用手机热点可以更新成功.


    2. ROS基础

    2.1 ROS概念

    在这里插入图片描述
    在这里插入图片描述
    查看节点列表:rosnode list
    发布话题消息:rostopic pub -r 10 /话题名
    发布服务请求:rosservice call /服务文件 “变量:val”
    话题记录: rosbag record -a -O fileName
    话题复现: rosbag play fileName

    2.2 创建工作空间与功能包

    在这里插入图片描述
    在这里插入图片描述
    建立install空间:catkin_make install

    在这里插入图片描述

    2.3 发布者Publisher的编程实现

    在这里插入图片描述


    • C++
    /**
     * 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
     */
     
    #include <ros/ros.h>
    #include <geometry_msgs/Twist.h>
    
    int main(int argc, char **argv)
    {
    	// ROS节点初始化
    	ros::init(argc, argv, "velocity_publisher");
    
    	// 创建节点句柄
    	ros::NodeHandle n;
    
    	// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    	ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
    
    	// 设置循环的频率
    	ros::Rate loop_rate(10);
    
    	int count = 0;
    	while (ros::ok())
    	{
    	    // 初始化geometry_msgs::Twist类型的消息
    		geometry_msgs::Twist vel_msg;
    		vel_msg.linear.x = 0.5;
    		vel_msg.angular.z = 0.2;
    
    	    // 发布消息
    		turtle_vel_pub.publish(vel_msg);
    		ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
    				vel_msg.linear.x, vel_msg.angular.z);
    
    	    // 按照循环频率延时
    	    loop_rate.sleep();
    	}
    
    	return 0;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    • Python
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
    
    import rospy
    from geometry_msgs.msg import Twist
    
    def velocity_publisher():
    	# ROS节点初始化
        rospy.init_node('velocity_publisher', anonymous=True)
    
    	# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
        turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
    
    	#设置循环的频率
        rate = rospy.Rate(10) 
    
        while not rospy.is_shutdown():
    		# 初始化geometry_msgs::Twist类型的消息
            vel_msg = Twist()
            vel_msg.linear.x = 0.5
            vel_msg.angular.z = 0.2
    
    		# 发布消息
            turtle_vel_pub.publish(vel_msg)
        	rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
    				vel_msg.linear.x, vel_msg.angular.z)
    
    		# 按照循环频率延时
            rate.sleep()
    
    if __name__ == '__main__':
        try:
            velocity_publisher()
        except rospy.ROSInterruptException:
            pass
    
    
    

    在这里插入图片描述

    2.4 订阅者Subscriber的编程实现

    在这里插入图片描述


    • C++
    /**
     * 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
     */
     
    #include <ros/ros.h>
    #include "turtlesim/Pose.h"
    
    // 接收到订阅的消息后,会进入消息回调函数
    void poseCallback(const turtlesim::Pose::ConstPtr& msg)
    {
        // 将接收到的消息打印出来
        ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
    }
    
    int main(int argc, char **argv)
    {
        // 初始化ROS节点
        ros::init(argc, argv, "pose_subscriber");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
        ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
    
        // 循环等待回调函数
        ros::spin();
    
        return 0;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    • Python
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
    
    import rospy
    from turtlesim.msg import Pose
    
    def poseCallback(msg):
        rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)
    
    def pose_subscriber():
    	# ROS节点初始化
        rospy.init_node('pose_subscriber', anonymous=True)
    
    	# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
        rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
    
    	# 循环等待回调函数
        rospy.spin()
    
    if __name__ == '__main__':
        pose_subscriber()
    
    

    在这里插入图片描述

    2.5 话题消息的定义与使用

    在这里插入图片描述
    在这里插入图片描述


    • C++
    /**
     * 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
     */
     
    #include <ros/ros.h>
    #include "learning_topic/Person.h"
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "person_publisher");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
        ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
    
        // 设置循环的频率
        ros::Rate loop_rate(1);
    
        int count = 0;
        while (ros::ok())
        {
            // 初始化learning_topic::Person类型的消息
        	learning_topic::Person person_msg;
    		person_msg.name = "Tom";
    		person_msg.age  = 18;
    		person_msg.sex  = learning_topic::Person::male;
    
            // 发布消息
    		person_info_pub.publish(person_msg);
    
           	ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", 
    				  person_msg.name.c_str(), person_msg.age, person_msg.sex);
    
            // 按照循环频率延时
            loop_rate.sleep();
        }
    
        return 0;
    }
    
    /**
     * 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
     */
     
    #include <ros/ros.h>
    #include "learning_topic/Person.h"
    
    // 接收到订阅的消息后,会进入消息回调函数
    void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
    {
        // 将接收到的消息打印出来
        ROS_INFO("Subcribe Person Info: name:%s  age:%d  sex:%d", 
    			 msg->name.c_str(), msg->age, msg->sex);
    }
    
    int main(int argc, char **argv)
    {
        // 初始化ROS节点
        ros::init(argc, argv, "person_subscriber");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
        ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
    
        // 循环等待回调函数
        ros::spin();
    
        return 0;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    • Python
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
    
    import rospy
    from learning_topic.msg import Person
    
    def velocity_publisher():
    	# ROS节点初始化
        rospy.init_node('person_publisher', anonymous=True)
    
    	# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
        person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
    
    	#设置循环的频率
        rate = rospy.Rate(10) 
    
        while not rospy.is_shutdown():
    		# 初始化learning_topic::Person类型的消息
        	person_msg = Person()
        	person_msg.name = "Tom";
        	person_msg.age  = 18;
        	person_msg.sex  = Person.male;
    
    		# 发布消息
            person_info_pub.publish(person_msg)
        	rospy.loginfo("Publsh person message[%s, %d, %d]", 
    				person_msg.name, person_msg.age, person_msg.sex)
    
    		# 按照循环频率延时
            rate.sleep()
    
    if __name__ == '__main__':
        try:
            velocity_publisher()
        except rospy.ROSInterruptException:
            pass
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
    
    import rospy
    from learning_topic.msg import Person
    
    def personInfoCallback(msg):
        rospy.loginfo("Subcribe Person Info: name:%s  age:%d  sex:%d", 
    			 msg.name, msg.age, msg.sex)
    
    def person_subscriber():
    	# ROS节点初始化
        rospy.init_node('person_subscriber', anonymous=True)
    
    	# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
        rospy.Subscriber("/person_info", Person, personInfoCallback)
    
    	# 循环等待回调函数
        rospy.spin()
    
    if __name__ == '__main__':
        person_subscriber()
    

    2.6 客户端Client的编程实现

    在这里插入图片描述

    • C++
    /**
     * 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
     */
    
    #include <ros/ros.h>
    #include <turtlesim/Spawn.h>
    
    int main(int argc, char** argv)
    {
        // 初始化ROS节点
    	ros::init(argc, argv, "turtle_spawn");
    
        // 创建节点句柄
    	ros::NodeHandle node;
    
        // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
    	ros::service::waitForService("/spawn");//阻塞型函数
    	ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
    
        // 初始化turtlesim::Spawn的请求数据
    	turtlesim::Spawn srv;
    	srv.request.x = 2.0;
    	srv.request.y = 2.0;
    	srv.request.name = "turtle2";
    
        // 请求服务调用
    	ROS_INFO("Call service to spwan turtle[x:%0.6f, y:%0.6f, name:%s]", 
    			 srv.request.x, srv.request.y, srv.request.name.c_str());
    
    	add_turtle.call(srv); //阻塞型函数
    
    	// 显示服务调用结果
    	ROS_INFO("Spwan turtle successfully [name:%s]", srv.response.name.c_str());
    
    	return 0;
    };
    

    在这里插入图片描述
    在这里插入图片描述

    • Python
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
    
    import sys
    import rospy
    from turtlesim.srv import Spawn
    
    def turtle_spawn():
    	# ROS节点初始化
        rospy.init_node('turtle_spawn')
    
    	# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
        rospy.wait_for_service('/spawn')
        try:
            add_turtle = rospy.ServiceProxy('/spawn', Spawn)
    
    		# 请求服务调用,输入请求数据
            response = add_turtle(2.0, 2.0, 0.0, "turtle2")
            return response.name
        except rospy.ServiceException, e:
            print "Service call failed: %s"%e
    
    if __name__ == "__main__":
    	#服务调用并显示调用结果
        print "Spwan turtle successfully [name:%s]" %(turtle_spawn())
    

    2.7 服务端Server的编程实现

    在这里插入图片描述

    • C++
    /**
     * 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
     */
     
    #include <ros/ros.h>
    #include <geometry_msgs/Twist.h>
    #include <std_srvs/Trigger.h>
    
    ros::Publisher turtle_vel_pub;
    bool pubCommand = false;
    
    // service回调函数,输入参数req,输出参数res
    bool commandCallback(std_srvs::Trigger::Request  &req,
             			std_srvs::Trigger::Response &res)
    {
    	pubCommand = !pubCommand;
    
        // 显示请求数据
        ROS_INFO("Publish turtle velocity command [%s]", pubCommand==true?"Yes":"No");
    
    	// 设置反馈数据
    	res.success = true;
    	res.message = "Change turtle command state!"
    
        return true;
    }
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "turtle_command_server");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个名为/turtle_command的server,注册回调函数commandCallback
        ros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);
    
    	// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    	turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
    
        // 循环等待回调函数
        ROS_INFO("Ready to receive turtle command.");
    
    	// 设置循环的频率
    	ros::Rate loop_rate(10);
    
    	while(ros::ok())
    	{
    		// 查看一次回调函数队列
        	ros::spinOnce();
    		
    		// 如果标志为true,则发布速度指令
    		if(pubCommand)
    		{
    			geometry_msgs::Twist vel_msg;
    			vel_msg.linear.x = 0.5;
    			vel_msg.angular.z = 0.2;
    			turtle_vel_pub.publish(vel_msg);
    		}
    
    		//按照循环频率延时
    	    loop_rate.sleep();
    	}
    
        return 0;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    • Python

    注意,ros在Python中没有spinonce方法,可通过多线程来实现

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
    
    import rospy
    import thread,time
    from geometry_msgs.msg import Twist
    from std_srvs.srv import Trigger, TriggerResponse
    
    pubCommand = False;
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
    
    def command_thread():	
    	while True:
    		if pubCommand:
    			vel_msg = Twist()
    			vel_msg.linear.x = 0.5
    			vel_msg.angular.z = 0.2
    			turtle_vel_pub.publish(vel_msg)
    			
    		time.sleep(0.1)
    
    def commandCallback(req):
    	global pubCommand
    	pubCommand = bool(1-pubCommand)
    
    	# 显示请求数据
    	rospy.loginfo("Publish turtle velocity command![%d]", pubCommand)
    
    	# 反馈数据
    	return TriggerResponse(1, "Change turtle command state!")
    
    def turtle_command_server():
    	# ROS节点初始化
        rospy.init_node('turtle_command_server')
    
    	# 创建一个名为/turtle_command的server,注册回调函数commandCallback
        s = rospy.Service('/turtle_command', Trigger, commandCallback)
    
    	# 循环等待回调函数
        print "Ready to receive turtle command."
    
        thread.start_new_thread(command_thread, ())
        rospy.spin()
    
    if __name__ == "__main__":
        turtle_command_server()
    
    

    2.8 服务数据的定义与使用

    在这里插入图片描述
    在这里插入图片描述

    • C++
    //客户端
    /**
     * 该例程将请求/show_person服务,服务数据类型learning_service::Person
     */
    
    #include <ros/ros.h>
    #include "learning_service/Person.h"
    
    int main(int argc, char** argv)
    {
        // 初始化ROS节点
    	ros::init(argc, argv, "person_client");
    
        // 创建节点句柄
    	ros::NodeHandle node;
    
        // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
    	ros::service::waitForService("/show_person");
    	ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
    
        // 初始化learning_service::Person的请求数据
    	learning_service::Person srv; //注意要跟srv的文件名相同
    	srv.request.name = "Tom";
    	srv.request.age  = 20;
    	srv.request.sex  = learning_service::Person::Request::male;
    
        // 请求服务调用
    	ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", 
    			 srv.request.name.c_str(), srv.request.age, srv.request.sex);
    
    	person_client.call(srv);
    
    	// 显示服务调用结果
    	ROS_INFO("Show person result : %s", srv.response.result.c_str());
    
    	return 0;
    };
    
    
    
    
    
    //服务端
    
    /**
     * 该例程将执行/show_person服务,服务数据类型learning_service::Person
     */
     
    #include <ros/ros.h>
    #include "learning_service/Person.h"
    
    // service回调函数,输入参数req,输出参数res
    bool personCallback(learning_service::Person::Request  &req,
             			learning_service::Person::Response &res)
    {
        // 显示请求数据
        ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);
    
    	// 设置反馈数据
    	res.result = "OK";
    
        return true;
    }
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "person_server");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个名为/show_person的server,注册回调函数personCallback
        ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
    
        // 循环等待回调函数
        ROS_INFO("Ready to show person informtion.");
        ros::spin();
    
        return 0;
    }
    
    
    • Python

    客户端

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将请求/show_person服务,服务数据类型learning_service::Person
    
    import sys
    import rospy
    from learning_service.srv import Person, PersonRequest
    
    def person_client():
    	# ROS节点初始化
        rospy.init_node('person_client')
    
    	# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
        rospy.wait_for_service('/show_person')
        try:
            person_client = rospy.ServiceProxy('/show_person', Person)
    
    		# 请求服务调用,输入请求数据
            response = person_client("Tom", 20, PersonRequest.male)
            return response.result
        except rospy.ServiceException, e:
            print "Service call failed: %s"%e
    
    if __name__ == "__main__":
    	#服务调用并显示调用结果
        print "Show person result : %s" %(person_client())
    
    
    
    服务端
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将执行/show_person服务,服务数据类型learning_service::Person
    
    import rospy
    from learning_service.srv import Person, PersonResponse
    
    def personCallback(req):
    	# 显示请求数据
        rospy.loginfo("Person: name:%s  age:%d  sex:%d", req.name, req.age, req.sex)
    
    	# 反馈数据
        return PersonResponse("OK")
    
    def person_server():
    	# ROS节点初始化
        rospy.init_node('person_server')
    
    	# 创建一个名为/show_person的server,注册回调函数personCallback
        s = rospy.Service('/show_person', Person, personCallback)
    
    	# 循环等待回调函数
        print "Ready to show person informtion."
        rospy.spin()
    
    if __name__ == "__main__":
        person_server()
    
    

    2.9 参数的使用与编程方法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • C++
    /**
     * 该例程设置/读取海龟例程中的参数
     */
    #include <string>
    #include <ros/ros.h>
    #include <std_srvs/Empty.h>
    
    int main(int argc, char **argv)
    {
    	int red, green, blue;
    
        // ROS节点初始化
        ros::init(argc, argv, "parameter_config");
    
        // 创建节点句柄
        ros::NodeHandle node;
    
        // 读取背景颜色参数
    	ros::param::get("/background_r", red);
    	ros::param::get("/background_g", green);
    	ros::param::get("/background_b", blue);
    
    	ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);
    
    	// 设置背景颜色参数
    	ros::param::set("/background_r", 255);
    	ros::param::set("/background_g", 255);
    	ros::param::set("/background_b", 255);
    
    	ROS_INFO("Set Backgroud Color[255, 255, 255]");
    
        // 读取背景颜色参数
    	ros::param::get("/background_r", red);
    	ros::param::get("/background_g", green);
    	ros::param::get("/background_b", blue);
    
    	ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);
    
    	// 调用服务,刷新背景颜色
    	ros::service::waitForService("/clear");
    	ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");
    	std_srvs::Empty srv;
    	clear_background.call(srv);
    	
    	sleep(1);
    
        return 0;
    }
    
    

    在这里插入图片描述
    在这里插入图片描述

    • Python
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程设置/读取海龟例程中的参数
    
    import sys
    import rospy
    from std_srvs.srv import Empty
    
    def parameter_config():
    	# ROS节点初始化
        rospy.init_node('parameter_config', anonymous=True)
    
    	# 读取背景颜色参数
        red   = rospy.get_param('/background_r')
        green = rospy.get_param('/background_g')
        blue  = rospy.get_param('/background_b')
    
        rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)
    
    	# 设置背景颜色参数
        rospy.set_param("/background_r", 255);
        rospy.set_param("/background_g", 255);
        rospy.set_param("/background_b", 255);
    
        rospy.loginfo("Set Backgroud Color[255, 255, 255]");
    
    	# 读取背景颜色参数
        red   = rospy.get_param('/background_r')
        green = rospy.get_param('/background_g')
        blue  = rospy.get_param('/background_b')
    
        rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)
    
    	# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
        rospy.wait_for_service('/clear')
        try:
            clear_background = rospy.ServiceProxy('/clear', Empty)
    
    		# 请求服务调用,输入请求数据
            response = clear_background()
            return response
        except rospy.ServiceException, e:
            print "Service call failed: %s"%e
    
    if __name__ == "__main__":
        parameter_config()
    
    

    2.10 tf坐标系广播与监听的编程实现

    在这里插入图片描述
    在这里插入图片描述

    • C++
      广播器的编写
    /**
     * 该例程产生tf数据,并计算、发布turtle2的速度指令
     */
    
    #include <ros/ros.h>
    #include <tf/transform_broadcaster.h>
    #include <turtlesim/Pose.h>
    
    std::string turtle_name;
    
    void poseCallback(const turtlesim::PoseConstPtr& msg)
    {
    	// 创建tf的广播器
    	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);
    
    	// 广播world与海龟坐标系之间的tf数据
    	br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
    }
    
    int main(int argc, char** argv)
    {
        // 初始化ROS节点
    	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数据,并计算、发布turtle2的速度指令
     */
    
    #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节点
    	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的监听器
    	tf::TransformListener listener;
    
    	ros::Rate rate(10.0);
    	while (node.ok())
    	{
    		// 获取turtle1与turtle2坐标系之间的tf数据
    		tf::StampedTransform transform;
    		try
    		{
    			//查询是否有这两个坐标系,查询当前时间,如果超过3s则报错
    			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的速度控制指令
    		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;
    };
    
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    • Python

    广播器的编写

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将请求/show_person服务,服务数据类型learning_service::Person
    
    import roslib
    roslib.load_manifest('learning_tf')
    import rospy
    
    import tf
    import turtlesim.msg
    
    def handle_turtle_pose(msg, turtlename):
        br = tf.TransformBroadcaster()
        br.sendTransform((msg.x, msg.y, 0),
                         tf.transformations.quaternion_from_euler(0, 0, msg.theta),
                         rospy.Time.now(),
                         turtlename,
                         "world")
    
    if __name__ == '__main__':
        rospy.init_node('turtle_tf_broadcaster')
        turtlename = rospy.get_param('~turtle')
        rospy.Subscriber('/%s/pose' % turtlename,
                         turtlesim.msg.Pose,
                         handle_turtle_pose,
                         turtlename)
        rospy.spin()
    
    

    监听器的编写

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 该例程将请求/show_person服务,服务数据类型learning_service::Person
    
    import roslib
    roslib.load_manifest('learning_tf')
    import rospy
    import math
    import tf
    import geometry_msgs.msg
    import turtlesim.srv
    
    if __name__ == '__main__':
        rospy.init_node('turtle_tf_listener')
    
        listener = tf.TransformListener()
    
        rospy.wait_for_service('spawn')
        spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
        spawner(4, 2, 0, 'turtle2')
    
        turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
    
        rate = rospy.Rate(10.0)
        while not rospy.is_shutdown():
            try:
                (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
            except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
                continue
    
            angular = 4 * math.atan2(trans[1], trans[0])
            linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)
            cmd = geometry_msgs.msg.Twist()
            cmd.linear.x = linear
            cmd.angular.z = angular
            turtle_vel.publish(cmd)
    
            rate.sleep()
    
    

    2.11 launch启动文件的使用方法

    Launch文件 :通过XML文件实现多节点的配置和启动(可自动启动ROS Master)
    Launch文件语法:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    参数设置
    在这里插入图片描述
    在这里插入图片描述


    重映射
    在这里插入图片描述

    注意,映射完后原资源就不复存在了


    嵌套
    在这里插入图片描述


    其他:https://wiki.ros.org/roslaunch/XML

    例1:

    <launch>
        <node pkg="learning_topic" type="person_subscriber" name="talker" output="screen" />
        <node pkg="learning_topic" type="person_publisher" name="listener" output="screen" /> 
    </launch>
    

    例2:

    <launch>
    
    	<param name="/turtle_number"   value="2"/>
    
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node">
    		<param name="turtle_name1"   value="Tom"/>
    		<param name="turtle_name2"   value="Jerry"/>
    
    		<rosparam file="$(find learning_launch)/config/param.yaml" command="load"/>
    	</node>
    
        <node pkg="turtlesim" type="turtle_teleop_key" name="turtle_teleop_key" output="screen"/>
    
    </launch>
    
    

    例3:

     <launch>
    
        <!-- Turtlesim Node-->
        <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>
    

    例4:

    <launch>
    
    	<!-- Turtlesim Node-->
    	<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
    	<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
    
    	<node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py">
    	  <param name="turtle" type="string" value="turtle1" />
    	</node>
    	<node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py">
    	  <param name="turtle" type="string" value="turtle2" /> 
    	</node>
    
        <node pkg="learning_tf" type="turtle_tf_listener.py" name="listener" />
    
    </launch>
    
    

    例5:

    <launch>
    
    	<include file="$(find learning_launch)/launch/simple.launch" />
    
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node">
    		<remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
    	</node>
    
    </launch>
    
    

    2.12 常用可视化工具的使用

    2.12.1 rqt

    在这里插入图片描述

    rqt 是一个比较综合的工具,集成了rqt_ploat 等一系列的工具,可用于机器人的上位机调试软件

    2.12.2 Rviz

    在这里插入图片描述

    roscore
    rosrun rviz rviz
    

    2.12.3 Gazebo

    在这里插入图片描述

    roslaunch gazebo_ros
    

    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • ROS入门

    2021-03-02 17:20:15
    ROS入门什么是ROS? ROS产生、发展和壮大的原因和意义?在Ubuntu系统中熟悉ROS基本命令;运行小海龟demo例子,通过键盘控制小海龟运动。记录整个实践过程。 什么是ROS? ROS产生、发展和壮大的原因和意义? 1.什么是...
  • ROS入门的基本操作命令手册,详细介绍了ROS使用常用的命令及含义,是一份不可多得的文档资料,希望对需要学习ROS的人员有所帮助。
  • ROS入门资料.docx

    2020-08-13 11:49:10
    ROS入门资料,仅供初学者使用,ROS(机器人操作系统,Robot Operating System),是专为机器人软件开发所设计出来的一套电脑操作系统架构。它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,...
  • SLAM导航机器人零基础实战系列-第2章_ROS入门 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便。我们的机器人“miiboo”中的大部分程序也采用ROS进行...
  • 自己总结的ROS基本操作

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,838
精华内容 5,135
关键字:

ros入门