视觉SLAM十四讲 第六章程序出错(转载)

视觉SLAM十四讲 第六章程序出错(转载)

摘自:https://www.cnblogs.com/xueyuanaichiyu/p/7921382.html

问题:

首先贴出报错部分代码:

typedef g2o::BlockSolver< g2o::BlockSolverTraits<3,1> > Block; 
Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>(); 
Block* solver_ptr = new Block( linearSolver );     
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( solver_ptr );
g2o::SparseOptimizer optimizer;   
optimizer.setAlgorithm( solver );   
optimizer.setVerbose( true ); 

按照书上的例程编写代码,编译时报错(部分截图)如下:

/home/wxy/slambook/useg2o/main.cpp:77:49: error: no matching 

function for call to ‘g2o::BlockSolver<g2o::BlockSolverTraits<3, 1> >::BlockSolver(g2o::BlockSolver<g2o::BlockSolverTraits<3, 1> >::LinearSolverType*&)’
 Block* solver_ptr = new Block( linearSolver );      
                                             ^
/home/wxy/slambook/useg2o/main.cpp:77:49: note: candidate is:
In file included from     /usr/local/include/g2o/core/block_solver.h:199:0,
             from /home/wxy/slambook/useg2o/main.cpp:4:
/usr/local/include/g2o/core/block_solver.hpp:40:1: note: g2o::BlockSolver<Traits>::BlockSolver(std::unique_ptr<typename Traits::LinearSolverType>) [with Traits = g2o::BlockSolverTraits<3, 1>; typename Traits::LinearSolverType = g2o::LinearSolver<Eigen::Matrix<double, 3, 3> >]
 BlockSolver<Traits>::BlockSolver(std::unique_ptr<LinearSolverType> linearSolver)

好像是编译器无法找到某个函数,或者某个调用出错。我第一个想到的是无法找到g2o有关函数那应该是g2o库没有装好(这个库我make的时候等了大概两个小时,也不知道为啥会卡这么久)于是将库重装了一下,再次编译还是报错,仔细读报错信息下面有写到:

BlockSolver<Traits>::BlockSolver(std::unique_ptr<LinearSolverType> linearSolver)

会不会是我调用方法不对?网上搜索std::unique_ptr是干嘛用的(c++知识忘得差不多了....),搜到:http://blog.youkuaiyun.com/pi9nc/article/details/12227887
原来是智能指针。

unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。

原代码中用到的好像是普通的指针,难道是因为指针类型不匹配?然后我在网上收到了一篇博客:http://blog.youkuaiyun.com/robinhjwy/article/details/78084210
惊了,原来有人跟我一样遇到过这种问题,而且早就解决了。。。。修改过后的代码如下:

typedef g2o::BlockSolver< g2o::BlockSolverTraits<3,1> > Block;
std::unique_ptr<Block::LinearSolverType> linearSolver ( new g2o::LinearSolverDense<Block::PoseMatrixType>() );
std::unique_ptr<Block> solver_ptr (new Block( std::move(linearSolver) ));
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( std::move(solver_ptr) );
g2o::SparseOptimizer optimizer;   
optimizer.setAlgorithm( solver );   
optimizer.setVerbose( true ); 

将初始化中用等号赋值的地方改成用std::unique_ptr赋值,将linearSolver和solver_ptr用移动语言也就是std::move来实现。改完后编译运行成功,意犹未尽的我又去查了一下关于g2o的初始化问题,因为报错的地方就是这里,然后看到了这篇博客:
https://www.cnblogs.com/serser/p/7815588.html

修改代码如下:

typedef g2o::BlockSolver< g2o::BlockSolverTraits<3,1> > Block;
Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>();
Block* solver_ptr = new Block( std::unique_ptr<Block::LinearSolverType>(linearSolver) );
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(std::unique_ptr<Block>(solver_ptr) );
g2o::SparseOptimizer optimizer;   
optimizer.setAlgorithm( solver );   
optimizer.setVerbose( true ); 

前面还是用普通指针来赋值,之后再转换成unique_ptr.
运行结果:


<think>我们遇到了一个新的错误:`ActorProfiles 应为 struct 类型,但实际为 double`。这通常是因为在创建`visionDetectionGenerator`时,`ActorProfiles`参数传入的不是结构体,而是一个双精度数组(double)。在MATLAB中,`visionDetectionGenerator`的`ActorProfiles`属性需要传入一个结构体数组,这个结构体数组描述了场景中的演员(车辆、行人等)的属性。 错误发生在以下代码行: ```matlab camera = visionDetectionGenerator(... 'SensorLocation', [2 0],... % 安装位置 [X,Y] 'Height', 1.5,... % 安装高度 'Yaw', 0,... % 偏航角 'Intrinsics', intrinsics,... % 相机内参 'DetectionCoordinates', 'Sensor Cartesian',... % 坐标系类型 'ActorProfiles', actorProfiles(scenario)); % 场景关联 ``` 问题出在`actorProfiles(scenario)`的返回值类型上。在R2023b中,`actorProfiles`函数返回的实际上是一个结构体数组,但可能在某些情况下返回空数组(空的双精度数组)或者没有正确返回结构体。 我们需要检查`scenario`对象中是否有演员(actor)。如果没有演员,`actorProfiles(scenario)`可能返回一个空数组(即[],类型为double),从而导致这个错误。 解决方案: 1. 确保场景中有演员(车辆、行人等)。如果没有,需要添加至少一个演员(例如一辆自车)。 2. 如果场景中确实有演员,那么`actorProfiles(scenario)`应该返回一个结构体数组。我们可以通过显式地创建一个演员来确保这一点。 修改后的代码: 在创建场景和道路后,添加一个车辆(演员): ```matlab % 创建一辆车(自车) egoVehicle = vehicle(scenario, 'ClassID', 1, 'Position', [0 0 0]); ``` 这样,`actorProfiles(scenario)`就会返回一个非空的结构体数组。 完整修正代码: ```matlab %% 1. 创建驾驶场景和传感器系统 scenario = drivingScenario; roadCenters = [0 0 0; 50 0 0; 100 20 0; 200 40 0]; road(scenario, roadCenters, 'Lanes', lanespec(2)); % 添加一辆自车(关键修正:确保场景中有演员) egoVehicle = vehicle(scenario, 'ClassID', 1, 'Position', [0 0 0]); % 创建相机内参对象 intrinsics = cameraIntrinsics(... [800, 800],... % 焦距 [fx, fy] [640, 360],... % 主点 [cx, cy] [720, 1280]... % 图像尺寸 [高度, 宽度] ); %% 2. 正确配置 visionDetectionGenerator(解决ActorProfiles错误) % 获取演员配置(现在应该是结构体数组) profiles = actorProfiles(scenario); % 创建视觉传感器 camera = visionDetectionGenerator(... 'SensorLocation', [2 0],... % 安装位置 [X,Y] 'Height', 1.5,... % 安装高度 'Yaw', 0,... % 偏航角 'Intrinsics', intrinsics,... % 相机内参 'DetectionCoordinates', 'Sensor Cartesian',... % 坐标系类型 'ActorProfiles', profiles); % 使用获取到的结构体数组 %% 3. 使用 drivingScenarioDesigner 记录数据 dsd = drivingScenarioDesigner(scenario); % 创建设计器对象 addSensor(dsd, camera); % 添加传感器 % 手动操作步骤: % 1. 点击"Run"按钮运行仿真 % 2. 仿真结束后点击"Export" > "Export to Workspace" % 3. 导出变量:cameraFrames 和 groundTruthPoses %% 4. 视觉SLAM核心算法(等待数据导出后执行) % ...(后续代码保持不变,参考之前的修正) ``` 注意:如果场景中需要其他车辆,可以继续添加。但至少需要一辆车,否则`actorProfiles`将返回空数组(double类型)导致错误。 如果问题仍然存在,我们可以通过检查`profiles`变量的类型来调试: ```matlab profiles = actorProfiles(scenario); disp(class(profiles)); % 应该输出 'struct' ``` 如果`profiles`是空数组,我们可以手动创建一个默认的演员配置结构体(但通常不推荐,因为这样会失去与场景中实际演员的关联)。所以,最稳妥的方式是确保场景中有演员。 另外,如果场景中有多个演员,`visionDetectionGenerator`会使用这些演员的尺寸信息来生成检测框。对于自车,我们通常不希望被检测到,但为了生成传感器数据,我们需要有演员存在。 修正后,错误应该被解决。</think>### 错误分析与完整修正代码 您遇到的错误 `ActorProfiles 应为 struct 类型,但其类型为 double` 是由于 `actorProfiles(scenario)` 函数在场景中没有演员(Actor)时返回空数组(double 类型)导致的。以下是完全兼容的修正方案: ```matlab %% 1. 创建驾驶场景并添加演员(关键修正) scenario = drivingScenario; roadCenters = [0 0 0; 50 0 0; 100 20 0; 200 40 0]; road(scenario, roadCenters, 'Lanes', lanespec(2)); % 添加至少一个演员(车辆)到场景中 egoVehicle = vehicle(scenario, ... 'ClassID', 1, ... % 1-小汽车, 2-卡车, 3-行人 'Position', [0 0 0], ... % 初始位置 'Length', 4.7, ... % 车辆长度(m) 'Width', 1.8, ... % 车辆宽度(m) 'Height', 1.4); % 车辆高度(m) %% 2. 正确获取演员配置(解决ActorProfiles错误) % 获取场景中所有演员的配置信息(返回结构体数组) profiles = actorProfiles(scenario); % 验证profiles类型(调试用) assert(isstruct(profiles), 'ActorProfiles必须是结构体数组'); %% 3. 创建相机传感器(使用修正后的ActorProfiles) intrinsics = cameraIntrinsics(... [800, 800], ... % 焦距 [fx, fy] [640, 360], ... % 主点 [cx, cy] [720, 1280] ... % 图像尺寸 [高度, 宽度] ); camera = visionDetectionGenerator(... 'SensorLocation', [2 0], ... % 安装位置 [X,Y] 'Height', 1.5, ... % 安装高度 'Yaw', 0, ... % 偏航角 'Intrinsics', intrinsics, ... % 相机内参 'DetectionCoordinates', 'Sensor Cartesian', ... 'ActorProfiles', profiles); % 使用正确的结构体数组 %% 4. 验证传感器配置(可选) % 检查传感器属性 disp('传感器配置验证:'); disp(['传感器类型: ' class(camera)]); disp(['安装位置: ' num2str(camera.SensorLocation)]); disp(['安装高度: ' num2str(camera.Height)]); disp(['演员配置数量: ' num2str(numel(camera.ActorProfiles))]); %% 5. 使用drivingScenarioDesigner记录数据 dsd = drivingScenarioDesigner(scenario); addSensor(dsd, camera); % 操作指南: % 1. 点击"Run"运行仿真 % 2. 点击"Export" > "Export to Workspace" % 3. 导出变量: cameraFrames 和 groundTruthPoses %% 6. 替代方案:无演员时的解决方案 % 如果确实不需要演员,可手动创建空结构体 if isempty(profiles) profiles = struct(... 'ClassID', {}, ... 'Length', {}, ... 'Width', {}, ... 'Height', {}, ... 'OriginOffset', {}, ... 'RCSPattern', {}); warning('使用空演员配置,可能影响检测效果'); end ``` ### 关键修正说明: 1. **演员添加**: ```matlab % 添加车辆演员到场景 egoVehicle = vehicle(scenario, ... 'ClassID', 1, ... 'Position', [0 0 0], ... 'Length', 4.7, ... 'Width', 1.8, ... 'Height', 1.4); ``` - 必须至少添加一个演员(车辆、行人等) - `ClassID` 指定演员类型(1=小汽车,2=卡车,3=行人) 2. **演员配置获取**: ```matlab % 正确获取演员配置结构体 profiles = actorProfiles(scenario); ``` - 当场景中有演员时,返回结构体数组 - 空场景时返回空双精度数组导致错误 3. **类型验证**: ```matlab % 确保profiles是结构体类型 assert(isstruct(profiles), 'ActorProfiles必须是结构体数组'); ``` ### 错误原因解析: 1. **`actorProfiles` 函数行为**: - 当场景中没有演员时:返回空数组 `[]`(类型为 `double`) - 当场景中有演员时:返回结构体数组(类型为 `struct`) 2. **`visionDetectionGenerator` 要求**: ```matlab % 正确属性设置 'ActorProfiles', struct_array % 必须是结构体数组 ``` 3. **解决方案优势**: - 保持场景完整性,支持多演员检测 - 兼容所有 MATLAB 版本 - 提供无演员时的应急方案 ### 完整演员配置结构: 典型的演员配置结构包含以下字段: ```matlab profiles = 1×1 struct array with fields: ClassID Length Width Height OriginOffset RCSPattern ``` ### 验证测试脚本: ```matlab %% 测试1: 空场景验证 emptyScenario = drivingScenario; emptyProfiles = actorProfiles(emptyScenario); assert(isnumeric(emptyProfiles), '空场景应返回数值数组'); assert(isempty(emptyProfiles), '空场景应返回空数组'); %% 测试2: 含演员场景验证 scenario = drivingScenario; vehicle(scenario, 'Position', [0 0 0]); validProfiles = actorProfiles(scenario); assert(isstruct(validProfiles), '含演员场景应返回结构体'); assert(~isempty(validProfiles), '结构体不应为空'); %% 测试3: 多演员场景 scenario = drivingScenario; vehicle(scenario, 'Position', [0 0 0]); % 演员1 vehicle(scenario, 'Position', [10 2 0]); % 演员2 pedestrian(scenario, 'Position', [5 -2 0]); % 演员3 (ClassID=3) multiProfiles = actorProfiles(scenario); assert(numel(multiProfiles) == 3, '应返回3个演员配置'); ``` ### 无演员场景的应急方案: ```matlab %% 替代方案:手动创建空结构体 if isnumeric(profiles) && isempty(profiles) profiles = struct(... 'ClassID', {}, ... 'Length', {}, ... 'Width', {}, ... 'Height', {}, ... 'OriginOffset', {}, ... 'RCSPattern', {}); % 创建虚拟相机(无演员检测能力) camera = visionDetectionGenerator(... 'SensorLocation', [2 0], ... 'Height', 1.5, ... 'Intrinsics', intrinsics, ... 'DetectionCoordinates', 'Sensor Cartesian', ... 'ActorProfiles', profiles); warning('场景无演员:只能检测车道线等静态物体'); end ``` 此修正方案确保 `actorProfiles` 始终返回结构体类型,解决了 `类型为 double` 的错误,并提供了无演员场景的兼容方案。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值