视觉slam十四讲实践部分记录——ch6 非线性优化

发布于:2025-07-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

1、cmake报错:

     CMakeLists.txt 文件中使用了过时的 CMake 最低版本要求(cmake_minimum_required(VERSION 2.8)),而当前使用的 CMake 版本 不再支持小于 3.5 的版本号声明。 

解决方法:

将第一行改为:

cmake_minimum_required(VERSION 3.10)

 然后cmake编译安装。。。


记得先安装编译g2o,要不然报错:

 方法:

安装依赖项:

sudo apt-get install qt5-qmake qt5-default libqglviewer-dev-qt5 libsuitesparse-dev libcxsparse3 libcholmod3

 后按照cmake的方式对g2o编译安装即可。

最后记得:(不能光make)

sudo make install

3、编译报错:

   原因:

     G2O 的头文件使用了 C++17 特性(如 std::tuple_size_v, std::string_view, std::make_unique),但编译器 没有启用 C++17 标准。

解决方法: 

删除以下这行: 

将编译文件修改为:

cmake_minimum_required(VERSION 3.10)
project(ch6)

set(CMAKE_CXX_STANDARD 17)# 显式设置为C++17标准
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS_RELEASE "-O3") # 仅设置优化,不指定标准

list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

# OpenCV
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

# Ceres
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})

# g2o
find_package(G2O REQUIRED)
include_directories(${G2O_INCLUDE_DIRS})

# Eigen
include_directories("/usr/local/include/eigen3")

add_executable(gaussNewton gaussNewton.cpp)
target_link_libraries(gaussNewton ${OpenCV_LIBS})

add_executable(ceresCurveFitting ceresCurveFitting.cpp)
target_link_libraries(ceresCurveFitting ${OpenCV_LIBS} ${CERES_LIBRARIES})

add_executable(g2oCurveFitting g2oCurveFitting.cpp)
target_link_libraries(g2oCurveFitting ${OpenCV_LIBS} ${G2O_CORE_LIBRARY} ${G2O_STUFF_LIBRARY})

4、报错: 

error: ‘make_unique’ is not a member of ‘g2o’; did you mean ‘std::make_unique’?


    用了新版 g2o(从 GitHub master 分支构建的),而新版 g2o 使用的是 std::make_unique(C++14及以上),但原代码用的是 g2o::make_unique

解决方法:  

编辑 g2oCurveFitting.cpp 文件 

 改为:

auto solver = std::make_unique<BlockSolverType>(std::make_unique<LinearSolverType>());

⚠️ 注意:必须 #include <memory>,否则会提示 make_unique 不可用。

补全一下代码片段

在你 main() 函数中这段逻辑大概率如下,请你确认并修改为:

#include <memory>  // 加上这个!

int main(int argc, char** argv) {
    ...
    // 构建 solver
    using BlockSolverType = g2o::BlockSolver<g2o::BlockSolverTraits<3, 1>>;
    using LinearSolverType = g2o::LinearSolverDense<BlockSolverType::PoseMatrixType>;

    auto solver = std::make_unique<BlockSolverType>(std::make_unique<LinearSolverType>());

    optimizer.setAlgorithm(new g2o::OptimizationAlgorithmLevenberg(std::move(solver)));
    ...
}
警告也一起修复

还有一些 warning:

virtual bool read(istream& in) {} // 没 return

应该补上 return true;false;

virtual bool read(std::istream& in) override { return true; } virtual bool write(std::ostream& out) const override { return true; }

否则虽然不是致命错误,但也是不规范的虚函数定义,建议修复。

修改后部分代码: 

然后保存重新编译即可。

运行

 ./gaussNewton

 安装Ceres

安装依赖项:

sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3 libgflags-dev libgoogle-glog-dev libgtest-dev

其他同上。

./ceresCurveFitting

./g2oCurveFitting

报错:

 重复使用 std::unique_ptr 导致段错误

在代码中写了两次: 

auto solver = std::make_unique<BlockSolverType>(std::make_unique<LinearSolverType>());
g2o::OptimizationAlgorithmLevenberg* algorithm = new g2o::OptimizationAlgorithmLevenberg(std::move(solver));
optimizer.setAlgorithm(new g2o::OptimizationAlgorithmLevenberg(std::move(solver)));

这里:

第一次 std::move(solver) 把 solver 所拥有的指针移交给了 algorithm

第二次 std::move(solver) 再次使用已经为空的 unique_ptr,导致空指针被传入 SparseOptimizer::setAlgorithm()

当你运行 optimizer.optimize() 时,内部调用了空指针成员函数,直接段错误

解决方案:

只构造一次 solver,并传一次

auto solver = std::make_unique<BlockSolverType>(std::make_unique<LinearSolverType>());
auto algorithm = new g2o::OptimizationAlgorithmLevenberg(std::move(solver));

g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm(algorithm);  // 只传一次
optimizer.setVerbose(true);

 

重新清除,编译,运行: