上一节介绍了陀螺仪Imu传感数据的订阅和发布。

本节会介绍路标Landmark数据的发布和订阅。Landmark在cartographer中作为定位的修正补充,避免定位丢失。

这里着重解释一下Landmark,它与Scan,Odom,Imu数据不同,并不是直接的传感数据。它是地图上的特征点,通常是易被识别的物体。

在cartographer中,通常是用反光柱或者二维码做landmark,实际上反光柱用的更多,因为反光柱同样可以使用激光雷达识别,不需要添加多的传感器。

对于用反光板构建landmark,推荐slam大佬峰哥的博文:

使用2个反光柱作为landmark

使用3个反光柱作为landmark

对于用二维码作用landmark,这里同样推荐峰哥的博文:

使用二维码作为landmark

当然,在学习构建landmark之前,先看看Landmark的结构及如何订阅和发布landmark。

目录

1:cartographer_ros_msgs/LandmarkList消息类型

2:发布LandmarkList消息

3:订阅Landmark消息


1:cartographer_ros_msgs/LandmarkList消息类型

在终端查看消息数据结构:

rosmsg show cartographer_ros_msgs/LandmarkList

Landmark消息类型数据结构如下:

std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
cartographer_ros_msgs/LandmarkEntry[] landmarks
  string id
  geometry_msgs/Pose tracking_from_landmark_transform
    geometry_msgs/Point position
      float64 x
      float64 y
      float64 z
    geometry_msgs/Quaternion orientation
      float64 x
      float64 y
      float64 z
      float64 w
  float64 translation_weight
  float64 rotation_weight

LandmarkList中的landmarks是LandmarkEntry合集,LandmarkEntry对应的是单个路标的位置和姿势,所以LandmarkList其实是一个或多个路标的信息。


2:发布LandmarkList消息

#include <ros/ros.h>
#include <cartographer_ros_msgs/LandmarkList.h>
#include <cartographer_ros_msgs/LandmarkEntry.h> int main(int argc, char** argv){
  ros::init(argc, argv, "landmark_publisher");   ros::NodeHandle n;
  ros::Publisher landmark_pub = n.advertise<cartographer_ros_msgs::LandmarkList>("landmark", 50);   ros::Rate r(1.0);
  while(n.ok()){
    cartographer_ros_msgs::LandmarkList landmarkList;
    landmarkList.header.stamp = ros::Time::now();
    landmarkList.header.frame_id = "base_link";
    landmarkList.landmarks.resize(10);
    
    for(int i = 0; i < 10; i++)
    {
      landmarkList.landmarks[i].id = std::to_string(i);
      landmarkList.landmarks[i].tracking_from_landmark_transform.position.x = 1*i;
      landmarkList.landmarks[i].tracking_from_landmark_transform.position.y = 2*i;
      landmarkList.landmarks[i].tracking_from_landmark_transform.position.z = 3*i;
      landmarkList.landmarks[i].tracking_from_landmark_transform.orientation.w = 1;
      landmarkList.landmarks[i].tracking_from_landmark_transform.orientation.x = 0;
      landmarkList.landmarks[i].tracking_from_landmark_transform.orientation.y = 0;
      landmarkList.landmarks[i].tracking_from_landmark_transform.orientation.z = 0;
      landmarkList.landmarks[i].translation_weight = 10;
      landmarkList.landmarks[i].rotation_weight = 10;    
    }
    landmark_pub.publish(landmarkList);     r.sleep();
  }
}

值得注意的是,在真实的数据中,有多个反光柱时landmarks.id应该要是独一无二的,能通过id找到确定路标的。

所以如何识别和确定id是一个问题,通常辅助其他的反光柱构建特征三角形来识别和确定id。具体的可以参照其他资料,有机会作者会对此展开补充。


3:订阅Landmark消息

(1) 通过rosbag订阅

rostopic echo /landmark

(2) 通过rviz查看

打开rviz

rosrun rviz rviz

同时需要在cartographer配置文件中设置use_landmarks= true,并运行cartographer节点。

因为rviz无法接收显示cartographer_ros_msgs/LandmarkList,但是可以查看cartographer接收到landmark话题消息后发布的landmrk_pose_list。

Fixed Frame修改为base_link,添加Landmark并将Topic设为/landmrk_pose_list

(3) 编写程序打印

#include "ros/ros.h"
#include "cartographer_ros_msgs/LandmarkList.h"
#include "cartographer_ros_msgs/LandmarkEntry.h" void LandmarkCallback(const cartographer_ros_msgs::LandmarkList::ConstPtr &msg)
{
    ROS_INFO("Landmark Size: %d", msg->landmarks.size());
} int main(int argc, char **argv)
{
    ros::init(argc, argv, "listener");
    ros::NodeHandle node;
    ros::Subscriber sublandmark = node.subscribe("landmark", 1000, LandmarkCallback);
    ros::spin();
    return 0;
}

cartographer算法运行所需要的传感器数据的结束到此就告一段落了,在了解完数据的发布和订阅之后,接着来看怎样在cartographer算法中融入和配置这些数据。

【完】


下一节会介绍cartographer的主要配置参数。

【cartographer_ros】六: 发布和订阅路标landmark信息的更多相关文章

  1. 【cartographer_ros】五: 发布和订阅陀螺仪Imu信息

    上一节介绍了里程计Odometry传感数据的订阅和发布. 本节会介绍陀螺仪Imu数据的发布和订阅.陀螺仪在cartographer中主要用于前端位置预估和后端优化. 目录 1:sensor_msgs/ ...

  2. 【cartogarpher_ros】三: 发布和订阅雷达scan信息

    上一节介绍和测试了cartographer的官方demo. 本节会编写ros系统中,最常用的激光雷达LaserScan传感数据的订阅和发布,方便在cartographer中加入自己的数据进行建图与定位 ...

  3. 【cartographer_ros】四: 发布和订阅里程计odom信息

    上一节介绍了激光雷达Scan传感数据的订阅和发布. 本节会介绍里程计Odom数据的发布和订阅.里程计在cartographer中主要用于前端位置预估和后端优化. 官方文档: http://wiki.r ...

  4. EasyNetQ使用(六)【多态发布和订阅,消息版本控制】

    你能够订阅一个接口,然后发布基于这个接口的实现. 让我们看下一个示例.我有一个接口IAnimal和两个实现Cat和Dog: public interface IAnimal { string Name ...

  5. Redis的高级应用-事务处理、持久化、发布与订阅消息、虚拟内存使用

    三.事务处理 Redis的事务处理比较简单.只能保证client发起的事务中的命令可以连续的执行,而且不会插入其他的client命令,当一个client在连接 中发出multi命令时,这个连接就进入一 ...

  6. redis 发布和订阅实现

    参考文献 15天玩转redis -- 第九篇 发布/订阅模式 <Redis设计与实现> 命令简介 在redis用户手册中,跟发布订阅相关的命令有如下的六个: PSUBSCRIBE PUBL ...

  7. (转)SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步

    最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...

  8. (原)3.2 Zookeeper应用 - 数据的发布与订阅

    本文为原创文章,转载请注明出处,谢谢 数据的发布与订阅 1.应用 服务端监听数据改变,客户端创建/更新节点数据,客户端提供数据,服务端处理 2.原理 客户端监控节点数据改变事件(例如配置信息,下图的c ...

  9. MSSQLSERVER之发布-分发-订阅

    一.环境 发布服务器 O S: Windows servier 2003 64位 Soft: Microsoft SqlServer 2008 R2 I P: 192.168.3.70 HOST-NA ...

随机推荐

  1. 服务器脚本搭建国基北盛openstack平台

    @ 目录 基础环境搭建 控制节点网卡配置 计算节点网卡配置 主机映射 3,关闭防火墙和selinux以及NetworkManager 设置yum源 计算节点分区 配置openrc.sh环境变量 平台组 ...

  2. Linux网卡绑定bond0-实验

    虚拟机添加网卡 ip addr 查看新增的网卡是否读取 添加bonding接口 [root@centos8~]$nmcli con add type bond con-name mybond0 ifn ...

  3. Shell 脚本编程最佳实践

    前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看.而且当我在看其他人写的脚本的时候,总觉得难以阅读.毕竟shell脚本这个东 ...

  4. 超越OpenCV速度的MorphologyEx函数实现(特别是对于二值图,速度是CV的4倍左右)。

    最近研究了一下opencv的 MorphologyEx这个函数的替代功能, 他主要的特点是支持任意形状的腐蚀膨胀,对于灰度图,速度基本和CV的一致,但是 CV没有针对二值图做特殊处理,因此,这个函数对 ...

  5. 使用VLL技术实现多家合作伙伴复用同一条链路做两端数据全透传

    公司A当前租用一条10G跨市运营商光缆,自身业务只用到一半流量,为节省成本,寻求多家合作伙伴共用链路以达到财务需求 合作伙伴需求接入链路全透传,即光缆两端接入点端口逻辑直连 当前有三种方案可以实现上述 ...

  6. 使用echo 无法正确清空文件存储大小

    在使用echo进行重定向文件的时候,会存在大小没有发生改变的现象 使用上面的方法遇到一个现象 ls -l 与 du -sh 得到的大小事是不同的 可以尝试下面的方面之后在进行对比 再看是否正确清除 使 ...

  7. 429. N-ary Tree Level Order Traversal - LeetCode

    Question 429. N-ary Tree Level Order Traversal Solution 题目大意: N叉树,返回每层的值,从上到下,从左到右 思路: 利用队列遍历这个N叉树 J ...

  8. 以圆类 Circle 及立体图形类 Solid 为基础设计圆柱类 Cylinder

    学习内容:以圆类 Circle 及立体图形类 Solid 为基础设计圆柱类 Cylinder 代码示例: import java.util.Scanner;class Point3{ private ...

  9. .NET性能优化-推荐使用Collections.Pooled

    简介 性能优化就是如何在保证处理相同数量的请求情况下占用更少的资源,而这个资源一般就是CPU或者内存,当然还有操作系统IO句柄.网络流量.磁盘占用等等.但是绝大多数时候,我们就是在降低CPU和内存的占 ...

  10. Tensorboard SummaryWriter()

    import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvi ...