标签 C 下的文章

Hello, Apollo

要说目前哪个技术领域投资最火热,莫过于人工智能。而人工智能领域中最火的(或者说之一)肯定要算上自动驾驶。自动驾驶的概念不是什么新鲜的玩意了,只是随着近两年这一波人工智能的大热,自动驾驶又被推到了风口浪尖。各大汽车厂商、互联网公司也都跃跃欲试,准备给汽车这一“历经百年的黄金平台”做一次新的“赋能”。

今年7月5日,国内搜索引擎No.1企业百度在其首届百度AI开发者大会上发布了Apollo自动驾驶开放平台,同时百度也对外宣布baidu正式从互联网公司转型为一家人工智能公司。作为“错过了移动互联网时代”的典型公司代表,百度这次押宝人工智能,我觉得也是战略上迫不得已的选择:在现有现金牛“搜索广告业务”还能带来大量利润的时候,为抓住未来那头现金牛而进行的努力。而Apollo自动驾驶平台恰是百度人工智能战略的重要组成部分。

Apollo,阿波罗是古希腊神话中的光明之神,这个名字在西方文化中“自带光环”。提到Apollo,很多人还会想到半个多世纪前美国著名的“登月计划”。百度将其自动驾驶平台命名为Apollo,我猜测是有“借势之意”,即期望Apollo这个项目能在百度众多人工智能业务中拥有美好光明的前景。

作为技术人员,我们不能像一般媒体人员那样根据官方提供的“说辞”做宽泛的介绍,我们要与Apoll亲密接触,看看Apollo究竟是什么,究竟能做什么。这里就和大家一起来Say Hello to Apollo。

一、自动驾驶汽车- “百年黄金平台”的新时代赋能

在正式入门Apollo之前,还要说点“废话”。在接触Apollo之前,我从未认真思考过“汽车”这个平台,这次算是“顿悟”,虽然也算不上深刻。就我看来,汽车 是一个不可多得的“黄金平台”。作为一个平台,汽车已经有了上百年的历史,见证了人类科学技术的发展,是跨学科之集大成者。这百年多时间,任何新的、先进的民用技术都会赋能在汽车工业上。以一个长不足5米,重量不超过2t的一般家用乘用车为例,我们在其上面能看到先进的能源技术、材料技术、化工技术、电子技术、通讯技术以及精密的机械原件和组装技术等,可以说汽车为各个公司的创造力提供了展示的舞台。

就普通老百姓的衣食住行而言,汽车也是史无前例的高频使用典范,且是最直接、最贴近普通百姓生活的,这些都是飞机、火车等无法媲美的(如果非要选一个,那只有智能终端能与汽车媲美了,尤其是在集成度方面)。即便是到了科幻片中的漫天跑飞行器的时候,汽车也可能依旧是短距离交通的首选。当然届时的汽车很可能与我们此时的汽车大不相同了。随着时代的进步,汽车也在演化,日新月异的新技术、新材料、新能源对汽车的进一步赋能,因此汽车依旧是朝阳产业,这也是国际资本依旧积极群雄逐鹿汽车工业发展的根本原因了。比如:通过新能源方式赋能汽车的特斯拉、通过无人驾驶技术赋能的Google的waymo等。当然,不仅是从技术方面,从商业模式方面也有围绕着汽车这一平台创新的经典案例,典型的比如:uber滴滴等的高效出行以及近期日渐升温的共享汽车出行。

可以说,各大公司都在从自身优势出发,考虑如何为汽车这一百年黄金平台赋能。从这一点出发,我们就能大致理解百度Apollo的出现了:它是baidu结合自身的技术优势和数据优势拥抱汽车工业、为汽车做新时代赋能而迈出的重要一步。

二、Apollo的技术架构

Apollo是一套完整的自动驾驶技术方案,官方架构原图的截图较为模糊,这里自己画了一个简单的四层结构,每层内的模块暂未画出,因为不是本次入门的重点:

img{512x368}

按照上图,apollo自动驾驶分成四层技术栈,从下到上分别为:

1、Reference Vehicle Platform(参考车辆平台)

自动驾驶最终都要落地到车上,因此apollo抽象了一个”参考车辆平台”层,通过电子化的方式控制车辆的行驶行为。

Note: 在开发者大会上,百度展示了由美国创业公司AutonomouStuff基于Apollo 1.0开放平台改装而成的循迹自动驾驶车,这辆车是一辆美系的林肯MKZ。也就是说当前发布的Apollo适配林肯MKZ是没有问题的。但这款中型车对于普通开发者来说门槛算是稍高了。如果百度能拿出一款大众系、丰田系或至少也应该是一个本田系这样的车型,那对自动驾驶领域的开发者或者说爱好者来说,才是福利。相比而言,著名黑客George Hotz创立的自动驾驶技术公司comma.ai为其openpilot初始选用的车型则是Honda系的思域和CR-V,滥大街的车型,容易搞到,且低成本搞到,也容易改装。

2、Reference Hardware Platform(参考硬件平台)

这一层为自动驾驶汽车提供计算、感知、交互的硬件能力,包括计算单元(车载处理器设备)、GPS/IMU(惯性测量设备)、摄像头、激光雷达、声波雷达、HMI(人机接口)等。在发布的Apollo 1.0版本中,开放的硬件能力包括:计算单元、GPS/IMU(惯性测量设备)以及HMI。

3、Apollo open software Platform (开放软件平台)

这一层是百度Apollo 1.0开放的核心部分,见下图(蓝色的代表在apollo 1.0.0中已经开放的能力):

img{512x368}

从图中看到,这一层还可以分为三个子层,从下至上分别是:

  • apollo kernel层

这一层是运行于硬件上面的OS,对于自动驾驶这种实时性要求特别强的领域,这里显然只能是RTOS(实时操作系统)。Apollo 1.0开放的源码中包含一个”Apollo Kernel“的项目,在这个项目下汇集着可以满足实时性需求的OS kernel。当然目前还仅有一个选择:realtime linux kernel。这是apollo基于Linux Kernel 4.4.32+realtime patch定制的一款专用linux内核。

  • apollo platform层

在Kernel层的上面就是apollo的runtime framework了,提供platform级的支撑。Apollo 1.0同样也创建了一个专用项目:apollo-platform,用于汇集满足apollo平台级支撑需求的platform。当前该项目下也仅提供了一种选择:Apollo ROS,是基于ROS1的Indigo版二次开发后的定制版ROS。Apollo ROS基于自动驾驶需求出发,对ROS1主要做了三方面改进:

  • 为优化自动驾驶大量使用传感器引发很大的传输带宽需求, Apollo ROS改变基于socket的网络传输模式,大量采用共享内存的node间通信机制,减少传输中的数据拷贝,显著提升传输效率, 尤其是在满足一对多的传输场景下效果明显;

  • 从鲁棒性出发,使用RTPS(Real-Time Publish Subscribe)服务发现协议实现完全的P2P网络拓扑,避免原ROS的以Master作为拓扑网络的中心的单点故障问题;

  • 使用protobuf替代原ROSmessage,提供很好的向后兼容,避免接口升级后,不同版本的模块难以兼容的问题。

其实第二点改进也是ROS2正在做的事情。关于Apollo ROS的详尽变化,可以参考前不久百度工程师的一个分享:《Apollo代码开放框架—ROS 探索与实践》

  • apollo modules层

在这一层是apollo的功能modules,当前似乎依旧是基于ROS的package开发的,在github.com/ApolloAuto/apollo/modules/common/apollo_app.cc你大致能看出来一个ROS Package的开发模板。这一层提供诸如:规划(planning)、洞察(perception)、控制(control)、预测(prediction)、决策(decision)、定位等诸多功能。但Apollo 1.0仅仅开放了Control、Localization和HMI三个module,因为这三块足以构成Apollo 1.0提供的封闭场地循迹驾驶体系了。

4、Cloud Services(云端服务)

Apollo 1.0还开放了云端数据平台,以及唤醒万物的DuerOS能力。DuerOS也是Baidu人工智能战略的重要棋子,似乎也是目前Baidu在AI方面最为成熟的、应用最广的产品。当然这一层还包括仿真、高精度地图等服务,不过目前尚未开放。

三、上手Apollo

买不起林肯MKZ的童鞋也不要担心,Apollo 1.0提供了一个本地仿真工具,给你一个与Apollo亲密接触的途径,让你可以在PC上肆无忌惮地玩耍,毕竟Apollo 1.0仅提供封闭场地的寻迹能力,相对简单。

我们的重点是Apollo open software Platform这一层,而这一层中,我们不关心apollo kernel,只关心Apollo ROS和三个已经开放的apollo modules。

1、下载release版本

截至目前为止,Apollo仅发布了一个版本:apollo-v1.0.0,我们可以从github上将其下载到本地:

# wget -c https://github.com/ApolloAuto/apollo/archive/v1.0.0.tar.gz
# tar zxvf v1.0.0.tar.gz
# cd apollo-1.0.0
# ls -F
apollo_docker.sh*  apollo.doxygen  apollo.sh*  AUTHORS.md  BUILD  CPPLINT.cfg
docker/  docs/  LICENSE  modules/  README.md  scripts/  third_party/  tools/  WORKSPACE

注意:我的实验环境为ubuntu 16.04.1 amd64。

2、本地源码构建

对于基于Apollo这个framework的开发者,Apollo官方强烈建议直接采用官方预定义好的专用docker环境(for dev)。对于爱折腾的我而言,必须要在本地做一次源码构建,即使这个体验是糟糕的,甚至最终是失败的^0^。源码构建的命令很简单,一行即可:

# cd apollo-1.0.0
# bash apollo.sh build

在这个过程中,我遇到了两个错误:

  • bazel不存在

Apollo的构建依赖google出品的bazel构建工具,我个人对bazel并没有什么研究,这里先装上再说:

# echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" |  tee /etc/apt/sources.list.d/bazel.list
deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8

# curl https://bazel.build/bazel-release.pub.gpg | apt-key add -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3157  100  3157    0     0   3202      0 --:--:-- --:--:-- --:--:--  3201
OK

# apt-get update && apt-get install bazel
  • third_party/ros/setup.bash: No such file or directory

apollo的编译要依赖ros,但apollo并没有自带ros。我们需要到apollo platform那个项目中去下载Apollo ROS:

# wget -c https://github.com/ApolloAuto/apollo-platform/releases/download/1.0.0/ros-indigo-apollo-1.0.0.x86_64.tar.gz
# tar zxvf ros-indigo-apollo-1.0.0.x86_64.tar.gz
# cd ros
# ls -F
bin/  BUILD  env.sh*  etc/  include/  lib/  setup.bash  setup.sh  _setup_util.py*  setup.zsh  share/

将下载的ros目录copy到apollo-1.0.0/third_party下,并chmod +x third_party/ros/setup.bash。

我们再次执行bash apollo.sh build,这次执行前面的error和warning基本都消失了,apollo.sh脚本开始下载依赖包并编译:

# bash apollo.sh build
ROS_DISTRO was set to 'kinetic' before. Please make sure that the environment does not mix paths from different distributions.
[WARNING] ESD CAN library supplied by ESD Electronics does not exit.
[WARNING] If you need ESD CAN, please refer to third_party/can_card_library/esd_can/README.md
.
____Loading package: modules/common/util/testing
____Loading package: @com_github_grpc_grpc//
____Loading package: @google_styleguide//
____Loading package: @glog//
____Loading package: @eigen//
____Loading package: @gtest//
____Loading package: @civetweb//
____Loading package: @com_github_google_protobuf//
____Loading package: @websocketpp//
____Loading package: @curlpp//
Building on x86_64, with targets:
//tools/platforms:x86_64
//tools/platforms:aarch64
//modules/prediction:prediction
//modules/prediction:prediction_lib
... ...
//modules/common:log
//modules/canbus/proto:canbus_proto.pb
//:x86_64
//:arm64
WARNING: Running Bazel server needs to be killed, because the startup options are different.
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,750,374 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3309 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,773,664 bytes
INFO: Cloning https://github.com/madler/zlib: Receiving objects (3314 / 5016)
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 2,795,584 bytes
INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,504,198 bytes

INFO: Downloading https://github.com/google/boringssl/archive/master-with-bazel.zip via codeload.github.com: 13,522,008 bytes
INFO: Found 190 targets...
[34 / 41] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/java/java_message_lite.cc [for host]
[41 / 48] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/command_line_interface.cc [for host]
[157 / 163] Compiling external/com_github_google_protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc [for host]
[752 / 756] Compiling external/com_github_grpc_grpc/src/core/ext/client_config/resolver_result.c

ERROR: /root/test/apolloauto/apollo-1.0.0/modules/canbus/BUILD:32:1: Linking of rule '//modules/canbus:canbus' failed: gcc failed: error executing command /usr/bin/gcc -o bazel-out/local-dbg/bin/modules/canbus/canbus '-Wl,-rpath,$ORIGIN/../../_solib_k8/_U_S_Sthird_Uparty_Sros_Cros_Ucommon___Uthird_Uparty_Sros_Slib' ... (remaining 8 argument(s) skipped): com.google.devtools.build.lib.shell.BadExitStatusException: Process exited with status 1.
modules/canbus/main.cc:21: error: undefined reference to 'ros::init(int&, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
third_party/ros/include/ros/publisher.h:107: error: undefined reference to 'ros::console::initializeLogLocation(ros::console::LogLocation*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ros::console::levels::Level)'
... ...
collect2: error: ld returned 1 exit status
INFO: Elapsed time: 578.172s, Critical Path: 26.62s
============================
[ERROR] Build failed!
[INFO] Took 597.189 seconds
============================

经过漫长的等待后,还是以失败告终。并且C++的错误输出分析起来真是好痛苦,于是暂时放弃本地源码编译。

3、pre-specified Docker dev环境

既然apollo已经为我们准备好了pre-specified Docker dev环境,我们不妨用一下,下载和启动该环境可以用下面命令:

# cd apollo-1.0.0
# bash docker/scripts/dev_start.sh

apolloauto/apollo:dev-latest这个image超级庞大,大约有7个G左右,所以你需要耐心等待一会儿了。docker运行起来后,我们在另外一个terminal windows下可以执行下面命令切入到该docker容器内部:

# bash docker/scripts/dev_into.sh
root@myhost: /apollo#

在dev container中,我们可以来编译一下apollo源码:

root@myhost:/apollo# bash apollo.sh build
... ...
Copyright (c) 2017 Various License Holders. All Rights Reserved
Apollo software is built on top of various other open source software packages,
a complete list of licenses are located at https://github.com/ApolloAuto/apollo/blob/master/third_party/ACKNOWLEDGEMENT.txt

You agree to the terms of all the License Agreements.

Type 'y' or 'Y' to agree to the license agreement above, or type any other key to exit
y[WARNING] ESD CAN library supplied by ESD Electronics does not exit.
[WARNING] If you need ESD CAN, please refer to third_party/can_card_library/esd_can/README.md
____Loading package: modules/monitor/common
____Loading package: modules/common/adapters
____Loading package: modules/dreamview/conf
____Loading package: modules/control/integration_tests
____Loading package: @google_styleguide//
____Loading package: @com_github_google_protobuf//
... ...
[502 / 1,099] Compiling external/com_github_grpc_grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.c
[914 / 1,524] Compiling external/com_github_grpc_grpc/src/core/ext/census/tracing.c
[1,304 / 1,527] Linking modules/canbus/vehicle/libmessage_manager_base.a

INFO: Elapsed time: 371.151s, Critical Path: 260.93s
============================
[ OK ] Build passed!
[INFO] Took 401.521 seconds
============================

由于dev环境中相关的依赖已经就绪,因此无需过多干预,在漫长的一段等待后,我们看到编译ok了。

4、运行apollo demo

在dev enviroment中或apollo:release-latest中,我们都可以运行apollo的一个寻迹小车的demo。以apollo:release-latest image环境为例:

// 启动基于apollo:release-latest image的apollo container(image size大约为3G,耐心等待下载):

# cd apollo-1.0.0/
# bash docker/scripts/release_start.sh

//切入到容器中去
# bash docker/scripts/release_into.sh
root@myhost:/apollo#

在容器中启动HMI(human-machine interface):

root@myhost:/apollo# bash scripts/hmi.sh
Start roscore...
HMI ros node service running at localhost:8887
HMI running at http://localhost:8887

root@myhostr:/apollo# rosnode list
/hmi_ros_node_service
/rosout

可以看到,hmi.sh脚本启动了roscore(ros master节点和相关服务)以及hmi的service,我们打开浏览器,输入:http://host_ip:8887即可看到如下场景:

img{512x368}

在容器内继续执行如下命令,回放小车的轨迹数据:

# rosbag play -l ./docs/demo_guide/demo.bag

[ INFO] [1502809442.462789096]: Opening ./docs/demo_guide/demo.bag

Waiting 0.2 seconds after advertising topics... done.

Hit space to toggle paused, or 's' to step.
 [RUNNING]  Bag Time: 1497125289.756657   Duration: 20.614178 / 41.613536
 [RUNNING]  Bag Time: 1497125289.896669   Duration: 20.754189 / 41.613536
... ...

我们打开hmi页面上的Debug开关,点击右上角的”Dreamview”按钮,稍后片刻,你就会在新打开的页面上看到小车仿真寻迹行驶的场景了:

img{512x368}

最初实验时,由于没有在阿里云的防火墙打开8888端口,导致dreamview的websocket建立连接失败,dreamview页面始终无法显示出小车。后经与apollo team的ycool在线联调才发现这个问题。这个问题的解决方法也已更新到Apollo的FAQ中了。

四、小结

Baidu为apollo项目做了一个4年的规划(见下面的roadmap),并计划在2020年实现全路网自动驾驶,这个说法似乎有意避开了自动驾驶的级别,这个2020目标到底是L4呢还是L5呢?不过无论是L4还是L5,这个目标都十分有挑战啊。

img{512x368}

个人觉得:未来的L4、L5级别的自动驾驶一定不光光是依靠车辆自身的设备与算法,还要与道路基础设施相配合去实现。甚至是依赖车与车之间的通信才能做到全天候、全路况的自动驾驶。apollo虽然迈出了第一步,但任重道远,让我们拭目以待吧!


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

Hello, ROS

ROS,全称是Robot Operating System,字面译为“机器人操作系统”。不过ROS并非是一个真正意义上的操作系统,而仅仅是一套用于机器人操作和控制软件开发的开发框架(framework),包括各种库和工具。

ROS在2007年诞生于斯坦福大学人工智能实验室Stanford Artificial Intelligence Laboratory,简称SAIL;2008年至2013年,ROS的开发和推广由Willow Garage公司(该公司2014年已关门大吉)主导。2013年8月,ROS的管理权转移给了Open Source Robotics Foundation。截至目前,ROS已经成为全世界使用和支持最为广泛的机器人开发框架之一。

一、ROS简介

ROS推出的初衷旨在降低机器人类软件开发的门槛,提高复用率,避免机器人软件开发人员的重复劳动,快速搭建机器人原型。因此,它采用了当时流行的面向服务SOA的软件架构,最大程度上降低内部耦合,并且易于被第三方扩展。采用C++作为主要开发语言,提高ROS的可移植性,让ROS可以很方便地移植到其他各种CPU体系和OS上。

ROS最初的是针对单机家用移动智能机器人而设计的,因此ROS1版本在以下几方面尚存不足:

  • 鲁棒性

ROS1版本运行时仅有一个master node,一旦master node发生crash,整个robot将无法正常工作。

  • 安全性

ROS1内部完全不设防,Node间通信完全是信赖的。任何Node都可以轻易得到其他node的各种topic数据、参数以及访问相关关键service。

  • 实时性

在ROS1的设计约束下,ROS内部各个节点间产生的实时数据通过master建立的内部网络在各个node间传递。一旦数据量很大,数据可能因内部网络通信性能问题而导致延迟,致使机器人工作异常。这也是ROS在工业机器人领域并未受到“热烈欢迎”的重要原因之一。

为了解决上述这些问题,ROS启动了ROS2的设计和实现。ROS2的第一个alpha版本发布于2015年,最新一个版本是今年七月份发布的beta2版本,ROS2的1.0版本计划将于今年年末正式发布。不过对于ROS2,笔者了解也不多,感兴趣的童鞋可以移步其wiki观看详情。

二、ROS1安装

在深入ROS1之前,我们先来安装一个ROS1。我们首先需要选择一个ROS1的发布版。ROS的发布模式与Ubuntu极其相似:每逢偶数年份发布一个长期支持版(LTS),support 5年;每逢奇数年份发布一个支持2年的版本。

并且ROS的发布版与Ubuntu发布版有着“神同步”:

2014:     ROS Indigo Igloo  对应  Ubuntu 14.04 LTS
2016:     ROS Kinetic Kame 对应 Ubuntu 16.04 LTS

ROS主要基于Ubuntu这款OS进行开发和测试,所以官方建议ROS尽量与Ubuntu一并使用,当然其他linux distribution也可以安装ROS,但正确性和稳定性ROS不能给予明确的保证。目前ROS1发布版的最新版本为:ROS Lunar Loggerhead,但官方推荐使用Ubuntu 16.04 + ROS Kinetic Kame组合;不过由于KK版本发布也就一年出头,市面上更多组织采用的可能还是Ubuntu 14.04 + ROS Indigo Igloo组合。

这里以Ubuntu 16.04+ ROS Kinetic Kame简单说明一下ROS1的安装过程:

1、获取source list并update源

# sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
# apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
Executing: /tmp/tmp.gJDpQgL6qG/gpg.1.sh --keyserver
hkp://ha.pool.sks-keyservers.net:80
--recv-key
421C365BD9FF1F717815A3895523BAEEB01FA116
gpg: requesting key B01FA116 from hkp server ha.pool.sks-keyservers.net
gpg: key B01FA116: public key "ROS Builder <rosbuild@ros.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1

如果需要代理,可以用:
apt-key adv --keyserver-options http-proxy=<myProxy>  --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116

# apt-get update

2、安装kk版本

ROS有几个release配置供你选择安装:ROS-Base、Desktop Install和Desktop-Full Install,Desktop-Full Install是官方推荐的选项,也是安装最全的选项,它包含了ROS, rqt, rviz, robot-generic libraries, 2D/3D simulators, navigation and 2D/3D perception等package:

# apt-get install ros-kinetic-desktop-full

这个过程需要好长一段时间(依你的网络情况而定),因为ROS超级庞大,有大约2G的安装文件要下载安装。

3、初始化ROS依赖

在使用ROS之前,我们还得先初始化ROS的一些依赖,ROS为你提供了“一键式”的初始化命令:

# rosdep init
Wrote /etc/ros/rosdep/sources.list.d/20-default.list
Recommended: please run

    rosdep update

# rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
... ...
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index https://raw.githubusercontent.com/ros/rosdistro/master/index.yaml
Add distro "groovy"
Add distro "hydro"
Add distro "indigo"
Add distro "jade"
Add distro "kinetic"
Add distro "lunar"
updated cache in /home/tonybai/.ros/rosdep/sources.cache
... ...

到这里,我们可以看到ROS被安装到/opt/ros/kinetic下面了:

# tree -L 1  /opt/ros/kinetic
/opt/ros/kinetic
├── bin
├── env.sh
├── etc
├── include
├── lib
├── setup.bash
├── setup.sh
├── _setup_util.py
├── setup.zsh
└── share

5 directories, 5 files

4、设置环境变量

ROS提供了设置环境变量的脚本:/opt/ros/kinetic/setup.bash,我们将其加入到.bashrc中,这样每次用户登录后就可以使用下面这些ROS专属环境变量了:

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

# env|grep ROS
ROS_ROOT=/opt/ros/kinetic/share/ros
ROS_PACKAGE_PATH=/opt/ros/kinetic/share
ROS_MASTER_URI=http://localhost:11311
ROSLISP_PACKAGE_DIRECTORIES=
ROS_DISTRO=kinetic
ROS_ETC_DIR=/opt/ros/kinetic/etc/ros

5、安装一些用于ROS package构建的工具依赖

ROS的用户会创建自己的ROS package,为了方便构建这些user package,我们需要安装以下一些工具:

# apt-get install python-rosinstall python-rosinstall-generator python-wstool build-essential

6、验证安装结果

完成以上操作后,ROS kk版本就安装OK了,我们来验证一下安装结果是否正确。我们来尝试启动一下ROS的master node:

# roscore
... logging to /root/.ros/log/fc6a002e-75cf-11e7-b053-00163e1001d7/roslaunch-myhost-7609.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://myhost:43606/
ros_comm version 1.12.7

SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.7

NODES

auto-starting new master
process[master]: started with pid [7620]
ROS_MASTER_URI=http://myhost:11311/

setting /run_id to fc6a002e-75cf-11e7-b053-00163e1001d7
process[rosout-1]: started with pid [7633]
started core service [/rosout]

如果你看到上面这些roscore的输出,那么基本就证明你的ROS1安装成功了!

三、ROS架构

ROS安装完毕后,我们来对ROS做进一步的探索!先来看看ROS1的架构。

ROS文档中将ROS架构分为三个级别:Filesystem level、Computation Graph level和Community level。对于一个framework来说,从字面意义上理解这三个level还是有些晦涩的。Community level先不说,我们可以通过对照来理解Filesystem level和Computation Graph level,实质上它们一个对应的是ROS的静态结构,一个对应的则是ROS的运行时结构。

1、ROS Filesystem level

我们这里借用《Effective Robotics Programming with ROS 3rd》中的图来整体看一下ROS Filesystem的概念:

img{512x368}

ROS实质上是由一系列的packages组成的,在packages的基础上,ROS通过metapackage来聚合一组packages以形成一个逻辑package。基于metapackage和package概念,ROS为开发者提供了在package之间跳转、文件拷贝、包查找、执行等功能的”类FileSystem”命令集合,比如:roscd、rosls、roscp、rosrun、roscat、rospack等。下面是一些命令使用的例子:

// 切换到ros安装目录
root@myhost:~# roscd
root@myhost:/opt/ros/kinetic#

// 切换到turtlesim包目录
root@myhost:~# roscd turtlesim
root@myhost:/opt/ros/kinetic/share/turtlesim#

// list turtlesim包内的文件
root@myhost:~# rosls turtlesim
cmake  images  msg  package.xml  srv

// 查找turtlesim包的路径
root@myhost:~# rospack find turtlesim
/opt/ros/kinetic/share/turtlesim

// 执行包turtlesim下的turtlesim_node
root@myhost:~# rosrun turtlesim turtlesim_node

// 查看包turtlesim的package.xml内容
root@myhost:~# roscat turtlesim package.xml

<?xml version="1.0"?>
<package>
  <name>turtlesim</name>
  <version>0.7.1</version>
  <description>
    turtlesim is a tool made for teaching ROS and ROS packages.
  </description>
... ...
</package>

ROS安装后,其所有package均存储在$ROS_PACKAGE_PATH下面,初始情况下即为/opt/ros/kinetic/share:

root@myhost:/opt/ros/kinetic# ls share
actionlib                         eigen_stl_containers          laser_pipeline         rosbag_migration_rule  roswtf                 shape_msgs
actionlib_msgs                    executive_smach               librviz_tutorial       rosbag_storage         rqt_action             simulators
actionlib_tutorials               filters                       map_msgs               ros_base               rqt_bag                smach
... ...

每个package下的结构都类似,以turtlesim包为例:

root@myhost:/opt/ros/kinetic/share# ls -F turtlesim
cmake/  images/  msg/  package.xml  srv/

至此,上面图片中package中的结构似乎与上面看到的turtlesim package中的结构对应上了。每个package下面都至少有一个package.xml作为package的manifests,msg、srv是功能性配置,分别定义了package用到的message和提供的service的结构。这里并没有代码,只是一些配置信息。

而对应的包的可执行文件则在/opt/ros/kinetic/lib下,还是以turtlesim package为例,当我们执行下面命令时:

# rosrun turtlesim turtlesim_node

rosrun首先会到$ROS_PACKAGE_PATH下找是否有package.xml中name为”turtlesim”的package(与目录的名字无关)。如果有,rosrun会到/opt/ros/kinetic/lib/turtlesim下查找是否有turtlesim_node这个二进制可执行文件。存在,则启动之;否则报错。

root@myhost:/opt/ros/kinetic/lib/turtlesim# ls
draw_square  mimic  turtlesim_node  turtle_teleop_key

root@myhost:/opt/ros/kinetic/lib/turtlesim# rosrun turtlesim turtlesim_node
[ INFO] [1501549501.410816841]: Starting turtlesim with node name /turtlesim
[ INFO] [1501549501.428589492]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

还有一种package:metapackage。metapackage在目录结构上与普通package无异,但package.xml尾部多了metapackage标签,我们以ros_core/package.xml为例:

<package>
  <name>ros_core</name>
  <version>1.3.1</version>

  <buildtool_depend>catkin</buildtool_depend>

  <run_depend>catkin</run_depend>
  <run_depend>cmake_modules</run_depend>
  <run_depend>common_msgs</run_depend>
  <run_depend>gencpp</run_depend>
  <run_depend>geneus</run_depend>
  <run_depend>genlisp</run_depend>
  <run_depend>genmsg</run_depend>
  <run_depend>gennodejs</run_depend>
  <run_depend>genpy</run_depend>
  <run_depend>message_generation</run_depend>
  <run_depend>message_runtime</run_depend>
  <run_depend>ros</run_depend>
  <run_depend>ros_comm</run_depend>
  <run_depend>rosbag_migration_rule</run_depend>
  <run_depend>rosconsole_bridge</run_depend>
  <run_depend>roscpp_core</run_depend>
  <run_depend>rosgraph_msgs</run_depend>
  <run_depend>roslisp</run_depend>
  <run_depend>rospack</run_depend>
  <run_depend>std_msgs</run_depend>
  <run_depend>std_srvs</run_depend>

  <export>
    <metapackage/>
  </export>
</package>

这种包称为metapackage,它的实质是一组package的集合。

2、ROS Computation Graph level

说完了ROS的静态结构,我们再来看看ROS整体的运行时结构,即ROS Computation Graph level:

img{512x368}

ROS在运行时层面是由一个master和一组node组成的,master的作用就是名字注册和查找,建立node与topic间联系以及服务发现之用。node间的通信方式可以是:

  • 服务srv调用
  • topic的发布和订阅

我们通过rosnode命令可以操作node,比如查看当前ROS中node信息:

# rosnode list
/rosout
/turtlesim

/rosout node是一个由roscore命令启动的特殊node,它相当于整个ROS运行环境的stdout/stderr,将所有node发往/rosout topic的消息汇聚在一起。

每个ROS运行时环境有且仅有一个ros master,ros master通过执行roscore命令启动,这也是一个ROS运行环境启动最先应该执行的命令:

# roscore
... logging to /home/tonybai/.ros/log/ee13b88e-7666-11e7-af90-4ccc6a7061a6/roslaunch-tonybai-myhost-26158.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://tonybai-myhost:36180/
ros_comm version 1.12.7

SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.7

NODES

auto-starting new master
process[master]: started with pid [26169]
ROS_MASTER_URI=http://tonybai-myhost:11311/

setting /run_id to ee13b88e-7666-11e7-af90-4ccc6a7061a6
process[rosout-1]: started with pid [26182]
started core service [/rosout]

roscore位于/opt/ros/kinetic/bin下,它实际上是一个python脚本,它调用位于/opt/ros/kinetic/lib/python2.7/dist-packages/roslaunch下的roslaunch lib,并依据launch配置文件/opt/ros/kinetic/etc/ros/roscore.xml启动对应的核心node:

// /opt/ros/kinetic/etc/ros/roscore.xml
<!--
  ROS Core Stack definition

  Before making any modifications to this file, please read:

http://ros.org/wiki/roscore

  -->
<launch>
  <group ns="/">
    <param name="rosversion" command="rosversion roslaunch" />
    <param name="rosdistro" command="rosversion -d" />
    <node pkg="rosout" type="rosout" name="rosout" respawn="true"/>
  </group>
</launch>

roscore会自动启动master,master对应的是一个metapackage: ros。ros package的package.xml如下:

<package>
  <name>ros</name>
  <version>1.13.5</version>
  <description>ROS packaging system</description>
  <maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
  ... ...

  <buildtool_depend>catkin</buildtool_depend>

  <run_depend>catkin</run_depend> <!-- only for backward compatibility with rosbuild -->
  <run_depend>mk</run_depend>
  <run_depend>rosbuild</run_depend>
  <run_depend>roslang</run_depend>
  <run_depend>roslib</run_depend>
  <run_depend>rosbash</run_depend>
  <run_depend>rosboost_cfg</run_depend>
  <run_depend>rosclean</run_depend>
  <run_depend>roscreate</run_depend>
  <run_depend>rosmake</run_depend>
  <run_depend>rosunit</run_depend>

  <export>
    <metapackage/>
  </export>
</package>

ROS的运行时当前目录为~/.ros,在这个目录下你会看到ros的一些运行时输出信息:

$ tree  -L 1 ~/.ros
/home/tonybai/.ros
├── log/
├── roscore-11311.pid
├── rosdep/
├── rospack_cache_00988404638878154258
├── rospack_cache_04359245844500407984
├── rospack_cache_05251971726343818934
├── rospack_cache_11134725904490598093
├── rosstack_cache_00988404638878154258
├── rosstack_cache_04359245844500407984
├── rosstack_cache_05251971726343818934
└── rosstack_cache_11134725904490598093

2 directories, 9 files

roscore还会启动一个Parameter Server,用于各个节点保存或读取parameters,通过rosparam可以查看相关param信息,比如当前param的list:

$ rosparam list
/background_b
/background_g
/background_r
/rosdistro
/roslaunch/uris/host_tonybai_myhost__36180
/rosversion
/run_id

我们可以通过ros提供的rqt_graph命令查看node之间以及node与topic之间的订阅和发布关系,如下图:

img{512x368}

3、ROS的“分布式”源码结构

安装过程中ROS的“庞大”,与ROS在github上源码库的“渺小”形成鲜明对比。其实我们安装的ROS与这份源码库并非一一对应的:ROS的源码结构也是“分布式”的,ROS源码实质上是一系列package源码的组合。当前版本的ROS发布版采用bloom工具进行release的。以kk版本为例,bloom读取一份rosdistro库的kk版本distribution.yaml文件(这份文件比较庞大),即ROS发布文件,并根据文件中的描述信息,下载对应的package源码并编译构建的:

// kinetic/distribution.yaml)
%YAML 1.1
# ROS distribution file
# see REP 143: http://ros.org/reps/rep-0143.html
---
release_platforms:
  debian:
  - jessie
  fedora:
  - '23'
  - '24'
  ubuntu:
  - xenial
repositories:
  abb:
    doc:
      type: git
      url: https://github.com/ros-industrial/abb.git
      version: kinetic-devel
    release:
      packages:
      - abb
      - abb_driver
      - abb_resources
      ... ...
      tags:
        release: release/kinetic/{package}/{version}
      url: https://github.com/ros-industrial-release/abb-release.git
      version: 1.3.0-1
    source:
      type: git
      url: https://github.com/ros-industrial/abb.git
      version: kinetic
    status: developed
  abb_experimental:
    doc:
      type: git
      url: https://github.com/ros-industrial/abb_experimental.git
      version: kinetic-devel
    status: developed
... ...
type: distribution
version: 2

鉴于ROS这种分布式的相对松散的源码组织结构,对ROS的裁剪则相对简单,只需挑选你自己需要的第三方包即可。

四、启动你的第一个ROS“机器人”

ROS虽然号称机器人开发框架,但拥有一个实体版机器人并不是进行ROS开发的必要条件。ROS的一大优势就是可以利用各种仿真工具进行机器人操作和控制逻辑的仿真和调试。常见的仿真器主要有三个:TurtlesimRviz+arbotixGazebo。Turtlesim是一个QT开发的2D轨迹显示界面,只能显示运动轨迹;arbotix是含有一个差速驱动机器人的控制器,结合rviz使用,用于机器人运动及topic数据的3D显示,但不包含物理学引擎;Gazebo是全功能的3D物理模拟器,要用这个模拟器,需要掂量掂量你的主机的内存和显卡是否够用。

本文是入门文章,我们就从turtlesim开始。假设此时roscore已经启动了。

我们来启动一下turtlesim_node:

# rosrun turtlesim turtlesim_node
[ INFO] [1501549501.410816841]: Starting turtlesim with node name /turtlesim
[ INFO] [1501549501.428589492]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

这时你的desktop会出现一个新的窗口,如下图:

img{512x368}

不过此时小海龟一动不动!如果要让它移动,我们需要告诉他如何移动!

我们启动另外一个node – turtle_teleop_key:

# rosrun turtlesim turtle_teleop_key
Reading from keyboard
---------------------------
Use arrow keys to move the turtle.

通过turtle_teleop_key,我们可以使用方向键控制小海龟的移动了:

img{512x368}

其原理在于:turtle_teleop_key将方向键产生的数据转换为位置信息后,发布到topic: /turtle1/cmd_vel上;turtlesim_node由于subscribe了该topic,因此将接收到新的位置数据,这样小海龟就会移动到新的位置上去:

img{512x368}

turtlesim node启动后还启动了一个service: spawn,调用该服务我们可以在窗口上创建出一个新的小海龟:

# rosservice call /spawn 2 2 0.2 ""
name: turtle2

img{512x368}

可以看到,通过service调用或向topic发布数据,我们可以自由控制小海龟。下面的是一个稍微复杂的控制指令,其结果就是让小海龟1进行持续的转圈动作:

rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'

img{512x368}

五、创建你的第一个ROS package

现在我们来创建第一个ROS package!

1、初始化ros workspace

我们要添加自己的ROS package,一般不会直接在ROS的安装目录下创建,因此我们需要创建自己的workspace,并在后续将其加入到ROS_PACKAGE_PATH中,以使得ros的文件系统命令也能适用于我们自己的workspace路径。

# mkdir -p ~/myros_ws/src
# cd ~/myros_ws/src
# catkin_init_workspace
Creating symlink "/home/tonybai/myros_ws/src/CMakeLists.txt" pointing to "/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake"

$ tree ~/myros_ws/
/home/tonybai/myros_ws/
└── src
    └── CMakeLists.txt -> /opt/ros/kinetic/share/catkin/cmake/toplevel.cmake

1 directory, 1 file

2、创建Package

我们来创建一个我们自己的package – chattingsim:

# cd ~/myros_ws/src
# catkin_create_pkg chattingsim std_msgs rospy roscpp
Created file chattingsim/package.xml
Created file chattingsim/CMakeLists.txt
Created folder chattingsim/include/chattingsim
Created folder chattingsim/src
Successfully created files in /home/tonybai/myros_ws/src/chattingsim. Please adjust the values in package.xml.

# tree chattingsim/
chattingsim/
├── CMakeLists.txt
├── include
│   └── chattingsim
├── package.xml
└── src

3 directories, 2 files

虽然目前我们的chattingsim package并没有任何有意义的代码,但不妨碍我们先来编译一下myros_ws这个workspace:

# cd ~/myros_ws/
# catkin_make

# catkin_make
Base path: /home/tonybai/myros_ws
Source space: /home/tonybai/myros_ws/src
Build space: /home/tonybai/myros_ws/build
Devel space: /home/tonybai/myros_ws/devel
Install space: /home/tonybai/myros_ws/install
####
#### Running command: "cmake /home/tonybai/myros_ws/src -DCATKIN_DEVEL_PREFIX=/home/tonybai/myros_ws/devel -DCMAKE_INSTALL_PREFIX=/home/tonybai/myros_ws/install -G Unix Makefiles" in "/home/tonybai/myros_ws/build"
####
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
... ...
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found gtest sources under '/usr/src/gtest': gtests will be built
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.6
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - chattingsim
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'chattingsim'
-- ==> add_subdirectory(chattingsim)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tonybai/myros_ws/build
####
#### Running command: "make -j4 -l4" in "/home/tonybai/myros_ws/build"
####

catkin_make后,myros_ws下面又增加了不少目录和文件:

~/myros_ws$ tree -L 2
.
├── build
│   ├── catkin
│   ├── catkin_generated
│   ├── CATKIN_IGNORE
│   ├── catkin_make.cache
│   ├── chattingsim
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── CTestTestfile.cmake
│   ├── gtest
│   ├── Makefile
│   └── test_results
├── devel
│   ├── env.sh
│   ├── lib
│   ├── setup.bash
│   ├── setup.sh
│   ├── _setup_util.py
│   ├── setup.zsh
│   └── share
└── src
    ├── chattingsim
    └── CMakeLists.txt -> /opt/ros/kinetic/share/catkin/cmake/toplevel.cmake

12 directories, 12 files

我们看到~/myros_ws/devel目录下的结构与/opt/ros/kinetic下的非常相似,我们将其加入到ROS_PACKAGE_PATH:

# cd ~/myros_ws/devel
# source ./setup.bash
# echo $ROS_PACKAGE_PATH
/home/tonybai/myros_ws/src:/opt/ros/kinetic/share

3、添加talker和listener

chattingsim package的架子已经搭好,接下来我们开始“填肉”。这里我们直接使用ros tutorials中写好的两个源文件talker.cpplistener.cpp,我们把这两个文件放在~/myros_ws/src/chattingsim/src下面。

在build之前,我们需要修改一下chattingsim的CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.3)
project(chattingsim)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  genmsg
)

generate_messages(DEPENDENCIES std_msgs)

include_directories(
  include ${catkin_INCLUDE_DIRS}
)

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker chattingsim_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener chattingsim_generate_messages_cpp)

构建chattingsim package:

~/myros_ws# catkin_make
Base path: /home/tonybai/myros_ws
Source space: /home/tonybai/myros_ws/src
Build space: /home/tonybai/myros_ws/build
Devel space: /home/tonybai/myros_ws/devel
Install space: /home/tonybai/myros_ws/install
####
#### Running command: "make cmake_check_build_system" in "/home/tonybai/myros_ws/build"
####
####
#### Running command: "make -j4 -l4" in "/home/tonybai/myros_ws/build"
####
[  0%] Built target std_msgs_generate_messages_eus
[  0%] Built target std_msgs_generate_messages_cpp
[  0%] Built target std_msgs_generate_messages_lisp
[  0%] Built target std_msgs_generate_messages_py
[  0%] Built target std_msgs_generate_messages_nodejs
[  0%] Built target chattingsim_generate_messages_cpp
[  0%] Built target chattingsim_generate_messages_lisp
[ 14%] Generating EusLisp manifest code for chattingsim
[ 28%] Building CXX object chattingsim/CMakeFiles/talker.dir/src/talker.cpp.o
[ 28%] Built target chattingsim_generate_messages_nodejs
[ 42%] Generating Python msg __init__.py for chattingsim
[ 57%] Generating Python srv __init__.py for chattingsim
[ 71%] Building CXX object chattingsim/CMakeFiles/listener.dir/src/listener.cpp.o
[ 71%] Built target chattingsim_generate_messages_py
[ 71%] Built target chattingsim_generate_messages_eus
[ 71%] Built target chattingsim_generate_messages
[ 85%] Linking CXX executable /home/tonybai/myros_ws/devel/lib/chattingsim/talker
[ 85%] Built target talker
[100%] Linking CXX executable /home/tonybai/myros_ws/devel/lib/chattingsim/listener
[100%] Built target listener

4、启动chattingsim的talker node和listener node

在两个terminal窗口分别启动listener node和talker node:

# rosrun chattingsim listener
[ INFO] [1501577165.148477238]: I heard: [hello world 3]
[ INFO] [1501577165.248349227]: I heard: [hello world 4]
[ INFO] [1501577165.348301478]: I heard: [hello world 5]
[ INFO] [1501577165.448340592]: I heard: [hello world 6]
[ INFO] [1501577165.548433696]: I heard: [hello world 7]
[ INFO] [1501577165.648466054]: I heard: [hello world 8]
[ INFO] [1501577165.748424131]: I heard: [hello world 9]
[ INFO] [1501577165.848457076]: I heard: [hello world 10]
[ INFO] [1501577165.948449431]: I heard: [hello world 11]
[ INFO] [1501577166.048470110]: I heard: [hello world 12]
[ INFO] [1501577166.148340964]: I heard: [hello world 13]

# rosrun chattingsim talker
[ INFO] [1501577164.847745179]: hello world 0
[ INFO] [1501577164.947898377]: hello world 1
[ INFO] [1501577165.047889213]: hello world 2
[ INFO] [1501577165.147882701]: hello world 3
[ INFO] [1501577165.247923700]: hello world 4
[ INFO] [1501577165.347918242]: hello world 5
[ INFO] [1501577165.447917169]: hello world 6
[ INFO] [1501577165.547916593]: hello world 7
[ INFO] [1501577165.647920474]: hello world 8
[ INFO] [1501577165.747930882]: hello world 9
[ INFO] [1501577165.847917356]: hello world 10
[ INFO] [1501577165.947918365]: hello world 11
[ INFO] [1501577166.047918187]: hello world 12
[ INFO] [1501577166.147919712]: hello world 13
^C[ INFO] [1501577166.247984284]: hello world 14

至此,基于我们第一个package: chattingsim而创建的node工作正常!

六、小结

如果说人工智能的算法是大脑,实体的机械部件构成四肢,那么ROS则提供了大脑与各肢体间提供了神经传递的机制。之前ROS在国内发展的不瘟不火,随着Baidu Apollo项目将ros作为Apollo-platform支持的一部分,更多人会去了解ROS,ROS在国内的发展势也许会走得更顺畅一些。ROSCon 2017也即将于下月在加拿大温哥华召开,ROS2对ROS1的安全性和实时性的加强也势必会让ROS有更多用武之地,值得期待。

注:ros wiki 资料非常详尽,ros tutorial是学习ros的起点,几乎不用任何其他书籍。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats