Linux学习笔记(四)Ubantu16.04下安装ROS系统及helloworldDemo

1、什么是ROS?

机器人开发是一门综合学科,须要用到各方面知识,包括且不限于计算机,数学和物理等各个领域。因其综合程度高使其开发较为繁琐且困难,ROS的出现大大简单了机器人开发的门槛,ROS全称Robot Operating System ,本质上是一个分布式系统架构,提供标准的通信结构,实现功能的集成。
机器人开发的通常流程为:目标设计,构建框架,功能开发,总体优化,实体验证,该流程并不是顺序执行,更多的是循环和回溯。html

引用原文连接:
一、《机器人控制系统(一)前期准备》
二、创客智造–讲解ros系列node

2、Ubantu16.04LTS安装ROS桌面版

参考教程:
ROS入门——Ubuntu安装ROS
ubuntu16.04环境下安装ros:
参考一 | 参考二python

(一)准备工做

个人环境(VM VirtualBOX+ubantu16.04)
在这里插入图片描述c++

  1. 配置国内镜像源(可选,也能够跳过这一步)
  • 方法一 直接修改教程:点击软件存储库配置文件/etc/apt/sources.list文件
    在这里插入图片描述
    (单独添加源,可选步骤)其余-》APT添加deb http://ros.exbot.net/rospackage/ros/ubuntu/ xenial main
    在这里插入图片描述
  • 方法二 代码修改镜像源:(参考教程点这儿
sudo gedit /etc/apt/sources.list

须要输入root密码,而后修改成阿里或者中科大等镜像源:web

deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties  
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted  
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties  
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted  
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties  
deb http://mirrors.aliyun.com/ubuntu/ xenial universe  
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe  
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse  
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse  
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse  
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties  
deb http://archive.canonical.com/ubuntu xenial partner  
deb-src http://archive.canonical.com/ubuntu xenial partner  
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted  
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties  
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe  
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
  • 确认更新
sudo apt-get update

1
在这里插入图片描述

  1. 设置Ubuntu的sources.list;添加key。(重要步骤,若是不成功能够看看前面的教程,或者到官网看一下网址和秘钥是否更新)
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 0xB01FA116

在这里插入图片描述

  1. 更新(重要)
sudo apt-get update
sudo apt-get upgrade

在这里插入图片描述
在这里插入图片描述
这里碰见了一个问题,我这里跳过未解决,后面补充:(–fix missing这里有提示)
在这里插入图片描述shell

(我我的虚拟机更新环境花费了半小时,必须保证Deban系统达到最新~)ubuntu

(二)Ubantu16.04安装ROS桌面版

  1. 安装ROS kinetic完整版(下载半小时,解析5分钟)
sudo apt-get install ros-kinetic-desktop-full

在这里插入图片描述

  1. 查看可以使用的包:(可选)
apt-cache search ros-kinetic
  1. 初始化ROS系统(重要)
sudo rosdep init

碰见问题:
在这里插入图片描述
可能就是以前那个问题没解决:api

sudo apt-get update --fix-missingbash

在这里插入图片描述
初始化完成架构

  1. 确认ros系统更新(重要)
rosdep update

在这里插入图片描述
5. 初始化环境,不然每次启动都须要source一次(虽然我也这样作了,但是后面我运行前,仍是得source发布一下,暂不知缘由)

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

在这里插入图片描述
6. 安装额外依赖包

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

在这里插入图片描述
7. 测试

  • 启动ROSmaster,相似于给ROS操做系统开机(Ctrl+c退出)
roscore

在这里插入图片描述

  • 启动turtlesim并监听turtlesim_node发来的消息
    注意: 要在开一个终端:
rosrun turtlesim turtlesim_node

在这里插入图片描述
若如图出现小乌龟,则安装成功!

  1. ROS控制小乌龟运动轨迹测试
    注意 : 是三个控制台,第三个控制台的做用是获取键盘上下左右键控制小乌龟前进方向的信息:
roscore 
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key

在这里插入图片描述

(三)配置工做目录和环境

参考教程:
一、ros 编写 helloworld 程序:https://blog.csdn.net/mxgsgtc/article/details/71450763/
二、ROS中 helloworld 的实现(详细版):https://blog.csdn.net/QFJIZHI/article/details/82978447

  1. 在根目录下建立工做空间/catkin_ws,并建立src目录,为这个空间设置配置文件:
cd /opt/ros/kinetic/
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace

在这里插入图片描述
这时候会自动新建一个CMakeLists.txt文件
在这里插入图片描述

  1. 将ros用户本身的工程目录配置到bash里
sudo gedit ~/.bashrc

在其最后一行加入

export ROS_PACKAGE_PATH=~/catkin_ws:$ROS_PACKAGE_PATH

在这里插入图片描述

  1. 编译工程
cd ~/catkin_ws/
catkin_make

在这里插入图片描述
在这里插入图片描述
4. 将catkin_make加入到shell里

source devel/setup.bash
echo $ROS_PACKAGE_PATH

在这里插入图片描述

3、ROS编写helloword程序(C++版)

(一)建立第一个ros项目

一个简单的helloworldDemo

  1. catkin_ws/src包下建立咱们的项目beginner_tutorials
catkin_create_pkg beginner_tutorials

在这里插入图片描述
2. 进入项目目录,再新建src包

cd beginner_tutorials/
mkdir src

这里作一个强调和区分:catkin_ws是咱们的 工做空间workspace ,至关于IDEA,catkin_ws/src是放置工做空间的项目目录;beginner_tutorials是咱们的 项目名称 ,beginner_tutorials/src是咱们项目源文件.cpp存储的位置。

  1. 在beginner_tutorials/src文件夹中建立hello.cpp文件,并修改文件内容:
cd /src
touch hello.cpp
sudo gedit hello.cpp

hello.cpp内容为如下:

#include<ros/ros.h>
int main(int argc,char **argv){   
ros::init(argc,argv,"hello_ros");   
ros::NodeHandle nh;   
ROS_INFO_STREAM("helloworld,ROS!");
}

在这里插入图片描述
4. 修改CMakeLists.txt文件(项目配置文件)
退回到cd beginner_tutorials/文件夹中,修改CMakeLists.txt文件,

sudo gedit CMakeLists.txt

内容以下:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)
#添加须要的依赖库 roscpp
find_package(catkin REQUIRED COMPONENTS roscpp)
include_directories(
${catkin_INCLUDE_DIRS}
)
#声明想要的可执行文件的文件名,以及所须要的源列表,若是有多个源列表,空格列在此处
add_executable(hello src/hello.cpp)
#告诉Cmake当连接此可执行文件时须要连接哪些库
target_link_libraries(hello ${catkin_LIBRARIES})

在这里插入图片描述
5. 修改package.xml文件

sudo gedit package.xml

此处只需在 <buildtool_depend>catkin</buildtool_depend>后面添加两句便可

<build_depend>roscpp</build_depend>
 <exec_depend>roscpp</exec_depend>

在这里插入图片描述

  1. 回到编译工做区(workspace目录,catkin_make是ROS系统专用命令执行语句)
cd ~/catkin_ws
catkin_make

在这里插入图片描述
不出意外的话,在catkin_ws/devel/lib/beginner_tutorials/目录下会生成hello可执行文件在这里插入图片描述

  1. 设置环境变量并运行
    (必须先程序注册)
source devel/setup.bash

一个终端:

roscore

另外一个终端:

rosrun beginner_tutorials hello

运行结果如图:
在这里插入图片描述

(二)进阶talker.cpp和listener.cpp交互helloworldDemo

参考教程:
ROS学习笔记(一):本身动手写一个ROS程序:
https://blog.csdn.net/zouyu1746430162/article/details/70053811

与前面同理,

  1. beginner_tutorials/src目录下分别建立talker.cpp和listener.cpp
cd ~/catkin_ws/src/beginner_tutorials/src
sudo gedit talker.cpp
#源码见文末附录
sudo gedit listener.cpp
#附录
  1. 修改/beginner_tutorials/CMakeList.txt内容

【源码见附录】

  1. 回到~/catkin_ws/工做空间下catkin_make生成talker和listen的可执行程序
cd ~/catkin_ws/
catkin_make

在这里插入图片描述

  1. 运行测试时总共须要三个命令行终端
    • 打开ros服务 : 一个终端运行roscore
    • 运行talker : 另外一个终端先注册程序source devel/setup.bash再运行rosrun beginner_tutorials talker
    • 运行listener : 另外一个先注册程序【同上】再运行rosrun beginner_tutorials listener

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


附:
Hello.cpp:

#include<ros/ros.h>
 
int main(int argc,char **argv){   
 
ros::init(argc,argv,"hello_ros");   
 
ros::NodeHandle nh;   
 
ROS_INFO_STREAM("helloworld,ROS!");
 
}

Talker.cpp:

#include<ros/ros.h>
#include<std_msgs/String.h>
 
/** * This tutorial demonstrates simple receipt of messages over the ROS system. */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}
 
int main(int argc, char **argv)
{
  /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */
  ros::init(argc, argv, "listener");
 
  /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */
  ros::NodeHandle n;
 
  /** * The subscribe() call is how you tell ROS that you want to receive messages * on a given topic. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. Messages are passed to a callback function, here * called chatterCallback. subscribe() returns a Subscriber object that you * must hold on to until you want to unsubscribe. When all copies of the Subscriber * object go out of scope, this callback will automatically be unsubscribed from * this topic. * * The second parameter to the subscribe() function is the size of the message * queue. If messages are arriving faster than they are being processed, this * is the number of messages that will be buffered up before beginning to throw * away the oldest ones. */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
 
  /** * ros::spin() will enter a loop, pumping callbacks. With this version, all * callbacks will be called from within this thread (the main one). ros::spin() * will exit when Ctrl-C is pressed, or the node is shutdown by the master. */
  ros::spin();
 
  return 0;
}

Listener.cpp:

#include<ros/ros.h>
#include<std_msgs/String.h>
 
/** * This tutorial demonstrates simple receipt of messages over the ROS system. */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}
 
int main(int argc, char **argv)
{
  /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */
  ros::init(argc, argv, "listener");
 
  /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */
  ros::NodeHandle n;
 
  /** * The subscribe() call is how you tell ROS that you want to receive messages * on a given topic. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. Messages are passed to a callback function, here * called chatterCallback. subscribe() returns a Subscriber object that you * must hold on to until you want to unsubscribe. When all copies of the Subscriber * object go out of scope, this callback will automatically be unsubscribed from * this topic. * * The second parameter to the subscribe() function is the size of the message * queue. If messages are arriving faster than they are being processed, this * is the number of messages that will be buffered up before beginning to throw * away the oldest ones. */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
 
  /** * ros::spin() will enter a loop, pumping callbacks. With this version, all * callbacks will be called from within this thread (the main one). ros::spin() * will exit when Ctrl-C is pressed, or the node is shutdown by the master. */
  ros::spin();
 
  return 0;
}

CMakeList.txt:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs # Or other packages containing msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
# cfg/DynReconf1.cfg
# cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES beginner_tutorials
# CATKIN_DEPENDS other_catkin_pkg
# DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
# ${catkin_INCLUDE_DIRS}
${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/beginner_tutorials.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/beginner_tutorials_node.cpp)

#声明想要的可执行文件的文件名,以及所须要的源列表,若是有多个源列表,空格列在此处
add_executable(hello src/hello.cpp)
#告诉Cmake当连接此可执行文件时须要连接哪些库
target_link_libraries(hello ${catkin_LIBRARIES})

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})


## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_beginner_tutorials.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
  
add_executable(talker src/talker.cpp)  
target_link_libraries(talker ${catkin_LIBRARIES})  
add_dependencies(talker beginner_tutorials_generate_messages_cpp)  
  
add_executable(listener src/listener.cpp)  
target_link_libraries(listener ${catkin_LIBRARIES})  
add_dependencies(listener beginner_tutorials_generate_messages_cpp)