4.3.2 C++ 平面拟合的实现

news2024/11/27 2:23:44

4.3.2 C++ 平面拟合的实现

参考教程:

gaoxiang12/slam_in_autonomous_driving: 《自动驾驶中的SLAM技术》对应开源代码 (github.com)

Eigen打印输出_打印eigen矩阵-CSDN博客

1. 编写 Plane fitting

1.1 创建文件夹

通过终端创建一个名为Plane_fitting的文件夹以保存我们的VSCode项目,在/Plane_fitting目录下打开vscode

rosnoetic@rosnoetic-VirtualBox:~$ mkdir -p Plane_fitting

rosnoetic@rosnoetic-VirtualBox:~$ cd Plane_fitting/

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting$ code .

1.2 编写平面拟合程序

新建文件linear_fitting.cpp

使用快速 SVD 分解,仅计算 A 矩阵 SVD 结果的最后一列。在计算完成后,将点的具体取值代入本方程,要求它们的平方误差不超过预设的阈值。下面这段测试程序把随机生成的平面参数作为真值,在平面上取若干个点,再加入噪声,做平面拟合。

linear_fitting.cpp粘贴如下代码并保存(Ctrl+S)

// 引入Eigen头文件与常用类型
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <iostream>

Eigen::IOFormat HeavyFmt(Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");

template <typename S>
bool FitPlane(std::vector<Eigen::Matrix<S, 3, 1>>& data, Eigen::Matrix<S, 4, 1>& plane_coeffs, double eps = 1e-2) {
    if (data.size() < 3) {
        return false;
    }

    Eigen::MatrixXd A(data.size(), 4);
    for (int i = 0; i < data.size(); ++i) {
        A.row(i).head<3>() = data[i].transpose();
        A.row(i)[3] = 1.0;
    }

    Eigen::JacobiSVD<Eigen::MatrixXd>  svd(A, Eigen::ComputeThinV);
    plane_coeffs = svd.matrixV().col(3);

    // check error eps
    for (int i = 0; i < data.size(); ++i) {
        double err = plane_coeffs.template head<3>().dot(data[i]) + plane_coeffs[3];
        if (err * err > eps) {
            return false;
        }
    }

    return true;
}

int main(int argc, char argv) {

    Eigen::Vector4d true_plane_coeffs(0.1, 0.2, 0.3, 0.4);
    true_plane_coeffs.normalize();

    std::vector<Eigen::Vector3d> points;

    // 生成平面中的点的数量
    int FLAGS_num_tested_points_plane = 10;
    double FLAGS_noise_sigma = 0.01;

    // 随机生成仿真平面点
    cv::RNG rng;
    for (int i = 0; i < FLAGS_num_tested_points_plane; ++i) {
        // 先生成一个随机点,计算第四维,增加噪声,再归一化
        Eigen::Vector3d p(rng.uniform(0.0, 1.0), rng.uniform(0.0, 1.0), rng.uniform(0.0, 1.0));

        double n4 = -p.dot(true_plane_coeffs.head<3>()) / true_plane_coeffs[3];

        p = p / (n4 + std::numeric_limits<double>::min());  // 防止除零

        p += Eigen::Vector3d(rng.gaussian(FLAGS_noise_sigma),
                                                    rng.gaussian(FLAGS_noise_sigma), 
                                                    rng.gaussian(FLAGS_noise_sigma));

        points.emplace_back(p);

        // 验证在平面上
        printf("res of p: %.2f\n",p.dot(true_plane_coeffs.head<3>()) + true_plane_coeffs[3] );
    }

    Eigen::Vector4d estimated_plane_coeffs;
    FitPlane(points, estimated_plane_coeffs);
    estimated_plane_coeffs = estimated_plane_coeffs.transpose();
    std::cout << estimated_plane_coeffs.format(HeavyFmt) << std::endl;

    return 0;

}

2. 新建 CMakeLists.txt 文件

新建CMakeLists.txt文件

CMakeLists.txt中添加如下内容:

# 声明要求的cmake最低版本
cmake_minimum_required(VERSION 2.8 )

# 声明一个cmake工程
project(Plane_fitting)

# 添加C++ 11支持
set(CMAKE_CXX_FLAGS "-std=c++11")

# 寻找OpenCV库
find_package( OpenCV REQUIRED)
# 添加头文件
include_directories("/usr/include/eigen3"  ${OpenCV_INCLUDE_DIRS})

# 添加一个可执行文件
add_executable(linear_fitting linear_fitting.cpp)
# 链接OpenCV库
target_link_libraries(linear_fitting ${OpenCV_LIBS})

3. 编译并执行

ctrl+alt+T打开终端,执行如下指令进行cmake编译

rosnoetic@rosnoetic-VirtualBox:~$ cd Plane_fitting/

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting$ mkdir build

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting$ cd build/

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting/build$ cmake ..

接着make对工程进行编译

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting/build$ make

进一步的调用可执行文件linear_fitting

rosnoetic@rosnoetic-VirtualBox:~/Plane_fitting/build$ ./linear_fitting 

res of p: -0.00
res of p: -0.00
res of p: -0.01
res of p: 0.00
res of p: 0.00
res of p: -0.00
res of p: 0.01
res of p: 0.00
res of p: 0.01
res of p: 0.00
[[0.186755046854881];
 [0.363655524983479];
 [0.546691644450618];
 [0.730756770417559]]

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

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

相关文章

Cookie和Session的区别(详细讲解)

Session 和 Cookie 的区别 在网络通信过程中&#xff0c;使用的是HTTP协议&#xff0c;它是一种无状态协议&#xff0c;比如&#xff0c;在登录一个网站时&#xff0c;登录成功后&#xff0c;之后在访问这个网站的其他页面时&#xff0c;都需要重新登录&#xff0c;无法识别出…

[240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能

目录 &#x1f4c3;Changelog✨ gtb✨ cd✨ chat✨ hashdir &#x1f4c3;Changelog ✨ gtb 调整了 fzf 预览窗口中书籍文本的显示效果&#xff0c;通过识别文本中的特殊字符、日期、章节标题等信息&#xff0c;为其赋予不同的颜色。 ✨ cd cd 模块新增功能&#xff1a;在找…

网络编程day03 20240813

一、相关练习 1、通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 机械臂需要发送16进制数&#xff0c;共5个字节&#xff0c;协议如下&#xff1a; 0xff 0x0…

数据库核心技术:存储与索引概览

文章目录 存储与索引技术概览存储结构索引技术 MySQL存储结构索引技术事务与锁优势 PostgreSQL存储结构索引技术事务与锁优势 Oracle存储结构索引技术事务与锁优势 SQL Server存储结构索引技术事务与锁优势 选型考量存储结构索引技术事务与锁的支持综合因素未来趋势 结语 数据库…

【微信小程序】网络数据请求

1. 小程序中网络数据请求的限制 2. 配置 request 合法域名 3. 发起 GET 请求 调用微信小程序提供的 wx.request() 方法,可以发起 GET 数据请求,示例代码如下: 4. 发起 POST 请求 调用微信小程序提供的 wx.request() 方法,可以发起 POST 数据请求,示例代码如下: 5. …

今日头条的账号id在哪里看(网页版)

今日头条的账号id在哪里看&#xff08;网页版&#xff09; 1.https://mp.toutiao.com/profile_v4/index2.登录今日头条账号3.设置->头条号ID 1.https://mp.toutiao.com/profile_v4/index 2.登录今日头条账号 3.设置->头条号ID 打开下方链接&#xff1a; https://mp.to…

进程的执行与结束

一、文件的读写 1、fork之前open 子进程会继承父进程已打开的文件相关信息 所以&#xff0c;此时父子进程会影响一个offset值 2、fork之后open 父子进程各自有各自的打开文件的信息&#xff0c;相互之间不会有影响。 二、 进程的执行 //进程运行时&#xff0c;典型场景 1…

量化策略开发步骤系列(3)关键投资组合指标

量化策略开发步骤系列&#xff08;3&#xff09;关键投资组合指标 投资组合指标波动性夏普比率最大回撤赢/输百分比每笔交易的平均利润/亏损每期交易次数风险价值&#xff08;VaR&#xff09; 这是量化交易系列文章的第二系列——量化策略开发步骤&#xff0c;第一系列请参考专…

Prometheus+Grafana-3-Nginx监控-Redis监控

一、监控Nginx 1.Nginx需要开启stub_status 这里我的nginx容器名为mynignx&#xff0c;进入容器查看。 docker exec -it mynginx bash #进入容器 nginx -v 2>&1 | grep -o with-http_stub_status_module #查看 修改nginx.conf ...location /stub_status {stub_stat…

华为od统一考试B卷【AI面板识别】python实现

思路 n int(input())class Light:def __init__(self, id, x1, y1, x2, y2):self.id idself.x1 x1self.y1 y1self.x2 x2self.y2 y2self.height y2 - y1def get_lights_info(n):lights []for _ in range(n):id, x1, y1, x2, y2 map(int, input().strip().split())lights…

量产工具——复习及改进(后附百问网课程视频链接)

目录 一、函数的使用 1.显示系统 1.1 mmap函数 2.输入系统 2.1 ts_setup()函数 2.2 ts_read()函数 2.3 socket()函数 2.4 bind()函数 2.5 recvfrom()函数 2.6 inet_aton()函数 2.7 sendto()函数 2.8 pthread_create()函数 2.9 pthread_cond_signal()函数 2.10 pthre…

思科路由器的基本配置1

#路由技术基础# #路由器的基本配置1# #1调整超级终端的参数 #2退出配置向导&#xff0c;输入“NO”即可进入正常配置方式 #3路由器的模式切换 Router> &#xff01;进入用户模式 Router>enable &#xff01;进入特权模…

opencv-python实战项目一:获取鼠标框选区域的颜色

文章目录 一&#xff1a;简介二&#xff1a;框选区域选择颜色方案三、算法实现步骤3.1 按鼠标事件截取图像3.2将图像模糊后转化为hsv并求均值3.3 判断hsv处于何种颜色 四&#xff1a;整体代码实现五&#xff0c;效果: 一&#xff1a;简介 在计算机视觉领域&#xff0c;颜色检测…

19-ESP32-C3加大固件储存区

1默认编译情况。 2、改flash4M。ESP-IDF Partition Table Editor修改。 3、设置输入Partition Table 改自定义.CSV。保存。 4、查看命令输入Partition Table Editor打开-分区表编辑器UI。按图片增加。 nvs,data,nvs,0x9000,0x6000,, phy_init,data,phy,0xF000,0x1000,, factory…

计算机毕业设计Hadoop+Hive居民用电量分析 居民用电量可视化 电量爬虫 机器学习 深度学习 大数据毕业设计 Spark

《Hadoop居民用电量分析》开题报告 一、研究背景与意义 能源问题在全球范围内一直是热点议题&#xff0c;尤其是随着居民生活水平的提高和城市化进程的加快&#xff0c;居民用电量急剧增长&#xff0c;对电力系统的稳定运行和能源管理提出了更高要求。如何科学合理地管理和分…

Hive3:识别内部表、外部表及相互转换

一、识别方法 查看内部表信息 desc formatted stu;查看外部表信息 desc formatted test_ext1;通过Table Type对应的值&#xff0c;我们可以区分外部表和内部表。 二、相互转换 内部表转外部表 alter table stu set tblproperties(EXTERNALTRUE);外部表转内部表 alter ta…

PCIe学习笔记(21)

读请求的数据返回&#xff08;Data Return for Read Requests&#xff09; •针对内存读取请求的单个完成可能提供少于请求的全部数据量&#xff0c;只要对于给定请求的所有完成在组合起来时返回了读取请求中请求的数据量。 ◦不同请求的完成不能合并。 ◦I/O和Configuratio…

Qt QCustomPlot 图形库详解

文章目录 原文1. 下载qcustomplot.h与qcustomplot.cpp后,将代码文件拷贝到本地工程,并添加到工程项目2. 看到文件后就是添加成功了3. 在界面中拖拽一个Widget控件,选中并右键选中“提升为”,将原来的Widget控件已成为一个带坐标的 CustomPlot 控件4. 添加printsupport原文 …

【Ai学习】一个技巧,解决99%Comfyui报错!

前言 comfyui以极高灵活度及节点化工作流&#xff0c;深受AI绘画者追捧&#xff0c;每当新的模型开源&#xff0c;comfyui都是最先进行适配。 comfyui高度兼容性及灵活性带来丰富强大的扩展&#xff08;插件&#xff09;生态&#xff0c;同时也带来一系列插件安装的问题&…

Python程序结构

模块 Module 定义&#xff1a;包含一系列数据、函数、类的文件&#xff0c;通常以.py结尾。 作用&#xff1a;让一些相关的数据&#xff0c;函数&#xff0c;类有逻辑的组织在一起&#xff0c;使逻辑结构更加清晰。 有利于多人合作开发。 导入 import 语法&#xff1a; im…