Chapter 2. ROS 创建和编译功能包

1. 创建ROS功能包

使用catkin_create_pkg命令来创建一个新的catkin程序包。
首先切换到之前通过创建catkin工作空间教程创建的catkin工作空间中的src目录下:

~/ros_workspace$ cd src

接着使用catkin_create_pkg命令来创建一个名为’beginner_tutorials’的新程序包,这个程序包依赖于std_msgs、roscpp和rospy:

~/ros_workspace/src$ catkin_create_pkg my_demo roscpp rospy std_msgs

创建成功后,提示如下:

Created file my_demo/package.xml
Created file my_demo/CMakeLists.txt
Created folder my_demo/include/my_demo
Created folder my_demo/src
Successfully created files in /home/nic/ros_workspace/src/my_demo. Please adjust the values in package.xml.

这将会创建一个名为my_demo的文件夹,这个文件夹里面包含一个package.xml文件和一个CMakeLists.txt文件,这两个文件都已经自动包含了部分你在执行catkin_create_pkg命令时提供的信息。

catkin_create_pkg命令会要求你输入package_name,如果有需要你还可以在后面添加一些需要依赖的其它程序包:

# This is an example, do not try to run this
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]

catkin_create_pkg命令也有更多的高级功能,这些功能在catkin/commands/catkin_create_pkg中有描述。

2. 编译ROS功能包

采用CLion开发环境进行编译

CLion的安装及破解请参照此文

(1)创建节点 my_demo
~/ros_workspace/src/my_demo/src$ gedit my_demo.cpp

将一下示例代码复制到my_demo.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)%
(2)配置CLion快捷方式

进入CLion快捷方式所在的目录:

~$ cd /usr/share/applications

打开并编辑快捷方式:

/usr/share/applications$ sudo gedit jetbrains-clion.desktop

按照如下所示修改:

Exec=bash -i -c "/opt/clion-2018.1.6/bin/clion.sh" %f

重新注销系统使之生效。

(3)加载功能包

运行CLion,打开功能包下的CMakeList.txt文件,并作为工程打开,如图:
这里写图片描述

(4)编译节点并运行

打开功能包工程如图,编辑CMakeList.txt文件:

add_executable(my_demo src/my_demo.cpp)
target_link_libraries(my_demo ${catkin_LIBRARIES})

这里写图片描述

点击调试按钮,提示如下:
这里写图片描述

打开新的终端,输入:

~$ roscore

这里写图片描述

在CLion环境中,显示如下:
这里写图片描述

新建一个终端查看执行结果:
这里写图片描述

3. 创建ROS功能包并利用CLion进行编译,至此成功完成!

补充说明

如果采用标准版的QtCreator进行编译,请按以下步骤进行:

a. 参照前面,创建节点 demo_node
b. 设置QtCreator能够在启动时候添加ros环境

查找QtCreator的快捷方式

修改QtCreator的快捷方式

在Exec=处加上 bash -i -c
这里写图片描述
重启QtCreator。

c. 打开QtCreator,通过OpenProject打开工作空间下的CMakeLists.txt文件

这里写图片描述

d. 配置项目

这里写图片描述

e. 修改package中CMakeLists.txt的内容

这里写图片描述

d. 运行结果

这里写图片描述
这里写图片描述

<think>好的,我需要帮助用户了解如何创建编译ROS功能。首先,我应该回忆ROS的基本操作步骤。记得创建功能需要使用`catkin_create_pkg`命令,但用户提供的引用中提到了ROS2,所以可能需要区分ROS1ROS2的不同。引用[1]中提到在Windows下编译ROS2,涉及CMakePython的安装,而引用[2]则是在Linux环境下配置Qt编译功能。这说明用户可能同时接触ROS1ROS2,或者有跨平台的需求。 接下来,我需要明确创建功能的具体步骤。对于ROS1,通常是在工作空间的src目录下使用`catkin_create_pkg`,而ROS2使用的是`ros2 pkg create`命令。用户的问题没有明确指定版本,但引用中提到了ROS2,所以可能需要侧重ROS2的流程。同时,用户可能也需要了解ROS1的方法,所以可能需要分开说明。 然后,编译步骤在ROS1中使用`catkin_make`,而在ROS2中使用`colcon build`。需要指出这些差异,并确保用户正确设置环境变量,如引用[1]中提到的CMake路径添加到PATH,以及Python版本的正确安装。另外,引用[2]中关于Qt的环境变量配置可能涉及到功能依赖的库,比如rviz或GUI工具,可能需要安装相关依赖。 还需要考虑依赖管理,比如在package.xml中添加依赖项,以及在CMakeLists.txt中配置编译选项。用户可能需要知道如何添加编译时的依赖运行时的依赖,以及如何链接库生成可执行文件。 可能遇到的问题括环境变量未正确设置,依赖未安装导致编译失败,或者工作空间结构不正确。需要提醒用户检查这些方面,并参考官方文档或提供的引用链接进行故障排除。 最后,生成相关问题时,应该围绕创建编译功能的扩展知识,如依赖管理、工作空间结构、调试方法、跨平台编译等,帮助用户进一步深入学习。</think>### 创建编译ROS功能教程 #### 一、创建ROS功能 1. **准备工作环境** - 确保已安装ROS环境(ROS1或ROS2)并初始化工作空间。 - ROS1示例: ```bash mkdir -p ~/catkin_ws/src cd ~/catkin_ws/ catkin_make source devel/setup.bash ``` - ROS2示例: ```bash mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build source install/setup.bash ``` 2. **创建功能** - **ROS1**使用`catkin_create_pkg`: ```bash cd ~/catkin_ws/src catkin_create_pkg <名> [依赖项] # 例如: catkin_create_pkg my_pkg roscpp std_msgs ``` - **ROS2**使用`ros2 pkg create`: ```bash cd ~/ros2_ws/src ros2 pkg create --build-type ament_cmake <名> # 或 ament_python ``` 若需添加依赖,使用`--dependencies`参数,例如: ```bash ros2 pkg create --build-type ament_cmake my_pkg --dependencies rclcpp std_msgs ``` #### 二、编译功能 1. **ROS1编译流程** - 使用`catkin_make`: ```bash cd ~/catkin_ws catkin_make ``` - 若需单独编译指定: ```bash catkin_make --pkg <名> ``` 2. **ROS2编译流程** - 使用`colcon build`: ```bash cd ~/ros2_ws colcon build --packages-select <名> # 仅编译指定 ``` - 编译后需更新环境变量: ```bash source install/setup.bash ``` 3. **依赖与环境配置** - 确保所有依赖项已安装(如Python版本、CMake路径等)。 例如,Windows下需将CMake路径`C:\Program Files\CMake\bin`添加到系统环境变量[^1]。 - 若涉及图形工具(如Qt),需配置环境变量: ```bash export QT_HOME=/path/to/QtCreator/bin # 如引用[2]中的示例[^2] ``` #### 三、验证功能 1. **ROS1验证** ```bash roscd <名> # 进入目录 rospack depends1 <名> # 查看直接依赖 ``` 2. **ROS2验证** ```bash ros2 pkg executables # 列出所有可执行文件 ros2 run <名> <节点名> # 运行节点 ``` --- ### 常见问题解决 1. **编译失败** - 检查`package.xml``CMakeLists.txt`中的依赖项是否完整。 - 确保Python版本符合要求(如引用[1]中指定Python 3.8.3)[^1]。 2. **环境变量未生效** - 重新执行`source`命令或重启终端。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值