【ROS学习二】创建编译自己的功能包
一、准备
需要在电脑上事先安装好ROS
二、创建工作区间
ROS不同于其他软件,需要在特定的工作区间下通过ros编译运行自己的程序。
假设电脑上已经安装好ROS,则
$ source /opt/ros/kinetic/setup.bash (ros安装的路径)
//echo $ROS_PACKAGE_PATH 查看包的路径
//创建和编译一个 catkin workspace
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make
在执行完上述操作后,会在~/目录下,生成catkin_ws文件夹,~/catkin_ws/src下有一个CMakeLists.txt。
文件解说:src文件夹存放自己的源码、cmakelist等文件,devel中有.sh文件
程序编译完后,会在devel/lib/xxx中产生可执行文件,为执行可执行文件,source devel/setup.bash(只执行完代码框里的命令,并不会产生可执行文件,需要自己加入)
三、加入自己的代码
在创建完工作区间后,接下来我们加入自己的代码.
1.在/home/ning/catkin_ws/src路径下打开终端
ning@ning:~/catkin_ws/src$ pwd /home/ning/catkin_ws/src ning@ning:~/catkin_ws/src$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp //catkin_create_pkg 是创建包的命令 beginner_tutorials是包的名称 std_msgs rospy roscpp 是创建这个包所需要的库 Created file beginner_tutorials/package.xml Created file beginner_tutorials/CMakeLists.txt Successfully created files in /home/ning/catkin_ws/src/beginner_tutorials. Please adjust the values in package.xml.
就可以看到/home/ning/catkin_ws/src下有一个新的文件夹beginner_tutorials,里面有两个文件cmakelist.txt与package.xml
2.将自己的代码复制粘帖到/home/ning/catkin_ws/src/beginner_tutorials/src路径下
程序例子
beginner_tutorials.cpp
/* * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ // %Tag(FULLTEXT)% // %Tag(ROS_HEADER)% #include "ros/ros.h" // %EndTag(ROS_HEADER)% // %Tag(MSG_HEADER)% #include "std_msgs/String.h" // %EndTag(MSG_HEADER)% #include <sstream> /** * This tutorial demonstrates simple sending of messages over the ROS system. */ 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. */ // %Tag(INIT)% ros::init(argc, argv, "talker"); // %EndTag(INIT)% /** * 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. */ // %Tag(NODEHANDLE)% ros::NodeHandle n; // %EndTag(NODEHANDLE)% /** * The advertise() function is how you tell ROS that you want to * publish on a given topic name. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. After this advertise() call is made, the master * node will notify anyone who is trying to subscribe to this topic name, * and they will in turn negotiate a peer-to-peer connection with this * node. advertise() returns a Publisher object which allows you to * publish messages on that topic through a call to publish(). Once * all copies of the returned Publisher object are destroyed, the topic * will be automatically unadvertised. * * The second parameter to advertise() is the size of the message queue * used for publishing messages. If messages are published more quickly * than we can send them, the number here specifies how many messages to * buffer up before throwing some away. */ // %Tag(PUBLISHER)% ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); // %EndTag(PUBLISHER)% // %Tag(LOOP_RATE)% ros::Rate loop_rate(10); // %EndTag(LOOP_RATE)% /** * A count of how many messages we have sent. This is used to create * a unique string for each message. */ // %Tag(ROS_OK)% int count = 0; while (ros::ok()) { // %EndTag(ROS_OK)% /** * This is a message object. You stuff it with data, and then publish it. */ // %Tag(FILL_MESSAGE)% std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str(); // %EndTag(FILL_MESSAGE)% // %Tag(ROSCONSOLE)% ROS_INFO("%s", msg.data.c_str()); // %EndTag(ROSCONSOLE)% /** * The publish() function is how you send messages. The parameter * is the message object. The type of this object must agree with the type * given as a template parameter to the advertise<>() call, as was done * in the constructor above. */ // %Tag(PUBLISH)% chatter_pub.publish(msg); // %EndTag(PUBLISH)% // %Tag(SPINONCE)% ros::spinOnce(); // %EndTag(SPINONCE)% // %Tag(RATE_SLEEP)% loop_rate.sleep(); // %EndTag(RATE_SLEEP)% ++count; } return 0; } // %EndTag(FULLTEXT)%
3.修改CMakeLists.txt文件
我们要对他修改下,修改完之后就变成
cmake_minimum_required(VERSION 3.0.2) project(beginner_tutorials) SET(CMAKE_CXX_FLAGS "-std=c++11") find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs ) find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs) #此处为编译自己的cpp需要的库 include_directories( # include ${catkin_INCLUDE_DIRS} ) add_executable(beginner_tutorials src/beginner_tutorials.cpp) # 加入自己的程序cpp文件 add_dependencies(beginner_tutorials ${catkin_EXPORTED_TARGETS} ) target_link_libraries(beginner_tutorials ${catkin_LIBRARIES})
4.检查修改package.xml文件
使用gedit或者其他的编辑器打开package.xml文件,检查一下工程名字是否正确,链接的库是否齐全等
<?xml version="1.0"?> <package format="2"> <name>beginner_tutorials</name> <version>0.0.0</version> <description>The beginner_tutorials package</description> <!-- One maintainer tag required, multiple allowed, one person per tag --> <!-- Example: --> <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> <maintainer email="ubuntu@todo.todo">ubuntu</maintainer> <!-- One license tag required, multiple allowed, one license per tag --> <!-- Commonly used license strings: --> <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> <license>TODO</license> <!-- Url tags are optional, but multiple are allowed, one per tag --> <!-- Optional attribute type can be: website, bugtracker, or repository --> <!-- Example: --> <!-- <url type="website">http://wiki.ros.org/beginner_tutorials</url> --> <!-- Author tags are optional, multiple are allowed, one per tag --> <!-- Authors do not have to be maintainers, but could be --> <!-- Example: --> <!-- <author email="jane.doe@example.com">Jane Doe</author> --> <!-- The *depend tags are used to specify dependencies --> <!-- Dependencies can be catkin packages or system dependencies --> <!-- Examples: --> <!-- Use depend as a shortcut for packages that are both build and exec dependencies --> <!-- <depend>roscpp</depend> --> <!-- Note that this is equivalent to the following: --> <!-- <build_depend>roscpp</build_depend> --> <!-- <exec_depend>roscpp</exec_depend> --> <!-- Use build_depend for packages you need at compile time: --> <!-- <build_depend>message_generation</build_depend> --> <!-- Use build_export_depend for packages you need in order to build against this package: --> <!-- <build_export_depend>message_generation</build_export_depend> --> <!-- Use buildtool_depend for build tool packages: --> <!-- <buildtool_depend>catkin</buildtool_depend> --> <!-- Use exec_depend for packages you need at runtime: --> <!-- <exec_depend>message_runtime</exec_depend> --> <!-- Use test_depend for packages you need only for testing: --> <!-- <test_depend>gtest</test_depend> --> <!-- Use doc_depend for packages you need only for building documentation: --> <!-- <doc_depend>doxygen</doc_depend> --> <buildtool_depend>catkin</buildtool_depend> <build_depend>roscpp</build_depend> <build_depend>rospy</build_depend> <build_depend>std_msgs</build_depend> <build_export_depend>roscpp</build_export_depend> <build_export_depend>rospy</build_export_depend> <build_export_depend>std_msgs</build_export_depend> <exec_depend>roscpp</exec_depend> <exec_depend>rospy</exec_depend> <exec_depend>std_msgs</exec_depend> <!-- The export tag contains other, unspecified, tags --> <export> <!-- Other tools can request additional information be placed here --> </export> </package>
四、编译
进入~/catkin_ws文件夹,打开终端执行命令catkin_make
五、运行
1.新建第一个终端
roscore//如果遇到为找到命令的错误,可以尝试运行source /opt/ros/kinetic/setup.bash (ros安装的路径)
2.新建第二个终端
cd ~/catkin_ws
source devel/setup.bash
build目录下功能包里有可运行程序,直接运行
cd build/beginner_tutorials
./beginner_tutorials
3、新打开一个终端
rostopic list
查看运行的话题topic,程序创建的话题chatter也在列表里