当前位置: 首页 > 工具软件 > MRPT > 使用案例 >

mrpt tips

楚良平
2023-12-01

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();
 类似资料:

相关阅读

相关文章

相关问答