mrpt tips

26 篇文章 1 订阅
11 篇文章 1 订阅

1.命名空间及头文件地址

mrpt 1.0命名空间头文件地址
COccupancyGridMap2D.hmrpt::slam/usr/include/mrpt/maps/include/mrpt/slam
CICP.hmrpt::slam/usr/include/mrpt/slam/include/mrpt/slam
CSimplePointsMap.hmrpt::slam/usr/include/mrpt/maps/include/mrpt/slam
CObservation2DRangeScan.hmrpt::slam/usr/include/mrpt/obs/include/mrpt/slam
CPose2D.hmrpt::poses/usr/include/mrpt/base/include/mrpt/poses
CPose3D.hmrpt::poses/usr/include/mrpt/base/include/mrpt/poses
CPosePDF.hmrpt::poses/usr/include/mrpt/base/include/mrpt/poses

2.图优化

  • 函数实现文件为 mrpt/libs/graphslam/include/mrpt/graphslam/levmarq.h
#include <mrpt/random.h>
#include <mrpt/graphslam/levmarq.h>
#include <mrpt/system/threads.h> // sleep()
#include <mrpt/gui.h>
#include <mrpt/opengl/CSetOfObjects.h>
#include <mrpt/opengl/COpenGLScene.h>
#include <mrpt/opengl/graph_tools.h>

using namespace mrpt;
using namespace mrpt::utils;
using namespace mrpt::graphs;
using namespace mrpt::graphslam;
using namespace mrpt::poses;
using namespace mrpt::math;
using namespace mrpt::gui;
using namespace mrpt::opengl;
using namespace mrpt::random;
using namespace std;

static void my_levmarq_feedback(
		const CNetworkOfPoses2DInf &graph,
		const size_t iter,
		const size_t max_iter,
		const double cur_sq_error )
	{
		if ((iter % 100)==0)
			cout << "Progress: " << iter << " / " << max_iter << ", total sq err = " << cur_sq_error << endl;
	}

int main()
{
	CNetworkOfPoses2DInf graph;
	CNetworkOfPoses2DInf::global_poses_t  real_node_poses;

	const size_t N_VERTEX = 50;
	const double DIST_THRES = 7;
	const double NODES_XY_MAX = 20;

	//加点
	for (TNodeID j=0;j<N_VERTEX;j++)
	{
		static double ang = 2*M_PI/N_VERTEX;
		const double R = NODES_XY_MAX + 2 * (j % 2 ? 1:-1);
		CPose2D p(R*cos(ang*j), R*sin(ang*j), ang);
		real_node_poses[j] = p;
		graph.nodes[j] = p;
	}

	//加边
	static const int DIM = CNetworkOfPoses2DInf::edge_t::type_value::static_size;
	CMatrixFixedNumeric<double,DIM,DIM> inf_matrix;
	inf_matrix.unit(CMatrixFixedNumeric<double,DIM,DIM>::RowsAtCompileTime, square(1.0/10));
	for (TNodeID i=0;i<N_VERTEX;i++)
	{
		for (TNodeID j=i+1;j<N_VERTEX;j++)
		{
			if ( real_node_poses[i].distanceTo(real_node_poses[j]) < DIST_THRES )
			{
				CNetworkOfPoses2DInf::edge_t RelativePose(real_node_poses[j] - real_node_poses[i], inf_matrix);
				graph.insertEdge(i, j, RelativePose );
			}
		}
	}

	//图的原点
	graph.root = TNodeID(0);
	//GroundTruth
	const CNetworkOfPoses2DInf  graph_GT = graph;

	//加噪声
	randomGenerator.randomize(123);
	const double STD_NOISE_NODE_XYZ = 0.5;
	const double STD_NOISE_NODE_ANG = DEG2RAD(5);
	const double STD_NOISE_EDGE_XYZ = 0.001;
	const double STD_NOISE_EDGE_ANG = DEG2RAD(0.01);
	for (CNetworkOfPoses2DInf::edges_map_t::iterator itEdge=graph.edges.begin();itEdge!=graph.edges.end();++itEdge)
		{
			const CNetworkOfPoses2DInf::edge_t::type_value delta_noise(CPose3D(
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_XYZ),
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_XYZ),
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_XYZ),
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_ANG),
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_ANG),
				randomGenerator.drawGaussian1D(0,STD_NOISE_EDGE_ANG) ));
			itEdge->second.getPoseMean() += CNetworkOfPoses2DInf::edge_t::type_value(delta_noise);
		}


	for (CNetworkOfPoses2DInf::global_poses_t::iterator itNode=graph.nodes.begin();itNode!=graph.nodes.end();++itNode)
			if (itNode->first!=graph.root)
				itNode->second.getPoseMean() += CNetworkOfPoses2DInf::edge_t::type_value( CPose3D(
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_XYZ),
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_XYZ),
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_XYZ),
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_ANG),
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_ANG),
					randomGenerator.drawGaussian1D(0,STD_NOISE_NODE_ANG) ) );


	//优化前的图
	const CNetworkOfPoses2DInf  graph_initial = graph;

	TParametersDouble  params;
	//params["verbose"]  = 1;
	params["profiler"] = 1;
	params["max_iterations"] = 500;
	params["scale_hessian"] = 0.1;  
	params["tau"] = 1e-3; 
	graphslam::TResultInfoSpaLevMarq  levmarq_info;
	//图优化
	graphslam::optimize_graph_spa_levmarq(graph, levmarq_info, NULL, params, &my_levmarq_feedback);
	
	//显示
	CDisplayWindow3D  win("graph-slam demo results");
	CDisplayWindow3D  win2("graph-slam demo initial state");

	TParametersDouble  graph_render_params1;
	graph_render_params1["show_edges"] = 1;
	graph_render_params1["edge_width"] = 1;
	graph_render_params1["nodes_corner_scale"] = 1;
	CSetOfObjectsPtr gl_graph1 = mrpt::opengl::graph_tools::graph_visualize(graph, graph_render_params1 );

	TParametersDouble  graph_render_params2;
	graph_render_params2["show_ground_grid"] = 0;
	graph_render_params2["show_edges"] = 0;
	graph_render_params2["show_node_corners"] = 0;
	graph_render_params2["nodes_point_size"]  = 17;
	CSetOfObjectsPtr gl_graph2 = mrpt::opengl::graph_tools::graph_visualize(graph_initial, graph_render_params2 );

	graph_render_params2["nodes_point_size"]  = 10;
	CSetOfObjectsPtr gl_graph5 = mrpt::opengl::graph_tools::graph_visualize(graph, graph_render_params2 );

	TParametersDouble  graph_render_params3;
	graph_render_params3["show_ground_grid"] = 0;
	graph_render_params3["show_ID_labels"] = 1;
	graph_render_params3["show_edges"] = 1;
	graph_render_params3["edge_width"] = 3;
	graph_render_params3["nodes_corner_scale"] = 2;
	CSetOfObjectsPtr gl_graph3 = mrpt::opengl::graph_tools::graph_visualize(graph_GT, graph_render_params3 );
	CSetOfObjectsPtr gl_graph4 = mrpt::opengl::graph_tools::graph_visualize(graph_initial, graph_render_params3 );

	{
		COpenGLScenePtr &scene = win.get3DSceneAndLock();
		scene->insert(gl_graph1);
		scene->insert(gl_graph3);   //GT
		scene->insert(gl_graph2);   //未优化点位
		scene->insert(gl_graph5);   //优化后点位
		win.unlockAccess3DScene();
		win.repaint();
	}

	{
		COpenGLScenePtr &scene = win2.get3DSceneAndLock();
		scene->insert(gl_graph3);
		scene->insert(gl_graph4);
		win2.unlockAccess3DScene();
		win2.repaint();
	}

	cout << "Close any window to end...\n";
	while (win.isOpen() && win2.isOpen() && !mrpt::system::os::kbhit())
	{
		mrpt::system::sleep(10);
	}

	return 0;
}
  • 优化函数为graphslam::optimize_graph_spa_levmarq(graph, levmarq_info, NULL, params, &my_levmarq_feedback);参数依次为需要优化的图也是结果图,优化结果信息,优化点集(NULL表示所有点),优化参数,回调函数。第五个参数回调函数指针默认为NULL,如果没有后续处理,可以这样调用graphslam::optimize_graph_spa_levmarq(graph, levmarq_info, NULL, params);

3.CObservation2DRangeScan存取

  • 保存,假设要保存的变量是my_scan
ofstream output_frame("frame.txt");
ofstream output_valid("valid.txt");
vector<float> output_scan = my_scan->scan;
vector<char> valid = my_scan->validRange;
for(int j = 0; j < output_scan.size(); ++j)
{
	//保存inf
	if(output_scan[j] > 60)
    {
	    output_frame << 60.89 << "\t";
    }
    else
    {
	    output_frame << output_scan[j] << "\t";
    }
    //validRange非0即1
    output_valid << (int)valid[j] << "\t";
}
output_valid << endl;
output_frame << endl;
output_frame.close();
output_valid.close();
  • 读取
ifstream input_frame("frame.txt");
ifstream input_valid("valid.txt");
if(!input_frame.is_open() || !input_valid.is_open())
{
	return;
}
CObservation2DRangeScan scan;
//根据保存的数据确定
scan.aperture = 6.26573;
scan.rightToLeft = true;
float f;
int v, flag = 0, SCAN_SIZE = 360;
while(1)
{
    scan.scan.clear();        
    scan.validRange.clear();     //会将validRange的大小设为0
    //SCAN_SIZE根据保存的数据确定
    for(int i = 0; i < SCAN_SIZE; ++i)
    {
        //用此方式判断文件尾,防止多读一次
        input_frame >> f;
        if(input_frame.eof()) 
        {
            flag = 1;
            break;
        }
        if(f > 60)
        {
            scan.scan.push_back(1/0.0f);
        }
        else
        {
            scan.scan.push_back(f);
        }
        input_valid >> v;
        scan.validRange.push_back(char(v));
    }
    if(flag == 1) break;
}
input_frame.close();
input_valid.close();
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 相机标定2.0是MRPT项目的一部分。MRPT是一个开源机器人感知工具库,旨在提供用于机器人感知、定位和导航的算法和功能。相机标定是MRPT项目中的一个重要组成部分。 相机标定是指通过确定相机的内部和外部参数,将图像中的像素坐标与物体在真实世界中的坐标进行关联。在相机标定中,通过进行一系列的图像采集和处理,可以估计出相机的参数,如焦距、畸变、旋转和平移等。 相机标定2.0是对相机标定技术的进一步改进和优化。相较于传统的相机标定方法,相机标定2.0引入了更精确的算法和更高效的数据处理技术。这使得相机标定能够更准确地估计相机内部和外部参数,并且具备更快的计算速度。 在MRPT项目中,相机标定2.0的目标是提供一套完整的相机标定工具和算法,以满足不同应用场景的需求。相机标定2.0不仅可以应用于机器人感知和导航领域,还可以应用于计算机视觉、增强现实等多个领域。通过MRPT项目中的相机标定2.0,用户可以方便地进行相机标定,并获得高质量的相机参数估计结果。 总之,相机标定2.0是MRPT项目中重要的一部分,它提供了先进的相机标定工具和算法,可以广泛应用于机器人感知、计算机视觉等领域,为用户提供精确、高效的相机标定功能。 ### 回答2: 相机标定 2.0 是 MRPT 项目的一部分。MRPT(Modular Robotics and Perception Toolkit)是一个开源机器人感知和控制工具包,旨在提供一种通用的、跨平台的解决方案。相机标定 2.0 是 MRPT 项目在相机标定领域的新版本,旨在改进相机标定算法和技术。 相机标定是指确定相机参数的过程,以便将摄像机坐标系中的图像映射到世界坐标系中。相机标定的目的是估计相机的内部参数(如焦距、主点位置等)和外部参数(如相机的位置和姿态),以便以像素坐标表示的图像可以准确投影到物理空间中。 相机标定 2.0 在 MRPT 项目中的特点包括了改进的标定算法和更精确的结果。通过使用更复杂的数学模型和更准确的标定板,相机标定 2.0 可以获取更准确的内部和外部相机参数估计。此外,该版本还引入了一些新的功能,例如自动检测标定板的功能和自动图像选择功能,以简化标定过程。 MRPT 项目致力于提供一个完整的机器人感知和控制解决方案,并且有广泛的应用领域,包括机器人导航、物体识别和跟踪、三维重建等。相机标定 2.0 的引入将进一步提升 MRPT 项目的相机感知能力,为用户提供更准确和可靠的相机标定工具,从而提高机器人系统的精度和性能。这将促使更多的研究者和开发者使用 MRPT 项目进行相机标定,并推动机器人感知和控制技术的发展。 ### 回答3: 相机标定是计算机视觉领域的一个重要问题,用于确定相机的内部和外部参数。相机标定2.0是MRPT项目的一部分,MRPT是一个开源的机器人技术库,提供了许多机器人感知和导航相关的算法。 相机标定2.0是MRPT项目中的一个更新版本,旨在提供更高精度和更方便使用的相机标定方法。它基于计算机视觉和几何学的相关理论,通过对已知空间中的特定目标进行观测,推导出相机内部和外部的参数。 相机标定2.0具有许多优点。首先,它考虑到了更多的几何畸变,例如径向畸变和切向畸变,并通过确定畸变矫正的参数来提高图像的准确度。其次,它采用了更稳健的标定算法,可以在图像中存在较多噪声或遮挡的情况下进行标定。此外,相机标定2.0还提供了一种自适应标定方法,可以根据不同的场景和要求进行个性化的标定处理。 通过使用相机标定2.0,我们可以获得更准确的相机参数,从而提高计算机视觉算法的性能。例如,对于特征点匹配、三维重建等任务,标定后的相机可以提供更准确的测量结果。此外,相机标定2.0还为机器人导航、增强现实等应用场景提供了更可靠的图像数据。 总而言之,相机标定2.0是MRPT项目中的一部分,旨在提供更高精度和更方便使用的相机标定方法。通过使用这一方法,我们可以获得更准确的相机参数,并改善计算机视觉算法的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刀么克瑟拉莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值