SLAM从入门到精通(编写第一个package)

news2025/1/12 18:16:07

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        前面我们安装了ROS环境,接着就可以开始进行ROS程序的开发了。在开发之前,我们有几个概念需要厘清一下。第一个是workspace,它相当于一个项目。毕竟,一个电脑上面可以有很多的workspace,也就相当于有很多的项目。第二个是package,它相当于功能块,功能块里面可以有很多的程序,package本身就是很多程序的一个集合。第三个就是node,直接把它看成独立的程序就可以了。

1、创建workspace

        创建工作区是所有工作的第一步。可以通过创建workspace下面src目录的方法,直接进行创建,

mkdir -p ./catkin_ws/src

2、编译workspace

        创建完成之后,就可以直接编译了。这个时候虽然什么也没有,但是catkin_make命令会帮我们自动创建build和dev这两个目录,

cd ./catkin_ws
catkin_make

3、创建package

        有了工作区,就可以开始创建工作包了。工作包的创建方法也不复杂,主要使用catkin_create_pkg命令即可,前提是先进入src目录,

cd ./catkin_ws/src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

4、开始准备代码talker.cpp & listener.cpp

        package里面也是有src目录的,虽然有点绕,这个我们可以稍微花点时间理解一下。现在假设有两个程序,一个是talker.cpp,一个是listener.cpp,他们都是放在package的src目录里面。所以第一步,先进入package里面的src目录,即,

./catkin_ws/src/beginner_tutorials/src

        准备talker.cpp文件,

#include "ros/ros.h"
#include "std_msgs/String.h"

#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.
   */
  ros::init(argc, argv, "talker");

  /**
   * 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 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.
   */
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  /**
   * A count of how many messages we have sent. This is used to create
   * a unique string for each message.
   */
  int count = 0;
  while (ros::ok())
  {
    /**
     * This is a message object. You stuff it with data, and then publish it.
     */
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());

    /**
     * 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.
     */
    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }


  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;
}

5、修改CMakeLists.txt

        这里需要注意的是,相关的CMakeLists.txt文件不是src目录下面文件,而是package下面的文件。这一点很容易改错的。


cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
#add_message_files(FILES Num.msg)
#add_service_files(FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

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)

6、开始编译

        编译就非常简单了。需要回到workspace的目录,然后输入catkin_make就可以了,

cd ./catkin_ws
catkin_make

        不出意外的话,我们在./catkin_ws/devel/lib/beginner_tutorials看到对应的可执行文件。

7、启动程序

        启动程序需要三个步骤。第一个步骤,设置一下rosrun的环境,即,

source devel/setup.sh

        这样后期rosrun的时候,就可以直接启动node程序了。第二个步骤,输入roscore,这个相当于整个底层信息交换的大脑。第三个步骤,就是启动talker和listener了,

rosrun beginner_tutorials talker
rosrun beginner_tutorials listener

        所有操作都完成之后,我们就可以看到talker程序这边在不断发送消息,而listener这边在不断地接收消息。这是一个完整的publish和subscribe程序对。

        整个过程看上去自己要做的内容很少。这是因为ros已经帮助我们完成了大部分的工作,用ldd命令看下生成的程序就知道了,

feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/catkin_ws/devel/lib/beginner_tutorials$ ldd listener 
	linux-vdso.so.1 (0x00007ffeb4bfe000)
	libroscpp.so => /opt/ros/noetic/lib/libroscpp.so (0x00007f2381bc9000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2381b69000)
	librosconsole.so => /opt/ros/noetic/lib/librosconsole.so (0x00007f2381b06000)
	libroscpp_serialization.so => /opt/ros/noetic/lib/libroscpp_serialization.so (0x00007f2381b01000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f238191f000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f2381904000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2381710000)
	libxmlrpcpp.so => /opt/ros/noetic/lib/libxmlrpcpp.so (0x00007f23816ec000)
	librostime.so => /opt/ros/noetic/lib/librostime.so (0x00007f23816bf000)
	libcpp_common.so => /opt/ros/noetic/lib/libcpp_common.so (0x00007f23816b1000)
	libboost_thread.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_thread.so.1.71.0 (0x00007f2381685000)
	libboost_chrono.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_chrono.so.1.71.0 (0x00007f2381677000)
	libboost_filesystem.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_filesystem.so.1.71.0 (0x00007f2381657000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2381508000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2381db2000)
	librosconsole_log4cxx.so => /opt/ros/noetic/lib/librosconsole_log4cxx.so (0x00007f23814e8000)
	librosconsole_backend_interface.so => /opt/ros/noetic/lib/librosconsole_backend_interface.so (0x00007f23814e3000)
	liblog4cxx.so.10 => /lib/x86_64-linux-gnu/liblog4cxx.so.10 (0x00007f2381305000)
	libboost_regex.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_regex.so.1.71.0 (0x00007f2381205000)
	libconsole_bridge.so.0.4 => /lib/x86_64-linux-gnu/libconsole_bridge.so.0.4 (0x00007f23811fd000)
	libapr-1.so.0 => /lib/x86_64-linux-gnu/libapr-1.so.0 (0x00007f23811c4000)
	libaprutil-1.so.0 => /lib/x86_64-linux-gnu/libaprutil-1.so.0 (0x00007f2381196000)
	libicui18n.so.66 => /lib/x86_64-linux-gnu/libicui18n.so.66 (0x00007f2380e97000)
	libicuuc.so.66 => /lib/x86_64-linux-gnu/libicuuc.so.66 (0x00007f2380cb1000)
	libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f2380ca6000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2380ca0000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f2380c65000)
	libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f2380c37000)
	libicudata.so.66 => /lib/x86_64-linux-gnu/libicudata.so.66 (0x00007f237f176000)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/998945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux系统中LVM磁盘动态扩容方案

LVM动态扩展方案 信息确认&#xff1a; 磁盘空间确认 挂载磁盘的文件系统确认 lv卷组信息确认 1、确认磁盘已扩容&#xff1a;首先确认物理磁盘&#xff08;vdb&#xff09;已成功扩容至500G。 fdisk -l2、重新分区&#xff1a;将物理磁盘上多出的200G空间格式化为新的分区…

geopandas笔记:汇总连接两个区域的边

比如这样的两个区域&#xff0c;我们想知道从蓝到绿、从绿到蓝都有哪些边 1 读取openstreetmap import osmnx as ox import geopandas as gpdGox.graph_from_place(Singapore,simplifyTrue,network_typedrive)ox.plot_graph(G) 2 得到对应的边的信息 nodes,edgesox.graph_to_…

怎么在图片上编辑文字?这几种图片编辑工具了解下

在图片上编辑文字可以带来许多好处。首先&#xff0c;它可以更好地说明图片的内容和意义。有时候&#xff0c;一张图片可能不够清晰地传达想要表达的信息&#xff0c;但是通过在图片上添加文字说明&#xff0c;可以更好地让观众理解图片的意义。其次&#xff0c;编辑文字可以使…

AliExpress速卖通支付下单流程(测评补单优势及技术要点)

1. 打开全球速卖通官网,点击右上方的Join &#xff08;注册&#xff09;填写邮箱和密码&#xff0c;验证完毕后注册成功 2. 点击右上角的Account(账户)进入用户菜单 3. 点击导航了第一个My AliExpress&#xff08;我的速卖通&#xff09;选择左边My Shipping Address&#xff0…

VSCode自动分析代码的插件

今天来给大伙介绍一款非常好用的插件&#xff0c;它能够自动分析代码&#xff0c;并帮你完成代码的编写 效果如下图 首先我们用的是VSCode&#xff0c;&#xff08;免费随便下&#xff09; 找到扩展&#xff0c;搜索CodeGeeX&#xff0c;将它下载好&#xff0c;就可以实现了 到…

PathVariable注解

postman测试传参&#xff1a;http://localhost:8080/admin/employee/2 PathVariable PathVariable注解用法和作用

淘宝商品描述详细信息API接口

淘宝商品描述详细信息API接口是一个用于获取淘宝商品详细信息的API&#xff0c;通过它可以获取到商品的标题、价格、图片等信息。通过淘宝商品描述详细信息API接口&#xff0c;开发者可以方便地获取宝贝的相关信息&#xff0c;并将它们用于各种应用场景中。淘宝商品描述详细信息…

模板语言-Handlebars

Handlebars 是什么 Handlebars 是一种简单的模板语言。 它使用模板与传入的对象来生成HTML 或者其他文本格式。 Handlebars 模板看起来像是嵌入了handlebars 表达式的普通文本。 <p> {{firstname}} {{lastname}}</p> 一个handlebars表达式是使用两对尖括号包裹…

飞猪店铺小管家软件需求分析说明书

飞猪店铺小管家软件 项目背景&#xff1a; 在飞猪店铺运营过程中&#xff0c;客服人数不足导致客服团队忙不过来&#xff0c;容易出现订票信息错误&#xff0c;进而客户无法顺利参观景点&#xff0c;频繁投诉。这种情况不仅影响客户体验&#xff0c;还可能导致商家因赔付而承受…

玖章算术叶正盛:为什么 PostgreSQL 不如 MySQL 流行?|3306π活动预告

议题大纲 PostgreSQL 是业界功能最强大的开源数据库&#xff0c;为什么在全球流行度没有 MySQL 高&#xff0c;本次分享主题计划从产品、技术、商业等方面综合分析两个数据库的竞争。 议题方向&#xff1a; PostgreSQL 与 MySQL 数据库简介 市场分析 产品定位 技术优劣势 …

TensorFlow与pytorch特定版本虚拟环境的安装

TensorFlow与Python的版本对应&#xff0c;注意&#xff0c;一定要选择对应的版本&#xff0c;否则会让你非常痛苦&#xff0c;折腾很久搞不清楚原因。 建议使用国内镜像源安装 没有GPU后缀的就表示是CPU版本的&#xff0c;不加版本就是最新 pip install tensorflow -i https:…

如何创建集成 LSP 支持多语言的 Web 代码编辑器

对于一个云开发平台来说&#xff0c;一个好的 Web IDE 能很大程度地提高用户的编码体验&#xff0c;而一个 Web IDE 的一个重要组成部分就是代码编辑器。 目前有着多款 web 上的代码编辑器可供选择&#xff0c;比如 Ace、CodeMirror、Monaco&#xff0c;这三款编辑器的比较在这…

[ 云计算 华为云 ] 解决办法:如何更换华为云云耀云服务器L实例的镜像 | 文末送书

文章目录 问题描述分析原因解决办法文末送书《ANSYS Workbench项目分析与案例实操详解》博主推荐理由本书内容简介本书作者简介 废话在前&#xff08;直接看解决办法的这段可以过&#xff09;&#xff1a;讲道理&#xff0c;一般情况下云服务器&#xff0c;镜像是随便更换的&am…

13-JVM调优实战-3

上一篇&#xff1a;12-JVM调优实战-2 今天来介绍一款阿里巴巴的调优工具。 Arthas详解 Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6&#xff0c; 采用命令行交互模式&#xff0c;可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细&am…

【驱动开发】实现三盏灯的控制,编写应用程序测试

head.h #ifndef __HEAD_H__ #define __HEAD_H__//LED1:PE10 //LED2:PF10 //LED3:PE8#define LED_RCC 0X50000A28 //使能GPIO#define LED_MODER 0X50006000 //设置输出模式 #define LED_ODR 0X50006014 //设置输出高低电平#define LED2_MODER 0X50007000 …

一款 IDEA 插件帮你优雅转化 DTO、VO、BO、PO、DO

转自&#xff1a;码猿技术专栏 POJO 的定义是无规则简单的对象&#xff0c;在日常的代码分层中 pojo 会被分为VO、BO、 PO、 DTO VO &#xff08;view object/value object&#xff09;表示层对象 1、前端展示的数据&#xff0c;在接口数据返回给前端的时候需要转成VO 2、个…

火山引擎DataLeap的数据血缘用例与设计概述

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 数据血缘描述了数据的来源和去向&#xff0c;以及数据在多个处理过程中的转换。数据血缘是组织内使数据发挥价值的重要基础能力。本文从字节的数据链路概况开始&…

开学季,长沙又一次戳中年轻人:人才巴士,欢迎“星”同学

初秋临近&#xff0c;又是一年开学季。与往年不一样的是&#xff0c;当数以万计的学子从全国各地来到长沙&#xff0c;这座年轻人友好的城市也用独特的方式表达着对新生的欢迎与诚意&#xff1a;24辆人才巴士“穿上”欢迎词&#xff1b;60个公交站台向新生“表白”&#xff1b;…

linux一些常用的下载工具-aria2

从断点续传开始 故事的过程是这样的&#xff0c;朋友是搞科研的&#xff0c;需要在一个国外的学术网站下载一个药物的模型压缩包&#xff0c;大概有23g。关键他也不会用别的就wget下载…恩中间还断了…问我有什么方法没有断点续传&#xff0c;而是能不能更快速的下载&#xff…

实用工具JRebel XRebel【2023】配置和使用的详解

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于JRebel & XRebel的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.JRebel 的简介 二.插件的…