第三篇 视觉里程计(VO)的初始化过程以及openvslam中的相关实现详解

2023-05-16

视觉里程计(Visual Odometry, VO),通过使用相机提供的连续帧图像信息(以及局部地图,先不考虑)来估计相邻帧的相机运动,将这些相对运行转换为以第一帧为参考的位姿信息,就得到了相机载体(假设统一的刚体)的里程信息。先上一张本文主要内容的框图:
1779232-20190906154117746-2053129800.png

初始化实例

在实例化跟踪器的时候会实例化一个初始化实例,有一些比较重要的参数需要注意下,看代码注释以及初始值,参数值也可以在yaml文件中自定义。

// src/openvslam/module/initializer.h:83
//! max number of iterations of RANSAC (only for monocular initializer)
const unsigned int num_ransac_iters_;
//! min number of triangulated pts
const unsigned int min_num_triangulated_;
//! min parallax (only for monocular initializer)
const float parallax_deg_thr_;
//! reprojection error threshold (only for monocular initializer)
const float reproj_err_thr_;
//! max number of iterations of BA (only for monocular initializer)
const unsigned int num_ba_iters_;
//! initial scaling factor (only for monocular initializer)
const float scaling_factor_;


// src/openvslam/module/initializer.cc:16
initializer::initializer(const camera::setup_type_t setup_type,
                         data::map_database* map_db, data::bow_database* bow_db,
                         const YAML::Node& yaml_node)
        : setup_type_(setup_type), map_db_(map_db), bow_db_(bow_db),
          num_ransac_iters_(yaml_node["Initializer.num_ransac_iterations"].as<unsigned int>(100)),
          min_num_triangulated_(yaml_node["Initializer.num_min_triangulated_pts"].as<unsigned int>(50)),
          parallax_deg_thr_(yaml_node["Initializer.parallax_deg_threshold"].as<float>(1.0)),
          reproj_err_thr_(yaml_node["Initializer.reprojection_error_threshold"].as<float>(4.0)),
          num_ba_iters_(yaml_node["Initializer.num_ba_iterations"].as<unsigned int>(20)),
          scaling_factor_(yaml_node["Initializer.scaling_factor"].as<float>(1.0)) {
    spdlog::debug("CONSTRUCT: module::initializer");
}

使用不同的相机类型,初始化的方法也不相同,openvslam使用了perspective和bearing_vector两种初始化方法。

// src/openvslam/module/initializer.cc:91
void initializer::create_initializer(data::frame& curr_frm) {
    // 将当前帧设置为初始化过程中的参考帧
    init_frm_ = data::frame(curr_frm);

    // 将当前帧的特征点当作previously matched coordinates
    prev_matched_coords_.resize(init_frm_.undist_keypts_.size());
    for (unsigned int i = 0; i < init_frm_.undist_keypts_.size(); ++i) {
        prev_matched_coords_.at(i) = init_frm_.undist_keypts_.at(i).pt;
    }

    // initialize matchings (init_idx -> curr_idx)
    std::fill(init_matches_.begin(), init_matches_.end(), -1);

    // build a initializer
    initializer_.reset(nullptr);
    switch (init_frm_.camera_->model_type_) {
        case camera::model_type_t::Perspective:
        case camera::model_type_t::Fisheye: {
            initializer_ = std::unique_ptr<initialize::perspective>(new initialize::perspective(init_frm_,
                                                                                                num_ransac_iters_, min_num_triangulated_,
                                                                                                parallax_deg_thr_, reproj_err_thr_));
            break;
        }
        case camera::model_type_t::Equirectangular: {
            initializer_ = std::unique_ptr<initialize::bearing_vector>(new initialize::bearing_vector(init_frm_,
                                                                                                      num_ransac_iters_,            min_num_triangulated_,
                                                                                                      parallax_deg_thr_, reproj_err_thr_));
            break;
        }
    }
    // 设置状态为初始化状态
    state_ = initializer_state_t::Initializing;
}

执行完上面的函数后回直接直接退出,然后读取下一帧图像,进入初始化阶段。下面的匹配过程,在上一篇已经详细讲过了,有一点需要注意在匹配完成后,会将匹配到的点的prev_matched_coords_改为当前帧的特征点座标。如果匹配到的点数小于min_num_triangulated_(这里是50),则直接重置初始化,会把下一帧当作初始化的参考帧。

bool initializer::try_initialize_for_monocular(data::frame& curr_frm) {
    assert(state_ == initializer_state_t::Initializing);

    match::area matcher(0.9, true);
    const auto num_matches = matcher.match_in_consistent_area(init_frm_, curr_frm, prev_matched_coords_, init_matches_, 100);

    if (num_matches < min_num_triangulated_) {
        // rebuild the initializer with the next frame
        reset();
        return false;
    }

    // try to initialize with the current frame
    assert(initializer_);
    return initializer_->initialize(curr_frm, init_matches_);
}

初始化过程

通过计算单应矩阵和基础矩阵,评估出两帧之间的变换矩阵。首先搞清楚几个基本概念。

基础(Fundamental)矩阵

1779232-20190904182609369-1539721313.png

假设\(I1\)\(I2\)为相邻帧,\(p1\)\(p2\)为相邻帧匹配到的特征点,P为特征点的空间位置。対极约束描述了图像中特征点位置与帧间运动信息之间的关系。用过几何计算我们可以得到如下公式(对极约束)。具体推导可以参考两视图对极约束-基础矩阵:

\[p_2^TK^{-T}t^{\wedge }RK^{-1}p_1=0\]

定义本质矩阵\(E=t^{\wedge }R\),基础矩阵\(F=K^{-T}EK\)。通过匹配点对儿的像素位置可以计算出\(E或F\),进而计算出\(R,t\)
此外,假设相邻相机只做了旋转运动,即t为0,可以看到対极约束对于任意R都成立,因此想要通过对极约束评估相机运动内在要求不能只是纯旋转运动(可以使用单应矩阵来求解)。

单应Homography

单应(Homography)是射影几何中的概念,又称为射影变换。它把一个射影平面上的点(三维齐次矢量)映射到另一个射影平面上,并且把直线映射为直线,具有保线性质。总的来说,单应是关于三维齐次矢量的一种线性变换,可以用一个3×3的非奇异矩阵\(H\)表示:

\[ \begin{pmatrix}u_1\\ v_1\\ 1\end{pmatrix}= \begin{pmatrix}h_{11} & h_{12} & h_{13}\\h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{pmatrix} \begin{pmatrix}u_2\\ v_2\\ 1\end{pmatrix} \]
其中,\((u1,v1,1)^T\)表示图像1中的像点,\((u2,v2,1)^T\)是图像2中的像点,也就是可以通过单应矩阵H将图像2变换到图像1,描述的是两个平面之间的映射关系

1779232-20190904182622149-1016813479.png

上图表示场景中的平面\(π\)在两相机的成像,设平面\(π\)在第一个相机坐标系下的单位法向量为\(n^T\),其到第一个相机中心(坐标原点)的距离为\(d\),则平面\(π\)可表示为:

\[n^TX_1=d\]
其中,\(X_1\)是三维点P在第一相机坐标系下的坐标,其在第二个相机坐标系下的坐标为\(X_2\),则

\[X_2 = RX_1 + t \\ X_2 = RX_1 + t\frac{1}{d}n^TX_1=(R+t\frac{1}{d}n^T)X_1=HX_1 \\ H = R+t\frac{1}{d}n^T\]
假设\(p_1,p_2\)\(X_1,X_2\)对应的图像上的点,则

\[X_1=K^{-1}p_1, X_2=K^{-2}p_1\\ H = K(R+t\frac{1}{d}n^T)K^{-1}\]
这样求解出\(H\)便可以求解出\(R,t\),并却\(t=0\)也不影响求解R。

实践

在实际中,通常会同时计算H和F。

\\ src/openvslam/initialize/perspective.cc:27
bool perspective::initialize(const data::frame& cur_frm, const std::vector<int>& ref_matches_with_cur)
{
    ...

    // compute H and F matrices
    auto homography_solver = solve::homography_solver(ref_undist_keypts_, cur_undist_keypts_, ref_cur_matches_, 1.0);
    auto fundamental_solver = solve::fundamental_solver(ref_undist_keypts_, cur_undist_keypts_, ref_cur_matches_, 1.0);
    std::thread thread_for_H(&solve::homography_solver::find_via_ransac, &homography_solver, num_ransac_iters_, true);
    std::thread thread_for_F(&solve::fundamental_solver::find_via_ransac, &fundamental_solver, num_ransac_iters_, true);
    thread_for_H.join();
    thread_for_F.join();
    ...
}
初始化
    使用两个线程分别计算H和F矩阵
        homography_solver::find_via_ransac
        fundamental_solver::find_via_ransac
    通过判断0.4<rel_score_H = score_H / (score_H + score_F来决定用H还是F来评估R,t,
    在评估的过程中还会通过三角化确定特征点的空间位置信息
    通过一些列复杂的筛选得出到满足条件的R,t即算完成初始化

看完下面的文章再回过头来看这段话。总的来说初始化过程涉及到多视几何的基础内容很多,openvlsam的实现很大程度上都是借鉴ORB2的实现方法(三角化除外)。可以看到由于要求前后帧(可以中间隔若干帧)特征点有一定的视差,想要成功的初始化就一定要发生位移。由于同时评估H和F矩阵,纯旋转也有初始化成功的可能性,但是需要有比较多的特征点在相同的平面上。不过最好还是就有旋转又有平移吧。这里在评估过程中都是采用归一化平面上的特征点(没有深度信息),所以得到的t是不知道其物理尺度的,然后三角化又是基于R,t求解的,因此特征点的空间位置值,也是无法知道其物理尺度的,可以认为尺度和t一致。

homography_solver::find_via_ransac

首先正则化特征点,目的是为了后面使用RANSAC(就是随即从大样本集抽取小样本集用于求解问题的方法)计算SVD时得到更一致的解决,消除特征点在图像中位置分布对结果的影响。更详细的解释可参考《Multiple View Geometry in Computer Vision 》P104 “4.4 Transformation invariance and normalization”。
openvslam采样的方法略有不同,分析如下。

\\src/openvslam/solve/common.cc:6
void normalize(const std::vector<cv::KeyPoint>& keypts, std::vector<cv::Point2f>& normalized_pts, Mat33_t& transform) {
计算单应矩阵
    正则化特征点
    循环num_ransac_iters_=100次
        生成8个点的RANSAC序列
        计算正则化特征点的单应矩阵compute_H_21
        计算特征点的单应矩阵
        评估当前求解出单应矩阵的好坏,更新最好的结果
    将筛选过的好的点重新评估H矩阵,得到最优结果

正则化特征点

正则化的公式如下,还是比较直观的。

\[x_i^{\prime} = {x_i - \bar{x} \over \sigma_x},y_i^{\prime} = {y_i - \bar{y} \over \sigma_y} \\ \bar{x} = {\Sigma{x_i} \over N},\bar{y} = {\Sigma{y_i} \over N} \\ \sigma_x = {\Sigma{\left|x_i - \bar{x}\right|} \over N}, \sigma_y = {\Sigma{\left|y_i - \bar{y}\right|} \over N} \\ \begin{pmatrix}x_i^{\prime} \\ y_i^{\prime} \\ 1\end{pmatrix}= \begin{pmatrix}1/\sigma_x & 0 & -\frac{\bar{x}}{\sigma_x} \\ 0 & 1/\sigma_y & -\frac{\bar{y}}{\sigma_y} \\ 0 & 0 & 1\end{pmatrix} \begin{pmatrix}x \\ y \\ 1\end{pmatrix}=T\begin{pmatrix}x \\ y \\ 1\end{pmatrix}\]
\(x_i^{\prime},y_i^{\prime}\)为正则化后的座标值,T就是正则化矩阵。

compute_H_21

参考https://www.uio.no/studier/emner/matnat/its/UNIK4690/v16/forelesninger/lecture_4_3-estimating-homographies-from-feature-correspondences.pdf

计算特征点的单应矩阵

程序中normalized_H_21表示则正则化的参考帧到当前帧的单应矩阵。
H_21_in_sac: 帧1->帧2的homography, 注意21表示的是1->2。

\[p^{\prime}_{cur} = T_{cur}p_{cur} \\ p^{\prime}_{ref} = T_{ref}p_{ref} \\ \]
\(T_{cur},T_{ref}\)是当前帧特征点和参考帧特征点的正则化矩阵。

\[p^{\prime}_{cur}=H^{\prime}_{cr}p^{\prime}_{ref}\]

\(H^{\prime}_{rc}\)是正则化当前帧特征点与正则化参考帧特征点的单应矩阵。展开得到:

\[ T_{cur}p_{cur}=H^{\prime}_{cr}T_{ref}p_{ref} \\ p_{cur}=T^{-1}_{cur}H^{\prime}_{cr}T_{ref}p_{ref} \]
因此当前帧特征点与参考帧特征点的单应矩阵\(H_{cr}\)为:

\[H_{cr}=T^{-1}_{cur}H^{\prime}_{cr}T_{ref}\]

评估当前求解出单应矩阵的好坏

说实话,研究了半天也没搞清楚是如何和卡方检验联系起来的。在我看来就是定义了一个最小重投影误差门限(5.991),重投影误差小于门限就标记为inlier, 将最好的结果保存下来。这里面作者只累加小于门限的重投影误差,即score += 门限值 - 重投影误差,这个差值是>0的,这样做的好处大家可以思考下。

fundamental_solver::find_via_ransac

同样是先正则化特征点,然后采用RANSAC的方法计算F矩阵compute_F_21,过程和计算H矩阵完全一致。

从F或H恢复R,t

//src/openvslam/initialize/perspective.cc:91
bool perspective::reconstruct_with_H(const Mat33_t& H_ref_to_cur, const std::vector<bool>& is_inlier_match)
//src/openvslam/initialize/perspective.cc:114
bool perspective::reconstruct_with_F(const Mat33_t& F_ref_to_cur, const std::vector<bool>& is_inlier_match)

reconstruct_with_H: Motion and structure from motion in a piecewise planar environment (Faugeras et al. in IJPRAI 1988)
reconstruct_with_F: https://en.wikipedia.org/wiki/Essential_matrix#Determining_R_and_t_from_E

在得到若干组候选的R,t后,需要计算找到最佳的R,t。

// src/openvslam/initialize/base.cc:31
bool base::find_most_plausible_pose
寻找最佳位姿
    逐个候选位姿进行check_pose
    选取有效点最多的那组位姿,做以下判断:
    1.有效点数必须大于min_num_triangulated_(50);
    2.一个好的结果应该是只有一组有比较多的有效点,,如果发现有很多组都有个数相近的有效点,则这些位姿都不对;
    3.视差不能太小,因为太小的视差评估出的深度不可靠,这里的门限parallax_deg_thr_=1度;

在评估R,t的同时会对特征点进行三角化,注意保存到triangulated_pts_的点是特征点在参考帧下的三维坐标

check_pose

// src/openvslam/initialize/base.cc:86
unsigned int base::check_pose
循环所有的匹配点
    三角化计算得到特征点在参考帧下的三维坐标
    计算视差角的余弦值(向量内积的方法)
    排除视差小于0.5度和深度为负数的三维坐标
    验证特征点是否在参考帧和当前帧中可见,重投影误差L2 < 16
    以上条件都满足的点才认为有效
对视差排序后返回第50小或者(个数小于50则返回最小)的视差

Triangulate(三角化)

问题

  1. 评估H和F矩阵的好坏时是如何转为卡方检验的?
  2. triangulator::triangulate还没有彻底搞明白?

转载于:https://www.cnblogs.com/hardjet/p/11460822.html

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

第三篇 视觉里程计(VO)的初始化过程以及openvslam中的相关实现详解 的相关文章

  • 踩坑记录

    ERROR Session line number was not unique in database History logging moved to new session 66 在生成tfrecord时 总报如下错误 找了很长时间
  • git强制覆盖本地代码

    git强制覆盖本地 xff1a git fetch all 拉取所有更新 git reset hard origin master 本地代码同步线上最新版本 会覆盖本地所有与远程仓库上同名的文件 git pull git强制覆盖本地命令 x
  • 【毕业设计】基于STM32及OpenMV的云台追踪装置

    目录 修改记录1 摘 要2 整体功能分析3 硬件选型3 1 OpenMV4 Cam H73 2 STM32F103ZET63 3 DS3120舵机3 4 LED补光板3 5 供电及稳压3 6 硬件连接 4 软件功能实现4 1 OpenMV部
  • firewall-cmd 使用总结

    firewalld的简要说明 firewalld firewall cmd firewall offline cmd它们Python脚本 xff0c 通过定义的在 usr lib firewalld下面的xml配置信息 xff0c 在启动时
  • 机架与机柜

    随着计算机网络的发展 xff0c 数据中心的服务器以及网络通信设备等IT设施 xff0c 正逐步向着网络化 机架化的方向发展 机架是用于综合布线 xff0c 安装配线架和理线架 xff0c 实现对电缆和光缆布线系统的管理 在网络机柜中不具备
  • cmake和makefile区别和cmake指定编译器(cmake -G)

    一 cmake和makefile区别 要说明区别 xff0c 我们先要区分下面三类工具 xff1a 1 项目构建生成工具 首先cmake是项目构建生成工具 xff0c cmake的代码可以与平台系统和编译器无关 类似cmake的工具还有au
  • Gazebo使用过程中的问题

    1 运行命令gazebo没有反应 在虚拟机安装好gazebo后 xff0c 使用ALT 43 F2打开命令行运行命令gazebo没有反应 首先尝试内存不够的情况 xff0c 给虚拟机加到了4g内存 没有用 xff0c 运行gazebo还是没
  • 一张图理解板卡硬件调试流程

    最近在调试从焊板厂打样回来的板卡 xff0c 简单总结了下板卡的硬件测试流程 xff0c 如下图 xff1a 写在后面的话 xff1a 我之所以选择做技术这一行 xff0c 是觉得做技术的人简单 直接 xff0c 当你面对一个技术问题 xf
  • 关于Linux进程你所需要知道的一切都在这里!!

    文章目录 进程简单了解进程查看进程进程ID父进程ID父进程与子进程 程序与进程程序进程程序变成进程总结 进程状态进程状态转换启动新进程system fork exce系列函数 终止进程等待进程wait waitpid 进程 说明 xff1a
  • MQTT协议简介及协议原理

    文章目录 MQTT协议MQTT协议简介MQTT通信模型MQTT客户端的功能 xff1a MQTT客户服务器功能 xff1a 消息主题与服务质量MQTT控制报文固定报头可变报头CONNECT报文CONNACK报文 有效载荷 MQTT协议 MQ
  • 你不得不看的图文并茂的MQTT协议通信过程!!!

    文章目录 MQTT连接服务器MQTT订阅主题MQTT发布消息服务质量等级 QoSQoS0的PUBLISH控制报文QoS1的PUBLISH控制报文QoS2的PUBLISH控制报文 取消订阅断开连接 MQTT连接服务器 客户端到服务器的网络连接
  • 一个高性能、高稳定性的跨平台MQTT客户端——mqttclient简介与使用

    文章目录 mqttclient简介与使用优势 xff1a 在线代码生成工具占用资源大小整体框架支持的平台版本问题版权和许可linux平台下测试使用安装cmake xff1a 测试程序编译 amp 运行编译成动态库libmqttclient
  • 一个高性能、高稳定性的跨平台MQTT客户端——mqttclient代码生产工具介绍

    文章目录 mqttclient代码生产工具介绍连接参数配置订阅主题相关的代码配置发布消息相关的代码配置生成代码 mqttclient代码生产工具介绍 mqttclient代码生产工具主要是用于配置MQTT的参数 xff0c 并且生成相应的代
  • 一个高性能、高稳定性的跨平台MQTT客户端——mqttclient配置及裁剪工具

    文章目录 mqttclient配置及裁剪工具salof相关的配置使用mqttclient裁剪配置工具 mqttclient配置及裁剪工具 MQTT TOPIC LEN MAX 配置客户端支持最大的主题名长度 xff0c 主题是支持通配符的
  • 一个高性能、高稳定性的跨平台MQTT客户端——mqttclient设计与实现方式

    文章目录 mqttclient设计与实现方式设计思想API接口MQTT客户端的核心结构mqttclient实现申请一个mqtt客户端释放已申请的mqtt客户端设置MQTT客户端的信息连接服务器订阅报文取消订阅发布报文内部线程核心的处理函数发
  • mqtt连接百度天工物接入平台

    文章目录 mqtt连接到百度天工物接入百度天工物接入简介使用百度天工物接入创建项目创建策略创建身份创建用户测试连接 MQTT软件测试连接手动安装相关的依赖包拉取mqttclient仓库简单介绍mqttclient仓库文件夹编译运行测试代码使
  • mqttclient连接到OneNET云平台

    文章目录 mqttclient连接到OneNET云平台使用OneNET测试连接手动安装相关的依赖包拉取mqttclient仓库简单介绍mqttclient仓库文件夹编译运行代码使用到的API mqttclient连接到OneNET云平台 有
  • 2022年最新《谷粒学院开发教程》:1 - 构建工程篇

    资料资料资料地址代码地址 后台管理系统目录前台展示系统目录1 构建工程篇7 渲染前台篇2 前后交互篇8 前台登录篇3 文件上传篇9 前台课程篇4 课程管理篇10 前台支付篇5 章节管理篇11 统计分析篇6 微服务治理12 项目完结篇 目录
  • MQTT移植到stm32开发板——使用RT-Thread操作系统

    文章目录 mqttclientENV介绍env工具下载安装通过env移植MQTT客户端打开 env 控制台打开env并更新软件包列表移植MQTT客户端 编写自己的代码 xff1a 连接参数配置订阅主题相关的代码配置发布消息相关的代码配置生成
  • MQTT移植到stm32开发板——使用TencentOS tiny操作系统

    mqttclient 一个高性能 高稳定性的跨平台MQTT客户端 一个高性能 高稳定性的跨平台MQTT客户端 xff0c 基于socket API之上开发 xff0c 可以在嵌入式设备 xff08 FreeRTOS LiteOS RT Th

随机推荐

  • MQTT移植到stm32开发板——使用FreeRTOS操作系统

    mqttclient 一个高性能 高稳定性的跨平台MQTT客户端 一个高性能 高稳定性的跨平台MQTT客户端 xff0c 基于socket API之上开发 xff0c 可以在嵌入式设备 xff08 FreeRTOS LiteOS RT Th
  • 深入了解C++多态的原理及实现方式

    文章目录 前言关于多态函数承载方式虚函数方式 前言 需要深入了解C C 43 43 语言的基础之上再看此文章 关于多态 具有多种形态 xff0c 调用同一个方法会随上下文不同而产生不同的结果 xff0c 多态有静态多态与动态多态两种 函数承
  • select、poll、epoll的原理与区别

    文章目录 前言同步I O异步I O阻塞I O非阻塞I O多路复用I Oselectselect整个处理过程如下select函数原型 xff1a select的缺点 pollepollepoll的原理epoll的操作模式epoll的函数epo
  • MQTT连接到阿里云物联

    连接到阿里云物联 既然懂得专门连接百度天工物接入 xff0c 那么连接阿里云物联其实也是一样的 xff0c 因为都是基于MQTT协议进行通信的 xff0c 首先打开阿里云物联 xff1a https iot console aliyun c
  • Ubuntu20 安装微信

    1 安装deepin wine span class token function git span clone span class token string 34 https gitee com wszqkzqk deepin wine
  • 如果让你设计哈希表.....

    先确定选题 xff0c 待写
  • STM32进阶之串口环形缓冲区实现

    如需转载请说明出处 xff1a STM32进阶之串口环形缓冲区实现 队列的概念 在此之前 xff0c 我们来回顾一下队列的基本概念 xff1a 队列 Queue xff1a 是一种先进先出 First In First Out 简称 FIF
  • 在ROS中实现基于darknet_ros的目标检测

    最近用自己的渣渣笔记本电脑跑了一下yolo目标检测在ROS中的实现 xff0c 实现了用摄像头进行目标检测的任务 以下为笔记 xff0c 防止遗忘 1 使用的环境和平台 Ubuntu 16 04 LTS 43 ROS 43 Yolo 2 实
  • 01 FreeRTOS任务实例

    FreeRTOS任务实例 一 简要说明1 官方例程下载 二 学习任务的创建1 创建一个任务2 任务中传递参数3 不同优先级的任务 三 任务的延时1 使用阻塞式延时2 精确的任务定时3 低优先级任务无延时 xff0c 高优先级延时 一 简要说
  • opencv 读取相机图像+ros发布图像

    usr bin python2 coding 61 utf 8 import cv2 import numpy as np from std msgs msg import Header from sensor msgs msg impor
  • 无人机小知识:Pitch Yaw Roll的经典解释

    无人机的一个最基本的基础知识就是对Pitch Yaw Roll三个方向的辨别 查了下网上很多资料 xff0c 都采用的下面的几张图进行说明 xff0c 我觉得很直观 xff0c 记录一下 xff0c 当做备忘录 机体坐标系 xff1a 固定
  • 编译警告:warning: Clock skew detected. Your build may be incomplete.

    在编译darknet ros程序时 xff0c 遇到如下警告 xff1a make 2 Warning File 39 darknet ros darknet ros CMakeFiles darknet ros lib dir depen
  • Yolo v4系列学习(四)Yolo v4移植ROS

    目录 1 建立名为catkin ws的工作空间2 下载darknet ros包3 下载Yolo v4源码4 开始编译5 漫长的解决Bug的过程6 配置Yolo v4 43 ROS7 开始使用Yolo v4 43 ROS8 调参参考网址 1
  • C++(14):make_unique

    C 43 43 14增加了make unique xff0c 用于创建unique ptr对象 xff1a include lt iostream gt include lt memory gt using namespace std in
  • Git:修改commit内容

    在提交code xff0c 使用git commit编写注释时 xff0c 如果发现注释的内容不太准确 xff0c 需要修改怎么办 xff1f 比如 xff0c 当前写的注释是 xff1a this is fix for XXX 在git
  • ros安装详细教程+问题解决

    官方英文连接 xff1a melodic Installation Ubuntu ROS Wiki 如果一下命令有疑问 xff1a 见上方官方文档 xff0c 也很简洁 ROS有许多版本 xff0c ubuntu20 04对应的版本Noet
  • 激光slam 理论详解(一)

    什么是slam 技术 slam Simultaneous Localization and Mapping 叫即时定位与建图 xff0c 它主要的作用是让机器人在未知的环境中 xff0c 完成定位 xff08 Localization xf
  • gazebo模型下载以及配置

    最近在学习ROS xff0c 主要是为了结合SLAM仿真使用 启动gazebo命令 roscore 在另一个终端执行 gazebo 就可以进入清爽的gazebo界面 xff08 如果屏幕出现黑屏并不是安装错误可以稍微等待一会 xff09 x
  • ROS中在一个包里引用其他包内的自定义消息或服务

    假设我们要在a package中引用b package里自定义的my message msg 方法1 可直接通过添加依赖的方式解决 首先在创建包时添加b package catkin create pkg std msgs roscpp r
  • 第三篇 视觉里程计(VO)的初始化过程以及openvslam中的相关实现详解

    视觉里程计 xff08 Visual Odometry VO xff09 xff0c 通过使用相机提供的连续帧图像信息 xff08 以及局部地图 xff0c 先不考虑 xff09 来估计相邻帧的相机运动 xff0c 将这些相对运行转换为以第