aruco板_基于arucoTag的简单slam

2023-05-16

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "g2o/types/slam3d/types_slam3d.h"

#include "g2o/types/slam3d/vertex_pointxyz.h"

#include "g2o/types/slam3d/vertex_se3.h"

#include "g2o/types/slam3d/edge_se3.h"

#include "g2o/types/slam3d/edge_se3_pointxyz.h"

#include "g2o/core/factory.h"

#include "g2o/core/optimization_algorithm_factory.h"

#include "g2o/core/sparse_optimizer.h"

#include "g2o/core/block_solver.h"

#include "g2o/solvers/dense/linear_solver_dense.h"

#include "g2o/core/optimization_algorithm_levenberg.h"

#include "icp_g2o.hpp"

using namespace std;

using namespace cv;

using namespace Eigen;

using namespace g2o;

//使用图片

//输入当前帧检测到的tag

//维护一张节点地图用于g2o

class ArucoFrame

{

public:

vector landmark_id;

vector<:vector3d> landmarks_pointXYZ;//在相机坐标系下的位置

Eigen::Isometry3d robot_pose;//在map坐标系下的位姿

};

class ArucoMap

{

public:

vector landmark_id;

vector<:vector3d> landmarks_pointXYZ;//在Map坐标系下的位置

};

ArucoMap ArucoMapGlobal;

vector ArucoFrameGlobal;

int id_vertex_pose=0, id_vertex_pointXYZ_start=100;//机器人pose的初始点认为是建图坐标系原点,id从0开始,tag的节点id从100开始。默认机器人pose不可能超过100个

void buildMap(vector< int > &ids, vector< vector< Point2f > > &corners, vector< Vec3d > &rvecs, vector< Vec3d > &tvecs, g2o::SparseOptimizer &optimizer)

{

//获取当前帧里的tag

ArucoFrame ArucoFrame_temp;

if(ids.size() != 0)

{

ArucoFrame_temp.robot_pose = Eigen::Isometry3d::Identity();

for(int i=0; i

{

ArucoFrame_temp.landmark_id.push_back(ids[i]);

//cv转换到eigen下

Mat rot_mat;

Rodrigues(rvecs[i], rot_mat);

Eigen::Matrix3d eigen_r;

Eigen::Vector3d eigen_t;

cv2eigen(rot_mat, eigen_r);

cv2eigen(tvecs[i],eigen_t);

//这里的rt对应的T是从mark坐标系变到相机坐标系

//Point_camera = T_camera-mark * Point_mark

//很重要!!所以这里的四个点是按mark坐标系下的顺序排列的

ArucoFrame_temp.landmarks_pointXYZ.push_back( eigen_r * Eigen::Vector3d(-0.03,0.03,0)+eigen_t );

ArucoFrame_temp.landmarks_pointXYZ.push_back( eigen_r * Eigen::Vector3d(0.03,0.03,0)+eigen_t );

ArucoFrame_temp.landmarks_pointXYZ.push_back( eigen_r * Eigen::Vector3d(0.03,-0.03,0)+eigen_t );

ArucoFrame_temp.landmarks_pointXYZ.push_back( eigen_r * Eigen::Vector3d(-0.03,-0.03,0)+eigen_t );

}

ArucoFrameGlobal.push_back(ArucoFrame_temp);

}

else

return ;

//对地图操作

if(ArucoMapGlobal.landmark_id.size() == 0)//初始化第一帧

{

for(int i=0; i

{

ArucoMapGlobal.landmark_id.push_back(ArucoFrame_temp.landmark_id[i]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(ArucoFrame_temp.landmarks_pointXYZ[i*4+0]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(ArucoFrame_temp.landmarks_pointXYZ[i*4+1]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(ArucoFrame_temp.landmarks_pointXYZ[i*4+2]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(ArucoFrame_temp.landmarks_pointXYZ[i*4+3]);

//添加pose

VertexSE3* v = new VertexSE3;

v->setEstimate(ArucoFrame_temp.robot_pose);

v->setId(id_vertex_pose++);

optimizer.addVertex(v);

//添加landmark和edge

for(int j=0; j<4; j++)

{

VertexPointXYZ* l = new VertexPointXYZ;

l->setEstimate(ArucoFrame_temp.landmarks_pointXYZ[i*4+j]);

l->setFixed(true);

l->setId(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[i]*4+j);//之所以直接用tag的id是因为不会存在相同的tag,因此vertex的序号不会出现一样的。

optimizer.addVertex(l);

EdgeSE3PointXYZ* e = new EdgeSE3PointXYZ;

e->setVertex(0, (optimizer.vertices().find(id_vertex_pose-1))->second);

e->setVertex(1, (optimizer.vertices().find(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[i]*4+j))->second);

e->setMeasurement(ArucoFrame_temp.landmarks_pointXYZ[i*4+0]);

e->setParameterId(0,0);//这句话必须加

optimizer.addEdge(e);

}

}

}

else

{

//寻找当前帧里的tagid是否和map里的id一样

vector id_same, id_different;

for(int i=0; i

{

int j;

for(j=0; j

{

if(ArucoMapGlobal.landmark_id[j] == ArucoFrame_temp.landmark_id[i])

{

id_same.push_back(i);

break;

}

}

if(j == ArucoMapGlobal.landmark_id.size())

id_different.push_back(i);

}

if(id_different.size() != 0)//如果有新的id能看到,就要添加进地图里

{

if(id_same.size() != 0)//必须要同时看到地图里存在的tag以及新的tag,才能将新的tag添加进地图中,因为是根据scan匹配map获得自身位资

{

//先根据icp匹配获得当前帧的位置。

vector<:vector3d> landmarkXYZ_common_map;

vector<:vector3d> landmarkXYZ_common_frame;

for(int i=0; i

{

for(int j=0; j

{

if(ArucoMapGlobal.landmark_id[i] == ArucoFrame_temp.landmark_id[id_same[j]])

{

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+0]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+1]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+2]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+3]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+0]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+1]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+2]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+3]);

break;

}

}

}

Eigen::Isometry3d T;

bundleAdjustment(landmarkXYZ_common_map, landmarkXYZ_common_frame, T);//这个T就是当前摄像头的pose

ArucoFrame_temp.robot_pose = T;

ArucoFrameGlobal.back().robot_pose = T;

//当前摄像头的位姿计算出来以后,更新map中的pose和edge,这一步没有landmark添加进来

VertexSE3* v = new VertexSE3;

v->setEstimate(ArucoFrame_temp.robot_pose);

v->setId(id_vertex_pose++);

optimizer.addVertex(v);

for(int i=0; i

{

for(int j=0; j<4; j++)

{

EdgeSE3PointXYZ* e = new EdgeSE3PointXYZ;

e->setVertex(0, (optimizer.vertices().find(id_vertex_pose-1))->second);

e->setVertex(1, (optimizer.vertices().find(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[id_same[i]]*4+j))->second);

e->setMeasurement(ArucoFrame_temp.landmarks_pointXYZ[id_same[i]*4+j]);

e->setParameterId(0,0);//这句话必须加

optimizer.addEdge(e);

}

}

//更新map中的landmark和edge

for(int i=0; i

{

ArucoMapGlobal.landmark_id.push_back(ArucoFrame_temp.landmark_id[id_different[i]]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(T * ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+0]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(T * ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+1]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(T * ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+2]);

ArucoMapGlobal.landmarks_pointXYZ.push_back(T * ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+3]);

for(int j=0; j<4; j++)

{

VertexPointXYZ* l = new VertexPointXYZ;

l->setEstimate(T * ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+j]);

l->setId(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[id_different[i]]*4+j);

optimizer.addVertex(l);

EdgeSE3PointXYZ* e = new EdgeSE3PointXYZ;

e->setVertex(0, (optimizer.vertices().find(id_vertex_pose-1))->second);

e->setVertex(1, (optimizer.vertices().find(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[id_different[i]]*4+j))->second);

e->setMeasurement(ArucoFrame_temp.landmarks_pointXYZ[id_different[i]*4+j]);

e->setParameterId(0,0);//这句话必须加

optimizer.addEdge(e);

}

}

}

}

else//如果看到的全是存在的tag就添加优化关系

{

vector id_same;

for(int i=0; i

{

int j;

for(j=0; j

{

if(ArucoMapGlobal.landmark_id[j] == ArucoFrame_temp.landmark_id[i])

{

id_same.push_back(i);

break;

}

}

}

//先根据icp匹配获得当前帧的位置。

vector<:vector3d> landmarkXYZ_common_map;

vector<:vector3d> landmarkXYZ_common_frame;

for(int i=0; i

for(int j=0; j

{

if(ArucoMapGlobal.landmark_id[i] == ArucoFrame_temp.landmark_id[id_same[j]])

{

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+0]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+1]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+2]);

landmarkXYZ_common_map.push_back(ArucoMapGlobal.landmarks_pointXYZ[i*4+3]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+0]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+1]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+2]);

landmarkXYZ_common_frame.push_back(ArucoFrame_temp.landmarks_pointXYZ[id_same[j]*4+3]);

break;

}

}

Eigen::Isometry3d T;

bundleAdjustment(landmarkXYZ_common_map, landmarkXYZ_common_frame, T);//这个T就是当前摄像头的pose

ArucoFrame_temp.robot_pose = T;

ArucoFrameGlobal.back().robot_pose = T;

VertexSE3* v = new VertexSE3;

v->setEstimate(ArucoFrame_temp.robot_pose);

v->setId(id_vertex_pose++);

optimizer.addVertex(v);

for(int i=0; i

{

for(int j=0; j<4; j++)

{

EdgeSE3PointXYZ* e = new EdgeSE3PointXYZ;

e->setVertex(0, (optimizer.vertices().find(id_vertex_pose-1))->second);

e->setVertex(1, (optimizer.vertices().find(id_vertex_pointXYZ_start+ArucoFrame_temp.landmark_id[id_same[i]]*4+j))->second);

e->setMeasurement(ArucoFrame_temp.landmarks_pointXYZ[id_same[i]*4+j]);

e->setParameterId(0,0);//这句话必须加

optimizer.addEdge(e);

}

}

}

}

}

namespace {

const char* about = "Basic marker detection";

const char* keys =

"{d | 0 | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"

"DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "

"DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"

"DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"

"{v | | Input from video file, if ommited, input comes from camera }"

"{ci | 0 | Camera id if input doesnt come from video (-v) }"

"{c | log270 | Camera intrinsic parameters. Needed for camera pose }"

"{l | 0.06 | Marker side lenght (in meters). Needed for correct scale in camera pose }"

"{dp | detector_params.yml | File of marker detector parameters }"

"{r | | show rejected candidates too }";

}

static bool readCameraParameters(string filename, Mat &camMatrix, Mat &distCoeffs) {

FileStorage fs(filename, FileStorage::READ);

if(!fs.isOpened())

return false;

fs["camera_matrix"] >> camMatrix;

fs["distortion_coefficients"] >> distCoeffs;

return true;

}

static bool readDetectorParameters(string filename, Ptr<:detectorparameters> &params) {

FileStorage fs(filename, FileStorage::READ);

if(!fs.isOpened())

return false;

fs["adaptiveThreshWinSizeMin"] >> params->adaptiveThreshWinSizeMin;

fs["adaptiveThreshWinSizeMax"] >> params->adaptiveThreshWinSizeMax;

fs["adaptiveThreshWinSizeStep"] >> params->adaptiveThreshWinSizeStep;

fs["adaptiveThreshConstant"] >> params->adaptiveThreshConstant;

fs["minMarkerPerimeterRate"] >> params->minMarkerPerimeterRate;

fs["maxMarkerPerimeterRate"] >> params->maxMarkerPerimeterRate;

fs["polygonalApproxAccuracyRate"] >> params->polygonalApproxAccuracyRate;

fs["minCornerDistanceRate"] >> params->minCornerDistanceRate;

fs["minDistanceToBorder"] >> params->minDistanceToBorder;

fs["minMarkerDistanceRate"] >> params->minMarkerDistanceRate;

fs["doCornerRefinement"] >> params->doCornerRefinement;

fs["cornerRefinementWinSize"] >> params->cornerRefinementWinSize;

fs["cornerRefinementMaxIterations"] >> params->cornerRefinementMaxIterations;

fs["cornerRefinementMinAccuracy"] >> params->cornerRefinementMinAccuracy;

fs["markerBorderBits"] >> params->markerBorderBits;

fs["perspectiveRemovePixelPerCell"] >> params->perspectiveRemovePixelPerCell;

fs["perspectiveRemoveIgnoredMarginPerCell"] >> params->perspectiveRemoveIgnoredMarginPerCell;

fs["maxErroneousBitsInBorderRate"] >> params->maxErroneousBitsInBorderRate;

fs["minOtsuStdDev"] >> params->minOtsuStdDev;

fs["errorCorrectionRate"] >> params->errorCorrectionRate;

return true;

}

int main(int argc, char *argv[]) {

CommandLineParser parser(argc, argv, keys);

parser.about(about);

int dictionaryId = parser.get("d");

bool showRejected = parser.has("r");

bool estimatePose = parser.has("c");

float markerLength = parser.get("l");

Ptr<:detectorparameters> detectorParams = aruco::DetectorParameters::create();

if(parser.has("dp")) {

bool readOk = readDetectorParameters(parser.get("dp"), detectorParams);

if(!readOk) {

cerr << "Invalid detector parameters file" << endl;

return 0;

}

}

int camId = parser.get("ci");

String video;

if(parser.has("v")) {

video = parser.get("v");

}

if(!parser.check()) {

parser.printErrors();

return 0;

}

Ptr<:dictionary> dictionary =

aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));

Mat camMatrix, distCoeffs;

if(estimatePose) {

bool readOk = readCameraParameters(parser.get("c"), camMatrix, distCoeffs);

if(!readOk) {

cerr << "Invalid camera file" << endl;

return 0;

}

}

VideoCapture inputVideo;

/* int waitTime; if(!video.empty()) { inputVideo.open(video); waitTime = 0; } else { inputVideo.open(camId); waitTime = 10; } inputVideo.set(CAP_PROP_FRAME_WIDTH, 640); inputVideo.set(CAP_PROP_FRAME_HEIGHT , 480); */

double totalTime = 0;

int totalIterations = 0;

g2o::SparseOptimizer optimizer;//全局优化器

//以下三句话要加

g2o::ParameterSE3Offset* cameraOffset = new g2o::ParameterSE3Offset;

cameraOffset->setId(0);

optimizer.addParameter(cameraOffset);

optimizer.setVerbose(true);//调试信息输出

g2o::BlockSolverX::LinearSolverType * linearSolver;//6代表pose的自由度 3代表landmark的自由度

linearSolver= new g2o::LinearSolverDense<:blocksolverx::posematrixtype>();

g2o::BlockSolverX * solver_ptr

= new g2o::BlockSolverX(linearSolver);

//优化方法LM

g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);

optimizer.setAlgorithm(solver);

Mat inputImage=imread("./squre_80_120/0.jpg");

int num_image=1;

while(true) {

Mat image, imageCopy;

//inputVideo.retrieve(image);

image = inputImage;

double tick = (double)getTickCount();

vector< int > ids;

vector< vector< Point2f > > corners, rejected;

vector< Vec3d > rvecs, tvecs;

// detect markers and estimate pose

aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected);

if(estimatePose && ids.size() > 0)

aruco::estimatePoseSingleMarkers(corners, markerLength, camMatrix, distCoeffs, rvecs,

tvecs);

double currentTime = ((double)getTickCount() - tick) / getTickFrequency();

totalTime += currentTime;

// draw results

image.copyTo(imageCopy);

if(ids.size() > 0)

{

aruco::drawDetectedMarkers(imageCopy, corners, ids);

if(estimatePose) {

for(unsigned int i = 0; i < ids.size(); i++)

aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i],

markerLength * 0.5f);

}

}

if(showRejected && rejected.size() > 0)

aruco::drawDetectedMarkers(imageCopy, rejected, noArray(), Scalar(100, 0, 255));

imshow("out", imageCopy);

int key = waitKey(0);

cout << key << endl;

if(key == 1048689) break;//'q'

if(key == 1048675)//'c'

buildMap(ids, corners, rvecs, tvecs, optimizer);

string string_temp = "./squre2/" + to_string(num_image++) +".jpg";

if(num_image == 14)

break;

inputImage=imread(string_temp);

}

//之后开始g2o优化建图等。

optimizer.save("before.g2o");

optimizer.initializeOptimization();

optimizer.optimize(10);

optimizer.save("after.g2o");

return 0;

}

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

aruco板_基于arucoTag的简单slam 的相关文章

  • SLAM笔记(四)运动恢复结构的几何数学(本征矩阵、单应矩阵、基础矩阵)

    1 间接法进行运动恢复的前提假设 对于结构与运动或视觉三维重建中 通常假设已经通过特征匹配等方法获取了匹配好的点对 先求出匹配点对再获取结构和运动信息的方法称作间接法 间接法最重要的三个假设是 1 拥有一系列两帧之间的匹配点对 但同时假设匹
  • ubuntu系统下配置vscode编译cmake

    文章目录 一 配置vs code运行c 代码 三个关键文件介绍 1 tasks json run helloworld cpp 1 1 打开cpp文件 使其成为活动文件 1 2 按编辑器右上角的播放按钮 1 3生成task文件 1 4 此时
  • 《视觉SLAM十四讲》第一版源码slambook编译调试

    slambook master ch2 编译正常 log如下 slambook master ch2 mkdir build cd build cmake make j8 The C compiler identification is G
  • Event-based Stereo Visual Odometry(双目事件相机里程计)论文学习

    本文详细介绍一篇双目事件相机里程计的论文 Event based Stereo Visual Odometry 港科大沈邵劼团队Yi Zhou和TU Berlin的Guillermo Gallego共同完成 并公布了代码 我准备在接下来一段
  • 激光SLAM直接线性方法里程计运动模型及标定

    原创作者 W Tortoise 原创作者文章 https blog csdn net learning tortosie article details 107763626 1 里程计运动模型 1 1 两轮差分底盘的运动模型 1 2 三轮全
  • Sophus使用记录

    sophus库是一个基于Eigen的C 李群李代数库 可以用来方便地进行李群李代数的运算 头文件 主要用到以下两个头文件 include
  • 使用EKF融合odometry及imu数据

    整理资料发现早前学习robot pose ekf的笔记 大抵是一些原理基础的东西加一些自己的理解 可能有不太正确的地方 当时做工程遇到的情况为机器人在一些如光滑的地面上打滑的情形 期望使用EKF利用imu对odom数据进行校正 就结果来看
  • 视觉SLAM漫谈(二):图优化理论与g2o的使用

    视觉SLAM漫谈 二 图优化理论与g2o的使用 1 前言以及回顾 各位朋友 自从上一篇 视觉SLAM漫谈 写成以来已经有一段时间了 我收到几位热心读者的邮件 有的希望我介绍一下当前视觉SLAM程序的实用程度 更多的人希望了解一下前文提到的g
  • Difference Between LiDAR and RADAR——LiDAR和RADAR的不同

    Difference Between LiDAR and RADAR 原文连接 https www differencebetween com difference between lidar and vs radar 翻译 RADAR和L
  • LeGO-LOAM论文翻译(内容精简)

    LeGO LOAM是一种在LOAM之上进行改进的激光雷达建图方法 建图效果比LOAM要好 但是建图较为稀疏 计算量也更小了 本文原地址 wykxwyc的博客 github注释后LeGO LOAM源码 LeGO LOAM NOTED 关于代码
  • [SLAM四元数基础系列一] 四元数定义 Hamilton vs JPL

    四元数定义 Hamilton vs JPL 简介 四种区分方式 Hamilton vs JPL 引用 不管是卡尔曼滤波或者BA优化形式的SLAM或者VIO系统中 都需要用到单位四元数 Quaternion 来表示旋转 主要是单位四元数表示旋
  • 图像匹配算法

    图像匹配算法分为3类 基于灰度的匹配算法 基于特征的匹配算法 基于关系的匹配算法 1 基于灰度的模板匹配算法 模板匹配 Blocking Matching 是根据已知模板图像到另一幅图像中寻找与模板图像相似的子图像 基于灰度的匹配算法也称作
  • IMU预积分的一些理解

    IMU预积分 算是比较简单的一个算法 无奈网上找到的资料都讲的晦涩难懂 看明白了也觉得不过如此 讲一下我的理解 整体流程 1 推导IMU离散运动方程 2 根据离散运动方程 进行预积分 并将预积分的误差项拆分出来 因为我们在定义误差的时候 有
  • 用Eigen库练习代数运算方式以便后续对刚体旋转和移动做基础

    include
  • Ceres Solver从零开始手把手教学使用

    目录 一 简介 二 安装 三 介绍 四 Hello Word 五 导数 1 数值导数 2解析求导 六 实践 Powell函数 一 简介 笔者已经半年没有更新新的内容了 最近学习视觉SLAM的过程中发现自己之前学习的库基础不够扎实 Ceres
  • 无人车

    1 无人车四大核心技术 自动驾驶实际包含三个问题 一是我在哪 二是我要去哪 三是如何去 第一个问题是环境感知和精确定位 无人车需要的是厘米级定位 厘米级定位是无人驾驶的难点之一 不光是车辆本身的语义级定位 还有一个绝对坐标定位 第二个问题是
  • LeGO-LOAM中的数学公式推导

    LeGO LOAM是一种在LOAM之上进行改进的激光雷达建图方法 建图效果比LOAM要好 但是建图较为稀疏 计算量也更小了 本文原地址 wykxwyc的博客 github注释后LeGO LOAM源码 LeGO LOAM NOTED 关于代码
  • LIO-SAM运行自己数据包遇到的问题解决--SLAM不学无数术小问题

    LIO SAM 成功适配自己数据集 注意本文测试环境 Ubuntu18 04 ROS melodic版本 笔者用到的硬件以简单参数 激光雷达 速腾聚创16线激光雷达 RS Lidar 16 IMU 超核电子CH110型 9轴惯导 使用频率1
  • Ubuntu18.04安装Autoware1.15(解决Openplanner无法绕障的问题:Openplanner2.5)

    文章目录 一 下载Autoware1 15源码 二 安装依赖 三 修改CUDA版本 四 编译以及报错解决 编译 1 报 undefined reference to cv Mat Mat 的错就按照下面方式改相应包 2 遇到OpenCV的C
  • 什么是深度学习的无监督学习与有监督学习

    无监督学习 深度学习中的无监督学习方法是一种训练算法 它在没有标注输出的情况下从输入数据中学习模式和特征 这种方法的核心是探索和理解数据的内在结构和分布 而不是通过已知的输出来指导学习过程 无监督学习在深度学习领域有许多不同的形式和应用 以

随机推荐