软件篇-02-基于ZED 2和ORB_SLAM2的SLAM实践
本期内容如题,ZED 2的SDK功能还是挺多的,包括轨迹跟踪,实时建图等等。虽然由于是商业产品,我看不到他们的源代码,但是根据使用情况来看,ZED 2内部是采用了IMU和光学信息融合的算法,并且IMU的数据在决策权重上占了更大的比例,至于为什么我会在后文讲到。关于ORB_SALM2,它给我们提供了目前来说效果比较好的实时定位和稀疏地图构建功能,同时支持单目、双目和RGB-D摄像头的SLAM算法,但是目前来说大多数SLAM工程应用都是用来做导航避障,单单的稀疏地图并不能满足我们的要求,于是我决定充分利用两者的信息,以达到最佳的效果。
- 安装ZED 2 SDK和ORB_SLAM2
- 使用Qt Creator开发ROS工程
- 适配ORB_SALM2于双目相机ZED 2
- 创建功能包用于保存SLAM地图和三维点云图
- RVIZ、URDF配置
- 安装ZED 2 SDK和ZED 2 ROS功能包
- 安装ORB_SLAM2
$ rosdep install --from-paths src --ignore-src -r -y
$ catkin_make -DCMAKE_BUILD_TYPE=Release
$ source ./devel/setup.bash
# 后续你可能还需要以下Cmake参数 -DCATKIN_DEVEL_PREFIX=../devel -DCMAKE_INSTALL_PREFIX=../install
$ sudo vim /usr/share/applications/org.qt-project.qtcreator.desktop
$ sudo vim catkin_qi/src/CMakeLists.txt
project(catkin_qi)
#Add custom (non compiling)
targets so launch scripts and python files show up in QT Creator's project view. file(GLOB_RECURSE EXTRA_FILES */*)
# 以下的‘ROS_Packages’是我自定义的名字,到时所有功能包都会显示在该目录下 add_custom_target(ROS_Packages ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} SOURCES ${EXTRA_FILES})

Qt-ROS工程树
<?xml version="1.0"?>
<launch> <!-- launch the zed_ros_wrapper node-->
<include file="$(find zed_wrapper)/launch/zed2.launch"> </include>
<node name="orb_slam2_stereo" pkg="orb_slam2_ros" type="orb_slam2_ros_stereo" output="screen">
<remap from="image_left/image_color_rect" to="/zed2/zed_node/left/image_rect_color" />
<remap from="image_right/image_color_rect" to="/zed2/zed_node/right/image_rect_color" /> <param name="publish_pointcloud" type="bool" value="true" /> <param name="publish_pose" type="bool" value="true" /> <param name="localize_only" type="bool" value="false" /> <param name="reset_map" type="bool" value="false"/><!-- static parameters --><paramname="load_map"type="bool"value="true"/><paramname="map_file"type="string"value="/home/qi/catkin_qi/src/tx2_slam/map/bin/zed2_slam_Map.bin"/><paramname="settings_file"type="string"value="$(find tx2_slam)/config/Zed2Stereo.yaml"/><paramname="voc_file"type="string"value="$(find tx2_slam)/Vocabulary/ORBvoc.txt"/><paramname="pointcloud_frame_id"type="string"value="map"/><paramname="camera_frame_id"type="string"value="camera_link"/><paramname="min_num_kf_in_map"type="int"value="5"/></node><!-- Position respect to base frame (i.e. "base_link) --><argname="cam_pos_x"default="0.0"/><argname="cam_pos_y"default="0.0"/><argname="cam_pos_z"default="0.0"/><!-- Orientation respect to base frame (i.e. "base_link) --><argname="cam_roll"default="0.0"/><argname="cam_pitch"default="0.0"/><argname="cam_yaw"default="0.0"/><!-- ROS URDF description of the ZED --><groupif="true"><paramname="zed2_description"command="$(find xacro)/xacro '$(find tx2_slam)/urdf/zed_descr.urdf.xacro' camera_name:=tx2zed2 camera_model:=zed2 base_frame:=zed2_base_link cam_pos_x:=$(arg cam_pos_x) cam_pos_y:=$(arg cam_pos_y) cam_pos_z:=$(arg cam_pos_z) cam_roll:=$(arg cam_roll) cam_pitch:=$(arg cam_pitch) cam_yaw:=$(arg cam_yaw)"/><nodename="zed2_state_publisher"pkg="robot_state_publisher"type="robot_state_publisher"output="screen"required="true"><remapfrom="robot_description"to="zed2_description"/></node></group><!-- Launch rivz display --><nodename="rviz"pkg="rviz"type="rviz"args="-d $(find tx2_slam)/config/rviz_config.rviz"output="screen"/><nodename="MapBuild"pkg="tx2_slam"type="MapBuild"output="screen"><paramname="prefix"type="string"value="$(find tx2_slam)/map/pcd_files/"/></node></launch>
%YAML:1.0
# Camera calibration and distortion parameters (OpenCV) Camera.fx: 527.2025 Camera.fy: 527.245 Camera.cx: 618.31 Camera.cy: 367.1445 # get the rectified image from zed-ros-wrapper, so set all zero Camera.k1: 0.0 Camera.k2: 0.0 Camera.p1: 0.0 Camera.p2: 0.0 Camera.k3: 0.0 # more to see https://www.stereolabs.com/docs/video/camera-controls/ Camera.width: 2560 Camera.height: 720 Camera.fps: 30.0 # stereo baseline(m) times fx Camera.bf: 63.1965 # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale) Camera.RGB: 1 # Close/Far threshold. Baseline times. # set it according to the actual effect ThDepth: 35 # the depth in program equal to the real depth times the DepthMapFactor #DepthMapFactor: 1000.0 #-------------------------------------------------------------------------------------------- # Stereo Rectification. Only if you need to pre-rectify the images. # Camera.fx, .fy, etc must be the same as in LEFT.P #-------------------------------------------------------------------------------------------- LEFT.height: 720 LEFT.width: 2560 LEFT.D: !!opencv-matrix rows: 1 cols: 5 dt: d data: [0.0, 0.0, 0.0, 0.0, 0.0] LEFT.K: !!opencv-matrix rows: 3 cols: 3 dt: d data: [527.2025, 0.0, 618.31, 0.0, 527.245, 367.1445, 0.0, 0.0,1.0]LEFT.R:!!opencv-matrixrows:3cols:3dt: d data:[1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0]LEFT.P:!!opencv-matrixrows:3cols:4dt: d data:[527.2025,0.0,618.31,0.0,0.0,527.245,367.1445,0.0,0.0,0.0,1.0,0.0]RIGHT.height:720RIGHT.width:2560RIGHT.D:!!opencv-matrixrows:1cols:5dt: d data:[0.0,0.0,0.0,0.0,0.0]RIGHT.K:!!opencv-matrixrows:3cols:3dt: d data:[527.2025,0.0,618.31,0.0,527.245,367.1445,0.0,0.0,1.0]RIGHT.R:!!opencv-matrixrows:3cols:3dt: d data:[1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0]RIGHT.P:!!opencv-matrixrows:3cols:4dt: d data:[527.2025,0.0,618.31,0.0,0.0,527.245,367.1445,0.0,0.0,0.0,1.0,0.0]#--------------------------------------------------------------------------------------------# ORB Parameters#--------------------------------------------------------------------------------------------# ORB Extractor: Number of features per imageORBextractor.nFeatures:1200# ORB Extractor: Scale factor between levels in the scale pyramidORBextractor.scaleFactor:1.2# ORB Extractor: Number of levels in the scale pyramidORBextractor.nLevels:8# ORB Extractor: Fast threshold# Image is divided in a grid. At each cell FAST are extracted imposing a minimum response.# Firstly we impose iniThFAST. If no corners are detected we impose a lower value minThFAST# You can lower these values if your images have low contrastORBextractor.iniThFAST:20ORBextractor.minThFAST:7
//set the Zed2 ouput
mZedParams.camera_resolution = sl::RESOLUTION::HD720;
mZedParams.camera_fps = 30;
mConnStatus = mZed.open(mZedParams);
- 保存三维点云图

#pragma once
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl_ros/point_cloud.h>
#include <tf2_ros/buffer.h> #include <tf2_ros/transform_listener.h>
#include <tf2_eigen/tf2_eigen.h>
#include <pcl/io/pcd_io.h> class MapBuild {
public:
~MapBuild();
MapBuild();
private:
}; class PointCloudToPCD {
protected: ros::NodeHandle nh_; private: std::string prefix_; std::string filename_; bool binary_; bool compressed_; std::string fixed_frame_; tf2_ros::Buffer tf_buffer_; tf2_ros::TransformListener tf_listener_; public: std::string cloud_topic_; ros::Subscriber sub_; //////////////////////////////////////////////////////////////////////////////// // Callback void cloud_cb (const pcl::PCLPointCloud2::ConstPtr& cloud) { if ((cloud->width * cloud->height) == 0) return; ROS_INFO ("Received %d data points in frame %s with the following fields: %s", (int)cloud->width * cloud->height, cloud->header.frame_id.c_str (), pcl::getFieldsList(*cloud).c_str()); Eigen::Vector4f v = Eigen::Vector4f::Zero(); Eigen::Quaternionf q = Eigen::Quaternionf::Identity();if(!fixed_frame_.empty()){if(!tf_buffer_.canTransform(fixed_frame_, cloud->header.frame_id, pcl_conversions::fromPCL(cloud->header.stamp), ros::Duration(3.0))){ROS_WARN("Could not get transform!");return;} Eigen::Affine3d transform; transform = tf2::transformToEigen(tf_buffer_.lookupTransform(fixed_frame_, cloud->header.frame_id, pcl_conversions::fromPCL(cloud->header.stamp))); v = Eigen::Vector4f::Zero(); v.head<3>()= transform.translation().cast<float>(); q = transform.rotation().cast<float>();} std::stringstream ss;if(filename_ !=""){ ss << filename_ <<".pcd";}else{ ss << prefix_ << cloud->header.stamp <<".pcd";}ROS_INFO("Data saved to %s", ss.str().c_str()); pcl::PCDWriter writer;if(binary_){if(compressed_){ writer.writeBinaryCompressed(ss.str(),*cloud, v, q);}else{ writer.writeBinary(ss.str(),*cloud, v, q);}}else{ writer.writeASCII(ss.str(),*cloud, v, q,8);}}////////////////////////////////////////////////////////////////////////////////PointCloudToPCD():binary_(false),compressed_(false),tf_listener_(tf_buffer_){// Check if a prefix parameter is defined for output file names. ros::NodeHandle priv_nh("~");if(priv_nh.getParam("prefix", prefix_)){ROS_INFO_STREAM("PCD file prefix is: "<< prefix_);}elseif(nh_.getParam("prefix", prefix_)){ROS_WARN_STREAM("Non-private PCD prefix parameter is DEPRECATED: "<< prefix_);} priv_nh.getParam("fixed_frame", fixed_frame_); priv_nh.getParam("binary", binary_); priv_nh.getParam("compressed", compressed_); priv_nh.getParam("filename", filename_);if(binary_){if(compressed_){ROS_INFO_STREAM("Saving as binary compressed PCD");}else{ROS_INFO_STREAM("Saving as binary uncompressed PCD");}}else{ROS_INFO_STREAM("Saving as ASCII PCD");}if(filename_ !=""){ROS_INFO_STREAM("Saving to fixed filename: "<< filename_);} cloud_topic_ ="/zed2/zed_node/mapping/fused_cloud"; sub_ = nh_.subscribe(cloud_topic_,1,&PointCloudToPCD::cloud_cb,this);ROS_INFO("Listening for incoming data on topic %s", nh_.resolveName(cloud_topic_).c_str());}};
- 保存ORB_SLAM2地图
ros::init (
argc, argv, "MapBuild", ros::init_options::AnonymousName);
ros::NodeHandle n; ros::ServiceClient client = n.serviceClient<orb_slam2_ros::SaveMap>("/orb_slam2_stereo/save_map"); orb_slam2_ros::SaveMap srv; srv.request.name = "/home/qi/catkin_qi/src/tx2_slam/map/bin/zed2_slam_Map.bin";
if (client.call(srv)) { ROS_INFO("Ready to create Map"); } else { ROS_ERROR("Failed to call service SaveMap");
return 1;
}

软件篇-02-基于ZED 2和ORB_SLAM2的SLAM实践的更多相关文章
- 智能家居-3.基于esp8266的语音控制系统(软件篇)
智能家居-1.基于esp8266的语音控制系统(开篇) 智能家居-2.基于esp8266的语音控制系统(硬件篇) 智能家居-3.基于esp8266的语音控制系统(软件篇) 赞赏支持 QQ:505645 ...
- 驱动开发学习笔记. 0.02 基于EASYARM-IMX283 烧写uboot和linux系统
驱动开发读书笔记. 0.02 基于EASYARM-IMX283 怎么烧写自己裁剪的linux内核?(非所有arm9通用) 手上有一块tq2440,但是不知道什么原因,没有办法烧boot进norflas ...
- OA办公软件篇(二)—权限管理
权限管理的背景 权限管理的作用 迭代历程 关键名词释义 权限管理模型 具体实现 写在最后 权限管理的背景 在OA办公软件篇(一)-组织架构一文中,我们说到组织架构是软件系统的权限体系的重要搭建依据 ...
- GSM Sniffing入门之软件篇:GSMTAP抓取与SMS(Short Message Service)
重点介绍如何利用50元左右的设备,抓包并还原SMS短信内容: ps:研究GSM Sniffing纯属个人兴趣,能抓SMS报文只是捡了个明文传输的漏子,切勿用于非法用途.就像sylvain说的,osmo ...
- Atitit.升级软件的稳定性---基于数据库实现持久化 循环队列 循环队列
Atitit.升级软件的稳定性---基于数据库实现持久化 循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...
- [知乎]老狼:深入PCI与PCIe之二:软件篇
深入PCI与PCIe之二:软件篇 https://zhuanlan.zhihu.com/p/26244141 我们前一篇文章(深入PCI与PCIe之一:硬件篇 - 知乎专栏)介绍了PCI和PCIe的硬 ...
- Python网络编程02 /基于TCP、UDP协议的socket简单的通信、字符串转bytes类型
Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes类型 目录 Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes ...
- OA办公软件篇(一)—组织架构
OA办公软件篇(一)-组织架构 背景 作用 迭代历程 具体实现 写在最后 背景 在说组织架构之前,我们先来说说OA本身. 百度百科解释OA为:办公自动化(Office Automation,简称O ...
- OA办公软件篇(三)—审批流
背景 作用 迭代历程 具体实现 写在最后 背景 在前面两篇文章中,我们分别讲了组织架构和权限管理,今天我们来讲一个跟组织架构关系比较密切的功能-审批流. 审批流,通俗来说就是一个完整的审批流程,是 ...
随机推荐
- web前端学习笔记(二)---Django
[前言]前面(一)学习了web的基础知识,介绍到了MVC,项目使用一个Django框架. Django book:https://code.ziqiangxuetang.com/django/djan ...
- Youcans 的第一篇博客
这是我的第一篇博客. 今后我会将我的学习心得和总结在这里发布,与大家共享,共勉.
- 聊聊Dotnet的垃圾回收
最近在做一个项目,用到了大量的非托管技术,所以垃圾回收变得很重要. 在说垃圾回收之前,先说说两个概念: 托管代码,是由CLR管理的代码 非托管代码,是由操作系统直接执行的代码 在早期C++的时候, ...
- KMP(超详细复杂度分析)
从 stackoverflow中找到了一个时间复杂度分析很棒的链接 https://www.inf.hs-flensburg.de/lang/algorithmen/pattern/kmpen.htm ...
- .zip爆破
.zip爆破 Python的优化问题 Python在计算密集型任务方面没有明显的多线程优化,多线程更加适合用于处理I/O密集型任务(如网络请求).爆破任务使用顺序执行即可. 编写Python脚本 一个 ...
- python中数组切片[:,i] [i:j:k] [:-i] [i,j,:k]
逗号","分隔各个维度,":"表示各个维度内的切片,只有:表示取这个维度的全部值,举例说明如下 1 1.二维数组 2 3 X[:,0]取所有行的第0个数据,第二 ...
- SQL 存储过程里调用另一个存储过程
由于创建了一个存储过程,并且要在另一个存储过程里调用这个存储过程所以在网上找了一下相关的代码,现在总结一下,防止以后还会用到 由于这次我写的存储过程只需要返回一个求和的结果,所以我使用了output ...
- PAT (Advanced Level) Practice 1023 Have Fun with Numbers (20 分) 凌宸1642
PAT (Advanced Level) Practice 1023 Have Fun with Numbers (20 分) 凌宸1642 题目描述: Notice that the number ...
- [Fundamental of Power Electronics]-PART II-7. 交流等效电路建模-7.4 规范电路模型
7.4 规范电路模型 在讨论了推导开关变换器交流等效电路模型的几种方法后,让我们先停下来,说明下这些结果.所有的在 CCM下以PWM工作的DC-DC变换器都具有相似的基本功能.首先,他们在理想情况下, ...
- 附031.Kubernetes_v1.20.4高可用部署架构二
kubeadm介绍 kubeadm概述 参考附003.Kubeadm部署Kubernetes. kubeadm功能 参考附003.Kubeadm部署Kubernetes. 本方案描述 本方案采用kub ...