Ubuntu18.04 NX下用ZED2 双目立体相机进行SLAM

2023-05-16

NX下的ZED2开发

  • 安装流程
    • 问题开始了
      • 看效果
      • 安装ZED2 ROS工具
    • 新故事篇章-zed2测距
      • 开始实现

安装流程

了解zed参数
在这里插入图片描述
在这里插入图片描述

因为网上的安装流程还是不太完整,我补充一下,希望对其他人也有帮助
部分流程参考这位:博主

自己的安装流程:
因为NX本来就自带cuda,所以无需安装cuda,所以首先你要知道自己cuda

nvcc -V

在这里插入图片描述
可以看到我的版本是10.2

现在去下载 SDK

查看自己的jetpack 版本

jtop

在这里插入图片描述
可以看到我用的是jetpack 4.4.1版本
所以下载的是jetson jetpack 4.4 cuda10.2 的版本,也就是下图第二个
在这里插入图片描述

下载完成后,打开终端,进入文件目录

 chmod +x ZED_SDK_Ubuntu16_v2.7.1.run
 ./ZED_SDK_Ubuntu16_v2.7.1.run

全部Y就行

问题开始了

  1. 给电脑插上zed相机,注意要USB3.0的接口。
    安装成功后,软件会在/usr/local/zed文件夹下。

打开终端:

cd "/usr/local/zed/sample/positional tracking"

编译

mkdir build
cd build
cmake ..
make

此时没有生成可执行文件./ZED_Positional_Tracking

解决方法:去cpp文件下新建build 再编译

  1. cmake失败,报错:Could NOT find GLEW (missing: GLEW_INCLUDE_DIR GLEW_LIBRARY)
    在这里插入图片描述
    解决方法:安装libglew-dev软件包就可以解决这个问题了
sudo apt install libglew-dev
  1. cmake解决之后,make的时候失败了,报了类似这样的没有定义指向的错误
    在这里插入图片描述
    解决方法:使用camke选项来解决
cmake -DCMAKE_LIBRARY_PATH=/usr/local/cuda/lib64/stubs -DCMAKE_CXX_FLAGS="-Wl,--allow-shlib-undefined" ..

链接路径需要指向 CUDA 存根文件夹,由于nvcuvid在编译时可能不可用,我们告诉编译器忽略未定义的符号。

  1. make编译成功了,可是执行./ZED_Positional_Tracking却找不到libturbojpeg.so.0(其实在执行/usr/local/zed/tools里面的部分程序时候也是出现这个错误)

在这里插入图片描述
解决方法:安装libjpeg-turbo 2.0版本
转载这位博主

  • 第一步

    进入下载官网页面,网址链接

    下载2.0.x版本的libjpeg-turbo-2.0.2.tar.gz

  • 第二步

    使用tar -zxvf libjpeg-turbo-2.0.2.tar.gz 将压缩包解压到当前目录中, 接着执行以下命令:

   cd libjpeg-turbo-2.0.2
   
   mkdir build 
   
   cmake -G"Unix Makefiles" ..
   
   make

到这里, libjpeg-turbo就已经编译安装好了, 如果你是以root身份执行的,那么编译好后的文件在/usr/local/lib64 里面

  • 第三步(这一步做法和转载的博主不一样)

    参考这位博主教程我是修改共享库配置文件/etc/ld.so.conf.

  • 1、设置:

sudo gedit /etc/ld.so.conf
  • 2、添加库路径:
include /etc/ld.so.conf.d/*.conf
/home/xxx/Downloads/libjpeg-turbo-2.0.90

保存退出;

  • 3、使配置立即生效
sudo ldconfig

现在执行./ZED_Positional_Tracking成功了,tools里面的程序全部都可以执行成功.

看效果

在这里插入图片描述
对了,记得相机标定时候,下面和右边的圆圈要在中间才能标定成功.

安装ZED2 ROS工具

$ cd ~/ZED_WS/src
$ git clone https://github.com/stereolabs/zed-ros-wrapper.git
$ cd ../
$ rosdep install --from-paths src --ignore-src -r -y
$ catkin_make -DCMAKE_BUILD_TYPE=Release
$ source ./devel/setup.bash

如果zed-ros-interfaces缺失,那么

git clone https://github.com/stereolabs/zed-ros-interfaces

git clone 太慢,可以参考下列方式:

//这是我们要clone的
git clone https://github.com/Hackergeek/architecture-samples
 
//使用镜像
git clone https://github.com.cnpmjs.org/Hackergeek/architecture-samples
 
//或者
 
//其他镜像
git clone https://git.sdut.me/Hackergeek/architecture-samples
git clone https://hub.fastgit.org/stereolabs/zed-ros-wrapper.git
git clone https://github.91chi.fun//https://github.com/stereolabs/zed-ros-wrapper.git

编译安装包顺序是:

zed_interfaces:catkin_make -DCMAKE_BUILD_TYPE=Release
zed_wrapper:catkin_make -DCATKIN_WHITELIST_PACKAGES="zed_wrapper"
zed_nodelets:catkin_make -DCATKIN_WHITELIST_PACKAGES="zed_nodelets"

节点详情描述可以查看官方文档http://wiki.ros.org/zed-ros-wrapper,里面列举了该package中可以发布的话题:
在这里插入图片描述
相机自带的工具查看视频流

cd /usr/local/zed/tools

执行命令./ZED_Depth_Viewer
在这里插入图片描述
如果不能看到720和1080和2k,lsusb查看是不是用了usb2.0,也可以用zed2自带工具检测是否用了usb2.0,2.0会导致只能用VGA视频流

启动zed节点

roslaunch zed_wrapper zed2.launch

查看画面

rosrun image_view image_view image:=/zed2/zed_node/rgb_raw/image_raw_color 

用rviz看看点云

roscore
rosrun rviz rviz

在这里插入图片描述
查看视差图(相同颜色表示到相机距离相同)

rosrun image_view disparity_view image:=/zed2/zed_node/disparity/disparity_image

在这里插入图片描述
查看rgb(立体纠正的图像)+深度图(左相机为原点)+视差图
在这里插入图片描述

ros下命令行打开.pcd文件

sudo apt install pcl-tools 
pcl_viewer camera_test.pcd 

新故事篇章-zed2测距

故事到这里,我才开始慢慢了解双目摄像头
zed2、
深度相机—TOF、双相机立体视觉、结构光立体视觉原理及优势对比、
点云的概念、
三维计算视觉研究、
双目原理、
聚类算法、
激光点云与图像融合的车辆检测方法、
双目立体视觉(4)- ZED2双目视觉开发理论与实践 with examples 0.1 object detection(这位博主很强啊)、
YOLO v5与双目测距结合,实现目标的识别和定位测距、
ORB-SLAM2系统的实时点云地图构建、

然后选择查看这两篇文章开始了三维建模的实践
基于ZED 2和ORB_SLAM2的SLAM实践
ZED 相机 && ORB-SLAM2安装环境配置与ROS下的调试

ROS Topic更改

  在完成以步骤后我们仍需要更改ROS或ZED ROS Wrapper中topic的名称才能使得ORB-SLAM2 ROS与ZED相机相配合。

  根据ZED ROS Wrapper官网(http://www.stereolabs.com/blog/index.php/2015/09/07/use-your-zed-camera-with-ros/)中的信息,我们可以查询到ZED ROS Wrapper所发布的topic名称。我们可以选择更改ZED的相关文件使得其匹配ORB-SLAM2 ROS的topic名字,也可以反过来更改更改ORB-SLAM2的topic名字。我选择的是更改ORB-SLAM2 ROS所接收的Topic名称。

  ORB-SLAM2 ROS相关的Topic名称在路径/home/xxx/catkin_zed/src/orb_slam_2_ros/ros/src/StereoNode.cc中的相关文件中    

运行流程:开启zed2->打开slam2->rviz可视化

roslaunch zed_wrapper zed2.launch
roslaunch orb_slam2_ros orb_slam2_zed2_stereo.launch
rviz rviz

在这里插入图片描述
在这里插入图片描述
运行这两个节点后就可以看到物体特征点以及相机的姿态以及点云。貌似这个特征点如果缺失就会导致slam2的点云和姿态都停下。


突然项目要求居然从实时检测测距变成离线二维图测距,所以以上的东西又要放一放了。
题外话:项目要求是物外双目拍摄,然后回来再二维图上取点测距,这个和realsense深度摄像头很像,只是realsense测距只有10m,而这个zed2可以达到40米。好了,之后的内容就是直接拿zed2的深度图和rgb,然后三维映射到二维,然后opencv取点显示距离。搞好之后我再回来弄实时建图,融合图像识别加双目来测量每个聚类物的距离。但感觉户外用双目的点云测距肯定不如雷达,为什么不用雷达啊,因为穷。另外ZED2相机标定及运行VINS-mono、VINS-FUSION建模我也想跑一下,图像标定的话我想自己搞一下,那些都是后话。。。。

ZED2相机标定及运行VINS-mono
VINS-FUSION


开始实现

zed-ros的中心测距
中心测距是直接拿深度图,图像中心的深度值是通过图像像素中心的坐标然后转成深度图下的坐标来得到的。代码如下:

///
//
// Copyright (c) 2018, STEREOLABS.
//
// All rights reserved.
//
// 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.
//
///

/**
 * This tutorial demonstrates simple receipt of ZED depth messages over the ROS system.
 */

#include <ros/ros.h>
#include <sensor_msgs/Image.h>

/**
 * Subscriber callback
 */

void depthCallback(const sensor_msgs::Image::ConstPtr& msg)
{
  // Get a pointer to the depth values casting the data
  // pointer to floating point
  float* depths = (float*)(&msg->data[0]);

  // Image coordinates of the center pixel
  int u = msg->width / 2;
  int v = msg->height / 2;

  // Linear index of the center pixel
  int centerIdx = u + msg->width * v;

  // Output the measure
  ROS_INFO("Center distance : %g m", depths[centerIdx]);
}

/**
 * Node main function
 */
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, "zed_video_subscriber");

  /**
   * 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 imageCallback.  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 subDepth = n.subscribe("depth", 10, depthCallback);

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

改为自己的

#include <iostream>
#include "ros/ros.h"
#include "image_transport/image_transport.h"
#include "opencv2/highgui/highgui.hpp"
#include "cv_bridge/cv_bridge.h"
#include "sensor_msgs/image_encodings.h"

image_transport::Subscriber rgbsub;
image_transport::Subscriber depthsub;
image_transport::Publisher  image_pub;
void cvtColor_src(cv::Mat &src, cv::Mat &src_gray)
{
    //  转换单通道
    if (src.channels() == 4) {
        cv::cvtColor(src, src_gray, CV_BGRA2GRAY);
    }
    else if (src.channels() == 3) {
        cv::cvtColor(src, src_gray, CV_BGR2GRAY);
    }
    else if (src.channels() == 2) {
        cv::cvtColor(src, src_gray, CV_BGR5652GRAY);
    }
    else if (src.channels() == 1) {// 单通道的图片直接就不需要处理
        src_gray = src;
    }
    else { // 负数,说明图有问题 直接返回   
        src_gray = src;
    }
}
void showColorGrayView(const sensor_msgs::ImageConstPtr& msgImg) //672 x 376
{	
	cv_bridge::CvImagePtr cvImgPtr;
	try{
		cvImgPtr=cv_bridge::toCvCopy(msgImg,sensor_msgs::image_encodings::BGR8);
	}
	catch(cv_bridge::Exception e){
		ROS_ERROR_STREAM("Cv_bridge Exception:"<<e.what());
		return;
	}

	cv::Mat cvColorImgMat=cvImgPtr->image;
	cv::Mat cvGrayImgMat;
 
	// Draw an example circle on the video stream
    if (cvColorImgMat.rows > 60 && cvColorImgMat.cols > 60)
    cv::circle(cvColorImgMat, cv::Point(50, 50), 10, CV_RGB(255,0,0));

	cv::imshow("colorview",cvColorImgMat); //imshow函数只支持8位灰度图像、8位彩色图像和32位灰度图像(像素值范围0-1)
	cvtColor_src(cvColorImgMat,cvGrayImgMat);
	image_pub.publish(cvImgPtr->toImageMsg()); //OpenCV图像转换为ROS图像
	
	cv::imshow("grayview",cvGrayImgMat);
	cv::waitKey(20); 
}  

void showDepthView(const sensor_msgs::ImageConstPtr& msgImg) 
{	
	cv::Mat image; 
	try{
		image=cv_bridge::toCvCopy(msgImg, sensor_msgs::image_encodings::TYPE_32FC1) -> image;

	}
	catch(cv_bridge::Exception e){
		ROS_ERROR_STREAM("Cv_bridge Exception:"<<e.what());
		return;
	}
	ROS_INFO("center dis:%f m ", image.at<float>(image.rows / 2, image.cols / 2));
	cv::imshow("depth_view", image);
	cv::waitKey(20);
}

int main(int argc, char **argv)
{
	ros::init(argc, argv, "grayview");
	ros::NodeHandle nh;
	image_transport::ImageTransport it(nh);
	cv::namedWindow("colorview",cv::WINDOW_NORMAL);
	cv::moveWindow("colorview",100,100);
	cv::namedWindow("grayview",cv::WINDOW_NORMAL);
	cv::moveWindow("grayview",100,100);
	cv::namedWindow("depth_view",cv::WINDOW_NORMAL);
	cv::moveWindow("depth_view",100,100);
	rgbsub        = it.subscribe("/zed2/zed_node/rgb/image_rect_color", 1, showColorGrayView);
	depthsub      = it.subscribe("/zed2/zed_node/depth/depth_registered", 1, showDepthView);
	image_pub     = it.advertise("/test", 1);
	ros::spin();
	return 0;
}

cmakelist

cmake_minimum_required(VERSION 3.0.2)
project(pcl_detection)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  zed_interfaces
  pcl_ros

  cv_bridge
  image_transport
)
  
## Find opencv lib
find_package(OpenCV REQUIRED)


## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
  INCLUDE_DIRS include
#  LIBRARIES pcl_detection
  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
  ${PCL_INCLUDE_DIRS}
  ${OpenCV_LIBRARIES}
) 

FILE(GLOB SOURCE_FILES src/*/*.c src/*/*.cpp src/object_detection.cpp)
add_library(zed_pcl_src ${SOURCE_FILES})  
link_libraries(zed_pcl_src)
add_subdirectory(src)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/pcl_detection.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/pcl_detection_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation 
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_pcl_detection.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)


add_executable(wh_vehicle_node wh_vehicle_node.cpp)
add_dependencies(wh_vehicle_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(wh_vehicle_node ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} jsoncpp)

运行后可以看到zed2的rgb,但不知道为什么不能显示灰度图和深度图,我opencv用的4.1.,python2来编译,实在是太奇怪了,编译和运行节点报分别报以下警告和错误:

在这里插入图片描述

OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /build/opencv-XDqSFW/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp, line 9716
terminate called after throwing an instance of 'cv::Exception'
  what():  /build/opencv-XDqSFW/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp:9716: error: (-215) scn == 3 || scn == 4 in function cvtColor

找了一天,找到解决方法了,ROS自带的opencv版本为3.2.0,在安装opencv4后导致使用不同版本的opencv报错,需要给ROS指定统一版本的opencv,解决方法是修改cv_bridge配置文件,使ROS去调用自己安装的opencv版本。(详细操作看这篇文章)

记得Cmakelist.txt里面OpenCV改为4.1

## Find opencv lib
find_package(OpenCV 4.1 REQUIRED)

代码没修改,最后显示rgb+灰度图+深度图+rviz显示ROS发布画圈后的图。
在这里插入图片描述

上面的操作虽然一时可以,但治标不治本,会导致roscore从2.7切换到3.6启动节点失败,而且启动zed2.launch也会失败。之后再想想怎么解决。要解决roscore和zed2.launch的问题,那还是要切回原来的python2.7,操着如下:

sudo update-alternatives --config python

在这里插入图片描述

参考:
渲染深度图
单通道深度图像转化为彩色图发布
ros_多消息同步回调
近似时间算法
cv_bridge

录制多个话题,查看zed2深度和rgb的发布速率,这是为了等一下利用时间戳同步数据。录制过程会出现空间不够情况,我也没做压缩或者扩容等处理,简单验证一下自己问题就好。

rosbag record -o subset1 /zed2/zed_node/rgb/image_rect_colo   /zed2/zed_node/depth/depth_registered

rqt_bag查看数据

rqt_bag subset_2021-10-27-09-33-27.bag subset_2021-10-27-09-33-27.bag

在这里插入图片描述
rgb显示是有的,但显示似乎有点问题。但我们可以看到1s内深度和rgb每一帧发布的时间都差不多,1s20帧。
所以之后可以利用ExactTime Policy或者ApproximateTime Policy来进行消息匹配(详情看:ros_多消息同步回调)

对于这个zed2摄像头,通过/zed2/zed_node/depth/depth_registered 获取的像素值不是直接深度值,而是0-255像素的间接深度值,这个是通过image_transport将[0-255]的像素深度值、相机内参发布出去。
我们可以通过cv_bridge::toCvCopy()来得到深度值,里面转换公式是通过z=f.b/d 来得到深度值的。(详情请看双目模型及深度值计算以及zed2通过相机内参对图像的纠正)

`cv::Mat depthImage = cv_bridge::toCvCopy(depth_image, sensor_msgs::image_encodings::TYPE_32FC1) -> image;`

之后我用cv::imwrite保存深度图depthImage ,但这样会导致深度图数据缺失,因为它会全部转成8UC1**(cv::imwrite对于深度图是只能保存为8UC1,16UC1)**
所以我保存depthImage数据为.xml,但是这样输出会出现inf、inf、Nan(如下图所示),这个应该是点双目匹配时候失败导致的。也就是说不是每个像素点你都有深度值的。

题外话:cv::imwrite保存png是可以保存16位的,数据是无损的(也可以设置压缩等级),保存jpg只能8位且数据有损的。
在这里插入图片描述
其实这个是深度值, 你要需要相机内参才能将深度值转成三维坐标。待更.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ubuntu18.04 NX下用ZED2 双目立体相机进行SLAM 的相关文章

  • ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied问题解决

    Windows Anaconda python3 6 安装依赖包发生错误如下 pip install i https pypi tuna tsinghua edu cn simple r requirements txt user ERRO
  • docker的深入浅出--3.Dockerfile介绍及保留字指令的使用run、entrypoint、onbuild、add和copy关键字以及自定义镜像

    目录 一 Dockerfile介绍 1 centos镜像来理解Dockerfile 2 docker的创建流程 二 Dockerfile的保留字指令 1 自定义centos镜像 xff08 run保留字 xff09 history指令 2
  • 通过MAVROS控制仿真无人机

    首先 xff0c 在目录中建立工作区 xff0c 并进行初始化操作 mkdir p catkin ws src cd catkin ws catkin init wstool init src rosinstall generator ro
  • Jetson nano+T265+PX4实现室内定点飞行

    目录 前言 一 MAVROS的安装 二 Realsense SDK和Realsense ROS的安装 四 给予串口权限 五 在QGC中修改PX4参数 六 启动VIO节点 七 参考文献 前言 1 硬件 飞控 xff1a Pixhawk 6C
  • ros通信之topic通信机制及基于topic的节点通信

    现在的我对于节点node和节点句柄nodehandle的粗俗的理解是 xff1a 节点 xff0c 就是一个进程 xff0c 在ros的环境中叫做节点node 在计算机的工作中叫做进程 xff0c 两者是同时的 xff0c 在ros中 xf
  • inter realsener D435 ROS驱动安装(非源码编译)

    1 安装公钥 sudo apt key adv keyserver keys gnupg net recv key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE sudo apt key adv keys
  • 斜率与倾斜角的关系

    k 61 tan 61 atan k k 斜率 倾斜角
  • NVIDIA JETSON TX2 安装扩展SATA硬盘

    安装扩展硬盘 在dash中搜素disk 进入磁盘管理工具 xff0c 可以看到我们的扩展硬盘 点击磁盘左下角设置按钮 xff0c 进入Format Partition 为硬盘起个名字 xff0c 比如JetsonSSD 250 xff0c
  • Qt——QMessageBox类详解

    QMessageBox类提供了一个模式对话框 xff0c 用于通知用户或询问用户问题并接收答案 我们先来看下QMessageBox information函数的使用 其原型 xff1a static int QMessageBox info
  • 【UWB定位】 - DWM1000模块调试简单心得 - 3

    UWB定位 DWM1000模块调试简单心得 1 UWB定位 DWM1000模块调试简单心得 2 前俩篇介绍了简单的一基站一标签TOF方式测距 xff0c 第三篇我们来搭建一个 一标签三基站 的定位demo 目的 标签与三个基站分别测距 xf
  • 51单片机——计数器与定时器的区别

    定时器和计数器是同一器件 计数器 其共同的特点是都有一个计数脉冲输入端 每输入一个脉冲 计数器就进行加1或减1计数 若计数器件的计数脉冲的频率固定 则可利用计数实现定时 这就是定时器 若计数器件的作用仅仅是记录输入脉冲的多少 则称为计数器
  • vue 中 如何修改【数组中】【对象的值】,解决步骤如下

    原创 https segmentfault com q 1010000012375354 a 1020000012377603 vue 中 如何修改 数组中 对象的值 通过数组的变异方法 xff08 Vue数组变异方法 xff09 我们可以
  • 英伟达Jetson TX2 资源贴

    NVIDIA JETSON TX2 install packages 原创博客 xff0c 欢迎转载 xff0c 请注明博客链接 xff1a 英伟达Jetson TX2 资源贴 资源汇总 jetson tx2 GPIO 解决方案汇总 Jet
  • 研究线程锁之RLock(一)

    死锁 xff1a 是指两个或两个以上的进程或线程在执行过程中 xff0c 因争夺资源而造成的一种互相等待的现象 xff0c 若无外力作用 xff0c 它们都将无法推进下去 此时称系统处于死锁状态或系统产生了死锁 xff0c 这些永远在互相等
  • 虚拟机中使用OpenGL遇到的错误总结

    由于VMware对OpenGL的支持有限 xff0c 目前最新版本的VMware workstation15 Pro只支持到OpenGL3 3的core profile xff08 核心模式 xff09 xff0c 在有条件的前提下建议安装
  • 视觉SLAM——视觉里程计解决方案分析(间接法)

    目录 基本问题 分析各类求解方案优缺点分析 基本问题 视觉里程计是视觉SLAM技术的起点 xff0c 其核心问题同SLAM技术一样 xff0c 主要是定位与构图 xff0c 但视觉里程计解决的核心是定位问题 xff0c 也就是相机的位姿 通
  • 视觉SLAM理论——位姿的理解与间接求解

    目录 xff1a 位姿的定义位姿与变换矩阵的区别与联系位姿的求解方法 位姿的定义 在SLAM中 xff0c 位姿是世界坐标系到相机坐标系的变换 xff0c 包括旋转与平移 根据以上定义可以衍生以下几个问题 xff1a 1 世界坐标系在哪 x
  • 线性最小均方误差算法(LMSE),最小二乘法(LS)

    目录 背景正交投影引理LMSE算法LS算法直线拟合 背景 对于一个系统 xff0c 在给予一定的输入 xff0c 那么通常都会产生相对应的输出 在实际的系统中 xff0c 这样的输出必然伴随着噪声 xff0c 这样被噪声污染的输出通常是传感
  • 无人机,动力系统建模

    建模目的 无人机动力系统包括 xff1a 螺旋桨 电机 电调及电池 建模流程图如下 xff08 图片来源 多旋翼飞行器设计与控制 M 全权 xff09 xff1a 经过误差结算后 xff0c 将误差信息转换为螺旋桨的升力与转矩 xff0c
  • 寻找APM中EKF的五大公式

    EKF核心代码位置 AP NavEKF2 cpp 进入该函数 进入该函数 xff0c 然后可以看到关键部分 xff0c 也即卡尔曼五个公式的地方 下面介绍每个公式的具体位置 28状态值 首先要知道选用的状态值有哪些 xff0c 28状态值

随机推荐

  • 【PX4 EKF simulink仿真程序解析】(一)初始化

    PX4 EKF simulink仿真程序解析 xff08 一 xff09 初始化 整体框架如下 xff1a 进入InertialNavFliter xff0c 整体框架如下 xff1a 初始化过程包括协方差初始化 状态向量初始化 其中包括测
  • C++——三种继承方式与三种访问权限的相互组合

    三种访问权限 public 可以被任意实体访问 protected 只允许子类及本类的成员函数访问 private 只允许本类的成员函数访问 三种继承方式 public 继承 protect 继承 private 继承 组合结果 基类中 继
  • 小米路由器部分机型刷原生Openwrt系统

    小米路由器的部分机型在官网没有开发版的固件 xff0c 不支持直接开启ssh xff0c 可以通过OpenWRTInvasion工具解决 本文以小米路由器4为例 xff1a 在openwrt官网的设备列表中找到对应型号 xff0c 按照页面
  • qt的安装与卸载

    通常情况下 xff0c 有两种安装方法 xff1a 1 直接在命令行安装 sudo apt span class hljs keyword get span install qt5 span class hljs keyword defau
  • 固件提取

    前言使用工具识别芯片一 摘取芯片二 制作U盘编程器三 RT809H编程器读取eMMC芯片数据四 总结 前言 无处不在的物联网设备 xff0c 也可能成为无所不在的安全隐患 xff0c 物联网安全问题一直是困扰物联网快速发展的一大难题 作为安
  • xshell评估过期解决办法,非常简单

    首先 xff0c 你的xshell不要卸载 xff0c 不需要动任何地方 进官网 https www netsarang com zh xff0c 翻到最下面 xff0c 下载那里点家庭 学校免费 然后会跳转到下面这个界面 xff0c 按图
  • vscode配置markdown,安装插件

    一 概述 最近迷上了MarkDown xff0c 所以进行了学习 xff0c 首先是编辑器的选择 xff0c 可以参考这篇文章 xff1a 好用的MARKDOWN编辑器一览 我本人并没有选择其中的任意一款进行尝试 xff0c 因为我个人十分
  • Vs2019重新生成解决方案时报错

    解决办法 xff1a Release模式下 gt 属性 gt 高级 gt 高级属性 gt 全程序优化 将这里的默认项 使用链接时间代码生成 改为 无全程序优化 xff0c 接下来就可以运行了
  • 指针常量和常量指针

    参考 xff1a C语言 常量指针 指针常量以及指向常量的指针常量三者区别详解 望崖的博客 CSDN博客 常量指针和指针常量的区别
  • LW_OOPC 宏配置及使用指南

    LW OOPC 宏配置及使用指南 摘抄 xff1a https github com Akagi201 lw oopc LW OOPC 是一套轻量级的面向对象 C 语言编程框架 它是一套 C 语言的宏 xff0c 总共 1 个 h 文件 如
  • 十个值得学习的c开源项目(嵌入式)

    开源世界有许多优秀的开源项目 xff0c 我选取其中十个最优秀的 最轻量级的C语言的项目 xff0c 希望可以为C语言开发人员提供参考 十个最值得阅读学习的C开源项目代码 1 Webbench 2 Tinyhttpd 3 cJSON 4 C
  • 树莓派开机无法进入桌面的解决办法

    1 初次开机会出现 34 raspi config 34 这个界面 xff0c xff08 如下图 xff09 如果不是初装的系统 xff0c 也可以输入命令 xff1a sudo raspi config xff0c 调出此界面 2 如果
  • Xshell 6, 7 已过期的解决方案

    公开版的Xshell一段时间后就评估失效 xff0c 很麻烦 xff0c 下面的方法可以在官网下载个人免费版本 xff0c 常用功能都有亲测有效 xff01 就算之前安装过已经过期的Xshell也没关系 1 首先进入 xff1a https
  • C语言网络编程(1)— UDP通信

    C语言网络编程 xff08 1 xff09 UDP通信 一 socket 我们要进行网络通信 xff0c 那么就要用到socket xff0c socket即网络套接字 xff0c 应用程序可以通过它发送或接收数据 xff0c 可对其进行像
  • C语言网络编程(2)— TCP通信

    C语言网络编程 xff08 2 xff09 TCP通信 一 TCP客户端 1 建立连接 我们要使用到socket xff0c 首先首先我们添加要使用的头文件 span class token macro property span clas
  • 搭建kubernetes v1.21.5 和 kubesphere v3.2.1

    一 准备一台干净的centos7 6机器 二 关闭防火墙打上相关补丁和相关系统软件 systemctl stop firewalld yum span class token function install span openssh op
  • js定时器

    一 定时器概述 开发时用到的js定时器主要分为两种 xff1a 1 一次性的定时器setTimeOut方法 xff0c 通过设置一定的时间 xff0c 时间到就执行 var timer 61 setTimeout fun 毫秒数 清除的方法
  • UNIX 环境高级编程

    与你共享 xff0c 与你共舞 xff01 UNIX环境高级编程 xff08 第3版 xff09 是被誉为UNIX编程 圣经 xff1b 书中除了介绍UNIX文件和目录 标准I O库 系统数据文件和信息 进程环境 进程控制 进程关系 信号
  • ROS的CMakeList编写

    参考这位博主 我的cmakelist包 在 home xxx catkin Drone src Flight Control ROS CMakeLists txt cmake minimum required span class toke
  • Ubuntu18.04 NX下用ZED2 双目立体相机进行SLAM

    NX下的ZED2开发 安装流程问题开始了看效果安装ZED2 ROS工具 新故事篇章 zed2测距开始实现 安装流程 了解zed参数 因为网上的安装流程还是不太完整 xff0c 我补充一下 希望对其他人也有帮助 部分流程参考这位 xff1a