视觉SLAM十四讲学习笔记——ch8视觉里程计2

视觉SLAM十四讲学习笔记——ch8视觉里程计2,第1张

文章目录
  • 8.1 理论部分
  • 8.2 实践部分
    • 8.2.1光流法
    • 8.2.2 直接法
    • bug调试
  • 参考博客

8.1 理论部分

理论部分可参考: 视觉slam14讲——第8讲 视觉里程计2

8.2 实践部分 8.2.1光流法

代码及详细参考解释如下:

//
// Created by Xiang on 2017/12/19.
//

#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

string file_1 = "/home/lmf37/桌面/slambook2/ch8/LK1.png";  // first image
string file_2 = "/home/lmf37/桌面/slambook2/ch8/LK2.png";  // second image

/// Optical flow tracker and interface//定义光流追踪的类
class OpticalFlowTracker {
public:
    OpticalFlowTracker(
        const Mat &img1_,
        const Mat &img2_,
        const vector<KeyPoint> &kp1_,
        vector<KeyPoint> &kp2_,
        vector<bool> &success_,
        bool inverse_ = true, bool has_initial_ = false) :
        img1(img1_), img2(img2_), kp1(kp1_), kp2(kp2_), success(success_), inverse(inverse_),
        has_initial(has_initial_) {} //初始化

    void calculateOpticalFlow(const Range &range);

private: //属性
    const Mat &img1;
    const Mat &img2;
    const vector<KeyPoint> &kp1;
    vector<KeyPoint> &kp2;
    vector<bool> &success;
    bool inverse = true;
    bool has_initial = false;
};

/**
 * single level optical flow
 * @param [in] img1 the first image
 * @param [in] img2 the second image
 * @param [in] kp1 keypoints in img1
 * @param [in|out] kp2 keypoints in img2, if empty, use initial guess in kp1
 * @param [out] success true if a keypoint is tracked successfully
 * @param [in] inverse use inverse formulation?
 */
//单层光流
void OpticalFlowSingleLevel(
    const Mat &img1,
    const Mat &img2,
    const vector<KeyPoint> &kp1,
    vector<KeyPoint> &kp2,
    vector<bool> &success,
    bool inverse = false,
    bool has_initial_guess = false
);

/**
 * multi level optical flow, scale of pyramid is set to 2 by default
 * the image pyramid will be create inside the function
 * @param [in] img1 the first pyramid
 * @param [in] img2 the second pyramid
 * @param [in] kp1 keypoints in img1
 * @param [out] kp2 keypoints in img2
 * @param [out] success true if a keypoint is tracked successfully
 * @param [in] inverse set true to enable inverse formulation
 */
//多层光流
void OpticalFlowMultiLevel(
    const Mat &img1,
    const Mat &img2,
    const vector<KeyPoint> &kp1,
    vector<KeyPoint> &kp2,
    vector<bool> &success,
    bool inverse = false
);

/**
 * get a gray scale value from reference image (bi-linear interpolated)
 * @param img
 * @param x
 * @param y
 * @return the interpolated value of this pixel
 */

//计算灰度
inline float GetPixelValue(const cv::Mat &img, float x, float y) {
    // boundary check
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    if (x >= img.cols - 1) x = img.cols - 2;
    if (y >= img.rows - 1) y = img.rows - 2;
    
    float xx = x - floor(x);
    float yy = y - floor(y);
    int x_a1 = std::min(img.cols - 1, int(x) + 1);
    int y_a1 = std::min(img.rows - 1, int(y) + 1);
    
    return (1 - xx) * (1 - yy) * img.at<uchar>(y, x)
    + xx * (1 - yy) * img.at<uchar>(y, x_a1)
    + (1 - xx) * yy * img.at<uchar>(y_a1, x)
    + xx * yy * img.at<uchar>(y_a1, x_a1);
}

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

    // images, note they are CV_8UC1, not CV_8UC3
    Mat img1 = imread(file_1, 0);
    Mat img2 = imread(file_2, 0);

    // key points, using GFTT here.//  获取keypoints,建立GFTT角点探测器
     //cv::FAST(img1,keypoints1,40);//这是直接提取Fast角点
    // 1)参数maxCorners:检测到的最大角点数量;
    //(2)参数qualityLevel:输出角点的质量等级,取值范围是 [ 0 , 1 ];如果某个候选点的角点响应值小于(qualityLeve * 最大角点响应值),则该点会被抛弃,相当于判定某候选点为角点的阈值;
    //(3)参数minDistance:两个角点间的最小距离,如果某两个角点间的距离小于minDistance,则会被认为是同一个角点;
    //(4)参数mask:如果有该掩膜,则只计算掩膜内的角点;
    //(5)参数blockSize:计算角点响应值的邻域大小,默认值为3;如果输入图像的分辨率比较大,可以选择比较大的blockSize;
    //(6)参数useHarrisDector:布尔类型,如果为true则使用Harris角点检测;默认为false,使用shi-tomas角点检测算法;
    //(7)参数k:只在使用Harris角点检测时才生效,也就是计算角点响应值时的系数k。

    vector<KeyPoint> kp1;
     //建立GFTT角点探测器
    Ptr<GFTTDetector> detector = GFTTDetector::create(500, 0.01, 20); // maximum 500 keypoints
    //算出图1的keypoints-kp1
    detector->detect(img1, kp1);
   
       //在图2中追踪图1的keypoints
       //---------gauss-newton--------------------//
    // now lets track these key points in the second image
    // first use single level LK in the validation picture
    vector<KeyPoint> kp2_single;
    vector<bool> success_single;
    OpticalFlowSingleLevel(img1, img2, kp1, kp2_single, success_single);

    // then test multi-level LK
    vector<KeyPoint> kp2_multi;
    vector<bool> success_multi;
    chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    OpticalFlowMultiLevel(img1, img2, kp1, kp2_multi, success_multi, true);
    chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
    auto time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
    cout << "optical flow by gauss-newton: " << time_used.count() << endl;

    // use opencv's flow for validation
    vector<Point2f> pt1, pt2; //要把Keypoint类型转为Point2f
    for (auto &kp: kp1) pt1.push_back(kp.pt);
    vector<uchar> status;
    vector<float> error;
    t1 = chrono::steady_clock::now();
    cv::calcOpticalFlowPyrLK(img1, img2, pt1, pt2, status, error);
    t2 = chrono::steady_clock::now();
    time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
    cout << "optical flow by opencv: " << time_used.count() << endl;

    // plot the differences of those functions
    Mat img2_single;
    cv::cvtColor(img2, img2_single, CV_GRAY2BGR);
    for (int i = 0; i < kp2_single.size(); i++) {
        if (success_single[i]) {     //success_single[i]表示在图2中是否跟踪到图1中对应的点
            cv::circle(img2_single, kp2_single[i].pt, 2, cv::Scalar(0, 250, 0), 2);//在图2中用圆标出跟踪到的点
            cv::line(img2_single, kp1[i].pt, kp2_single[i].pt, cv::Scalar(0, 250, 0));
        }
    }

    Mat img2_multi;
    cv::cvtColor(img2, img2_multi, CV_GRAY2BGR);
    for (int i = 0; i < kp2_multi.size(); i++) {
        if (success_multi[i]) {
            cv::circle(img2_multi, kp2_multi[i].pt, 2, cv::Scalar(0, 250, 0), 2);
            cv::line(img2_multi, kp1[i].pt, kp2_multi[i].pt, cv::Scalar(0, 250, 0));
        }
    }

    Mat img2_CV;
    cv::cvtColor(img2, img2_CV, CV_GRAY2BGR);
    for (int i = 0; i < pt2.size(); i++) {
        if (status[i]) {
            cv::circle(img2_CV, pt2[i], 2, cv::Scalar(0, 250, 0), 2);
            cv::line(img2_CV, pt1[i], pt2[i], cv::Scalar(0, 250, 0));
        }
    }

    cv::imshow("tracked single level", img2_single);
    cv::imshow("tracked multi level", img2_multi);
    cv::imshow("tracked by opencv", img2_CV);
    cv::waitKey(0);

    return 0;
}

void OpticalFlowSingleLevel(
    const Mat &img1,
    const Mat &img2,
    const vector<KeyPoint> &kp1,
    vector<KeyPoint> &kp2,
    vector<bool> &success,
    bool inverse, bool has_initial) {
    kp2.resize(kp1.size());  //让kp2的大小和 kp1一样
    success.resize(kp1.size()); //每一个追踪成功与否的标志
    OpticalFlowTracker tracker(img1, img2, kp1, kp2, success, inverse, has_initial); //初始化 构建光流追踪类
    //并行循环  std还没有学到这个,看不太懂,暂且当做计算光流函数调用?
    parallel_for_(Range(0, kp1.size()),
                  std::bind(&OpticalFlowTracker::calculateOpticalFlow, &tracker, placeholders::_1));
}

//类外实现成员函数
void OpticalFlowTracker::calculateOpticalFlow(const Range &range) {
    // parameters
    int half_patch_size = 4;  //4*4的块的边
    int iterations = 10;   //迭代次数
    for (size_t i = range.start; i < range.end; i++) {
        auto kp = kp1[i];  //用kp存图1中的关键点
        double dx = 0, dy = 0; // dx,dy need to be estimated //待优化系数初始值
        if (has_initial) {   //待优化的系数如果需要初始化  在刚开始的时候不可能进行下面的 *** 作,因为kp2这时候没有点
            dx = kp2[i].pt.x - kp.pt.x;
            dy = kp2[i].pt.y - kp.pt.y;
        }

        double cost = 0, lastCost = 0;
        bool succ = true; // indicate if this point succeeded

       //进行高斯牛顿的迭代
        Eigen::Matrix2d H = Eigen::Matrix2d::Zero();    // hessian
        Eigen::Vector2d b = Eigen::Vector2d::Zero();    // bias
        Eigen::Vector2d J;  // jacobian
        for (int iter = 0; iter < iterations; iter++) {
            if (inverse == false) {  //默认 inverse=false
                 //对 H ,b 进行初始化
                H = Eigen::Matrix2d::Zero();
                b = Eigen::Vector2d::Zero();
            } else {
                // only reset b  //只对b进行初始化
                b = Eigen::Vector2d::Zero();
            }

            cost = 0;  //每次迭代cost都要先置为0

             //计算 cost 和雅克比 J
            //4*4的块,假设在这个块里的关键点的移动都是一样的,所以直接对这个4*4的块进行高斯牛顿
            // compute cost and jacobian
            for (int x = -half_patch_size; x < half_patch_size; x++)
                for (int y = -half_patch_size; y < half_patch_size; y++) {
                    //计算e=I(x,y)(图1)-I(x+dx,y+dy)(图2)
                    double error = GetPixelValue(img1, kp.pt.x + x, kp.pt.y + y) -
                                   GetPixelValue(img2, kp.pt.x + x + dx, kp.pt.y + y + dy);;  // Jacobian
                    if (inverse == false) {
                         //这里乘了一个-1 ,表示梯度是减小的
                        J = -1.0 * Eigen::Vector2d(
                            0.5 * (GetPixelValue(img2, kp.pt.x + dx + x + 1, kp.pt.y + dy + y) -
                                   GetPixelValue(img2, kp.pt.x + dx + x - 1, kp.pt.y + dy + y)),
                            0.5 * (GetPixelValue(img2, kp.pt.x + dx + x, kp.pt.y + dy + y + 1) -
                                   GetPixelValue(img2, kp.pt.x + dx + x, kp.pt.y + dy + y - 1))
                        );
                    } else if (iter == 0) {   //如果是第一次迭代,雅克比矩阵用图1的点来算
                        // in inverse mode, J keeps same for all iterations
                        // NOTE this J does not change when dx, dy is updated, so we can store it and only compute error
                        J = -1.0 * Eigen::Vector2d(
                            0.5 * (GetPixelValue(img1, kp.pt.x + x + 1, kp.pt.y + y) -
                                   GetPixelValue(img1, kp.pt.x + x - 1, kp.pt.y + y)),
                            0.5 * (GetPixelValue(img1, kp.pt.x + x, kp.pt.y + y + 1) -
                                   GetPixelValue(img1, kp.pt.x + x, kp.pt.y + y - 1))
                        );
                    }
                     // compute H, b and set cost;  这里应该就很熟悉了  见 SLAM十四讲p129页
                    b += -error * J;
                    cost += error * error;
                    if (inverse == false || iter == 0) {
                        // also update H
                        H += J * J.transpose();
                    }
                }//一次迭代的高斯牛顿相关矩阵计算结束


            // compute update
            Eigen::Vector2d update = H.ldlt().solve(b);

            if (std::isnan(update[0])) {  //判断增量有没有用
                // sometimes occurred when we have a black or white patch and H is irreversible
                cout << "update is nan" << endl;
                succ = false;  //表示追踪失败
                break;
            }

            if (iter > 0 && cost > lastCost) {
                break;   //满足条件就停止迭代
            }

            // update dx, dy,    更新优化系数
            dx += update[0];
            dy += update[1];
            lastCost = cost;
            succ = true;   //这个快跟踪成功

            if (update.norm() < 1e-2) {
                // converge
                break;  // 如果增量比较小了,就停止迭代
            }
        }

        success[i] = succ;

        // set kp2
        kp2[i].pt = kp.pt + Point2f(dx, dy);
    }
}//所有的点迭代完

//多层光流
void OpticalFlowMultiLevel(
    const Mat &img1,
    const Mat &img2,
    const vector<KeyPoint> &kp1,
    vector<KeyPoint> &kp2,
    vector<bool> &success,
    bool inverse) {

    // parameters
    int pyramids = 4;  //金字塔的层数 也就是要降采样四次
    double pyramid_scale = 0.5;//缩放比例
    double scales[] = {1.0, 0.5, 0.25, 0.125};  //分别是 从原图缩放到1/8

    // create pyramids
    chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    vector<Mat> pyr1, pyr2; // image pyramids  容器,分别存放 不同缩放比例的图片
    //利用循环得到四层不同比例的图片

    for (int i = 0; i < pyramids; i++) {
        if (i == 0) {
            pyr1.push_back(img1);
            pyr2.push_back(img2); //pyr1[0] 和 pyr2[0] 放的分别是图1和图2的原图
        } else {
            Mat img1_pyr, img2_pyr;  //降采样后临时存放在 img1_pyr, img2_pyr
            //利用resize函数,调整 重置img1_pyr, img2_pyr的尺寸,
            cv::resize(pyr1[i - 1], img1_pyr,
                       cv::Size(pyr1[i - 1].cols * pyramid_scale, pyr1[i - 1].rows * pyramid_scale));
            cv::resize(pyr2[i - 1], img2_pyr,
                       cv::Size(pyr2[i - 1].cols * pyramid_scale, pyr2[i - 1].rows * pyramid_scale));
            pyr1.push_back(img1_pyr);
            pyr2.push_back(img2_pyr);
        }
    }
     //完成图像的缩放
    chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
    auto time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
    cout << "build pyramid time: " << time_used.count() << endl;
  //接下来缩放关键点
    // coarse-to-fine LK tracking in pyramids,从粗到细
    vector<KeyPoint> kp1_pyr, kp2_pyr;
     //这个循环得到的是最小的那一层缩放后的点
    for (auto &kp:kp1) {
        auto kp_top = kp;
        kp_top.pt *= scales[pyramids - 1];
        kp1_pyr.push_back(kp_top);
        kp2_pyr.push_back(kp_top);
    }
        //循环从最小的那一层开始,然后慢慢恢复到原始图片
    for (int level = pyramids - 1; level >= 0; level--) {
        // from coarse to fine
        success.clear();
        t1 = chrono::steady_clock::now();
          //这里应该就可以知道 has_initial是什么了,就是看图2中的点有没有初始化
        OpticalFlowSingleLevel(pyr1[level], pyr2[level], kp1_pyr, kp2_pyr, success, inverse, true);
        t2 = chrono::steady_clock::now();
        auto time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
        cout << "track pyr " << level << " cost time: " << time_used.count() << endl;

        if (level > 0) {
            for (auto &kp: kp1_pyr)
                kp.pt /= pyramid_scale;  //这里是 点*2 相当于把点放大为上一层的点(图1中的点)
            for (auto &kp: kp2_pyr)
                kp.pt /= pyramid_scale;//这里是 点*2 相当于把点放大为上一层的点(图2中预测的点)
        }
    }
//把四层都走完了
    // 最后再把走完四次降采样的点返回到kp2
    for (auto &kp: kp2_pyr)
        kp2.push_back(kp);
}

运行结果如下:
vim终端输出结果:

build pyramid time: 0.00653729
track pyr 3 cost time: 0.00181171
track pyr 2 cost time: 0.00190378
track pyr 1 cost time: 0.00146762
track pyr 0 cost time: 0.00218046
optical flow by gauss-newton: 0.0143036
optical flow by opencv: 0.0110589

8.2.2 直接法

代码及详细参考解释如下:

#include 
#include 
#include 
#include 

using namespace std;

typedef vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d>> VecVector2d;

// Camera intrinsics
double fx = 718.856, fy = 718.856, cx = 607.1928, cy = 185.2157;
// baseline
double baseline = 0.573;
// paths
string left_file = "/home/lmf37/桌面/slambook2/ch8/left.png";
string disparity_file = "/home/lmf37/桌面/slambook2/ch8/left.png";
boost::format fmt_others("/home/lmf37/桌面/slambook2/ch8/%06d.png");    // other files

// useful typedefs
typedef Eigen::Matrix<double, 6, 6> Matrix6d;
typedef Eigen::Matrix<double, 2, 6> Matrix26d;
typedef Eigen::Matrix<double, 6, 1> Vector6d;

/// class for accumulator jacobians in parallel
class JacobianAccumulator {
public:
    JacobianAccumulator(
        const cv::Mat &img1_,
        const cv::Mat &img2_,
        const VecVector2d &px_ref_,  //左图的像素点
        const vector<double> depth_ref_, //左图的像素点对应的深度
        Sophus::SE3d &T21_) :  //从左图变换到友图的变换矩阵
        img1(img1_), img2(img2_), px_ref(px_ref_), depth_ref(depth_ref_), T21(T21_) {
        projection = VecVector2d(px_ref.size(), Eigen::Vector2d(0, 0));
    }

    /// accumulate jacobians in a range
    void accumulate_jacobian(const cv::Range &range);

    /// get hessian matrix
    Matrix6d hessian() const { return H; }

    /// get bias
    Vector6d bias() const { return b; }

    /// get total cost
    double cost_func() const { return cost; }

    /// get projected points
    VecVector2d projected_points() const { return projection; }

    /// reset h, b, cost to zero
    void reset() {
        H = Matrix6d::Zero();
        b = Vector6d::Zero();
        cost = 0;
    }

private:
    const cv::Mat &img1;
    const cv::Mat &img2;
    const VecVector2d &px_ref;
    const vector<double> depth_ref;
    Sophus::SE3d &T21;
    VecVector2d projection; // projected points

    std::mutex hessian_mutex;
    Matrix6d H = Matrix6d::Zero();
    Vector6d b = Vector6d::Zero();
    double cost = 0;
};

/**
 * pose estimation using direct method
 * @param img1
 * @param img2
 * @param px_ref
 * @param depth_ref
 * @param T21
 */
void DirectPoseEstimationMultiLayer(
    const cv::Mat &img1,
    const cv::Mat &img2,
    const VecVector2d &px_ref,
    const vector<double> depth_ref,
    Sophus::SE3d &T21
);

/**
 * pose estimation using direct method
 * @param img1
 * @param img2
 * @param px_ref
 * @param depth_ref
 * @param T21
 */
void DirectPoseEstimationSingleLayer(
    const cv::Mat &img1,
    const cv::Mat &img2,
    const VecVector2d &px_ref,
    const vector<double> depth_ref,
    Sophus::SE3d &T21
);

// bilinear interpolation  双线性输入
inline float GetPixelValue(const cv::Mat &img, float x, float y) {
    // boundary check  边界检测
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    if (x >= img.cols) x = img.cols - 1;
    if (y >= img.rows) y = img.rows - 1;
    uchar *data = &img.data[int(y) * img.step + int(x)];
    float xx = x - floor(x);
    float yy = y - floor(y);
    return float(
        (1 - xx) * (1 - yy) * data[0] +
        xx * (1 - yy) * data[1] +
        (1 - xx) * yy * data[img.step] +
        xx * yy * data[img.step + 1]
    );
}

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

    cv::Mat left_img = cv::imread(left_file, 0);
    cv::Mat disparity_img = cv::imread(disparity_file, 0);

    // let's randomly pick pixels in the first image and generate some 3d points in the first image's frame
    cv::RNG rng;
    int nPoints = 2000;
    int boarder = 20;
    VecVector2d pixels_ref;
    vector<double> depth_ref;
    //利用opencv的随机产生器,我们在边界以内随机产生2000个点
    // generate pixels in ref and load depth data
    for (int i = 0; i < nPoints; i++) {
        int x = rng.uniform(boarder, left_img.cols - boarder);  // don't pick pixels close to boarder
        int y = rng.uniform(boarder, left_img.rows - boarder);  // don't pick pixels close to boarder
        int disparity = disparity_img.at<uchar>(y, x);
        double depth = fx * baseline / disparity; // you know this is disparity to depth   这是利用视差求深度
        //公式就是fx * baseline / disparity  baseline是基线,disparity是视差
        depth_ref.push_back(depth);  //得到左图像素点的深度信息
        pixels_ref.push_back(Eigen::Vector2d(x, y));   //得到左图中随机产生的像素点 放在pixels_ref中
    }

    // estimates 01~05.png's pose using this information
    Sophus::SE3d T_cur_ref;
        //利用直接法求出左图与5个图的位姿变幻
    for (int i = 1; i < 6; i++) {  // 1~10
        cv::Mat img = cv::imread((fmt_others % i).str(), 0);
        // try single layer by uncomment this line
        // DirectPoseEstimationSingleLayer(left_img, img, pixels_ref, depth_ref, T_cur_ref);
        DirectPoseEstimationMultiLayer(left_img, img, pixels_ref, depth_ref, T_cur_ref);
    }
    return 0;
}

void DirectPoseEstimationSingleLayer(
    const cv::Mat &img1,
    const cv::Mat &img2,
    const VecVector2d &px_ref,
    const vector<double> depth_ref,
    Sophus::SE3d &T21) {

    const int iterations = 10;
    double cost = 0, lastCost = 0;
    auto t1 = chrono::steady_clock::now();
    JacobianAccumulator jaco_accu(img1, img2, px_ref, depth_ref, T21);//定义雅克比类,调用有参构造初始化jaco_accu
    //迭代

    for (int iter = 0; iter < iterations; iter++) {
        jaco_accu.reset();//功能就是上面的注释,也就是初始化
        //和手写光流一样,利用并行循环,调用雅克比类里面的计算雅克比的函数
        cv::parallel_for_(cv::Range(0, px_ref.size()),
                          std::bind(&JacobianAccumulator::accumulate_jacobian, &jaco_accu, std::placeholders::_1));
        Matrix6d H = jaco_accu.hessian();  //得到H矩阵
        Vector6d b = jaco_accu.bias();

        // solve update and put it into estimation
        Vector6d update = H.ldlt().solve(b);;  //求增量
        T21 = Sophus::SE3d::exp(update) * T21;  //更新待优化系数,也就是位姿
        cost = jaco_accu.cost_func();  //得到cost

        if (std::isnan(update[0])) {  //判断更新量是否有效
            // sometimes occurred when we have a black or white patch and H is irreversible
            cout << "update is nan" << endl;
            break;
        }
        if (iter > 0 && cost > lastCost) {  //满足这个条件停止迭代
            cout << "cost increased: " << cost << ", " << lastCost << endl;
            break;
        }
        if (update.norm() < 1e-3) {  //如果增量足够小,也停止迭代
            // converge
            break;
        }

        lastCost = cost;
        cout << "iteration: " << iter << ", cost: " << cost << endl;
    }

    cout << "T21 = \n" << T21.matrix() << endl;
    auto t2 = chrono::steady_clock::now();
    auto time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
    cout << "direct method for single layer: " << time_used.count() << endl;

    // plot the projected pixels here
    cv::Mat img2_show;
    cv::cvtColor(img2, img2_show, CV_GRAY2BGR);
    VecVector2d projection = jaco_accu.projected_points();
    for (size_t i = 0; i < px_ref.size(); ++i) {
        auto p_ref = px_ref[i];
        auto p_cur = projection[i];
        if (p_cur[0] > 0 && p_cur[1] > 0) {
            cv::circle(img2_show, cv::Point2f(p_cur[0], p_cur[1]), 2, cv::Scalar(0, 250, 0), 2);
            cv::line(img2_show, cv::Point2f(p_ref[0], p_ref[1]), cv::Point2f(p_cur[0], p_cur[1]),
                     cv::Scalar(0, 250, 0));
        }
    }
    cv::imshow("current", img2_show);
    cv::waitKey();
}

void JacobianAccumulator::accumulate_jacobian(const cv::Range &range) {

    // parameters
    const int half_patch_size = 1;  //这里又是一个边界
    int cnt_good = 0;
    Matrix6d hessian = Matrix6d::Zero();
    Vector6d bias = Vector6d::Zero();
    double cost_tmp = 0;

    for (size_t i = range.start; i < range.end; i++) {

        // compute the projection in the second image
        Eigen::Vector3d point_ref =
            depth_ref[i] * Eigen::Vector3d((px_ref[i][0] - cx) / fx, (px_ref[i][1] - cy) / fy, 1);//左图相机下的坐标
        Eigen::Vector3d point_cur = T21 * point_ref;//得到右图下相机的坐标 里面的额T21是待优化的位姿
        if (point_cur[2] < 0)   // depth invalid
            continue;

        float u = fx * point_cur[0] / point_cur[2] + cx, v = fy * point_cur[1] / point_cur[2] + cy;//得到右图下对应的像素点
        //判断这个点是不是在边界里面
        if (u < half_patch_size || u > img2.cols - half_patch_size || v < half_patch_size ||
            v > img2.rows - half_patch_size)
            continue;

        projection[i] = Eigen::Vector2d(u, v);//把右图的像素点放在 projection[i]里面进行保存
        double X = point_cur[0], Y = point_cur[1], Z = point_cur[2],
            Z2 = Z * Z, Z_inv = 1.0 / Z, Z2_inv = Z_inv * Z_inv;
        cnt_good++;

        // and compute error and jacobian
        //以像素点为中心 上下左右扩展 1 的小块里,这里的原因应该和光流一样,假设这个小块里面的点的移动是一样的
        for (int x = -half_patch_size; x <= half_patch_size; x++)
            for (int y = -half_patch_size; y <= half_patch_size; y++) {

                double error = GetPixelValue(img1, px_ref[i][0] + x, px_ref[i][1] + y) -
                               GetPixelValue(img2, u + x, v + y);
                Matrix26d J_pixel_xi;
                Eigen::Vector2d J_img_pixel;
                   //下面的雅克比矩阵是书上的公式  雅克比矩阵分成了两个部分,一个是I对水平方向的梯度 一个是水平方向对位姿(李代数)的梯度
                J_pixel_xi(0, 0) = fx * Z_inv;
                J_pixel_xi(0, 1) = 0;
                J_pixel_xi(0, 2) = -fx * X * Z2_inv;
                J_pixel_xi(0, 3) = -fx * X * Y * Z2_inv;
                J_pixel_xi(0, 4) = fx + fx * X * X * Z2_inv;
                J_pixel_xi(0, 5) = -fx * Y * Z_inv;

                J_pixel_xi(1, 0) = 0;
                J_pixel_xi(1, 1) = fy * Z_inv;
                J_pixel_xi(1, 2) = -fy * Y * Z2_inv;
                J_pixel_xi(1, 3) = -fy - fy * Y * Y * Z2_inv;
                J_pixel_xi(1, 4) = fy * X * Y * Z2_inv;
                J_pixel_xi(1, 5) = fy * X * Z_inv;

                J_img_pixel = Eigen::Vector2d(
                    0.5 * (GetPixelValue(img2, u + 1 + x, v + y) - GetPixelValue(img2, u - 1 + x, v + y)),
                    0.5 * (GetPixelValue(img2, u + x, v + 1 + y) - GetPixelValue(img2, u + x, v - 1 + y))
                );

                // total jacobian
                Vector6d J = -1.0 * (J_img_pixel.transpose() * J_pixel_xi).transpose();//得到雅克比矩阵

                hessian += J * J.transpose();
                bias += -error * J;
                cost_tmp += error * error;
            }
    }

    if (cnt_good) {
        // set hessian, bias and cost
        unique_lock<mutex> lck(hessian_mutex);
        H += hessian;
        b += bias;
        cost += cost_tmp / cnt_good;
    }
}

void DirectPoseEstimationMultiLayer(
    const cv::Mat &img1,
    const cv::Mat &img2,
    const VecVector2d &px_ref,
    const vector<double> depth_ref,
    Sophus::SE3d &T21) {

    // parameters
    int pyramids = 4;
    double pyramid_scale = 0.5;
    double scales[] = {1.0, 0.5, 0.25, 0.125};

    // create pyramids 构建金字塔
    vector<cv::Mat> pyr1, pyr2; // image pyramids
    for (int i = 0; i < pyramids; i++) {
        if (i == 0) {
            pyr1.push_back(img1);
            pyr2.push_back(img2);
        } else {
            cv::Mat img1_pyr, img2_pyr;
            cv::resize(pyr1[i - 1], img1_pyr,
                       cv::Size(pyr1[i - 1].cols * pyramid_scale, pyr1[i - 1].rows * pyramid_scale));
            cv::resize(pyr2[i - 1], img2_pyr,
                       cv::Size(pyr2[i - 1].cols * pyramid_scale, pyr2[i - 1].rows * pyramid_scale));
            pyr1.push_back(img1_pyr); //左图
            pyr2.push_back(img2_pyr);//右图
        }
    }

    double fxG = fx, fyG = fy, cxG = cx, cyG = cy;  // backup the old values
    //利用循环,我们可以从最小层到最大层(原始层)
    for (int level = pyramids - 1; level >= 0; level--) {
        VecVector2d px_ref_pyr; // set the keypoints in this pyramid level
        for (auto &px: px_ref) {
            px_ref_pyr.push_back(scales[level] * px);
        }

        // scale fx, fy, cx, cy in different pyramid levels  这里面的内参也要缩放 但深度不用,因为深度不变
        fx = fxG * scales[level];
        fy = fyG * scales[level];
        cx = cxG * scales[level];
        cy = cyG * scales[level];
        //对不同布局的图片进行单层的位姿估计
        DirectPoseEstimationSingleLayer(pyr1[level], pyr2[level], px_ref_pyr, depth_ref, T21);
    }

}

运行结果如下:
vim终端输出结果:

iteration: 0, cost: 277244
iteration: 1, cost: 177412
iteration: 2, cost: 164001
T21 = 
    0.999995  0.000111585  -0.00320604    0.0215113
-0.000103205     0.999997   0.00261377   0.00195144
  0.00320632  -0.00261342     0.999991   -0.0780015
           0            0            0            1
direct method for single layer: 0.00228075
iteration: 0, cost: 275959
iteration: 1, cost: 274780
iteration: 2, cost: 273955
T21 = 
   0.999986  0.00176637 -0.00490844   0.0258969
-0.00175892    0.999997  0.00152261  0.00315992
 0.00491111 -0.00151396    0.999987  -0.0772787
          0           0           0           1
direct method for single layer: 0.00416339
iteration: 0, cost: 383805
iteration: 1, cost: 381527
T21 = 
    0.99998  0.00142533 -0.00616037   0.0292343
-0.00141644    0.999998  0.00144786   0.0036321
 0.00616242  -0.0014391     0.99998  -0.0758864
          0           0           0           1
direct method for single layer: 0.00518361
iteration: 0, cost: 471983
T21 = 
    0.999978   0.00135828  -0.00649451    0.0291079
 -0.00135351     0.999999  0.000737908   0.00520567
  0.00649551 -0.000729102     0.999979   -0.0746946
           0            0            0            1
direct method for single layer: 0.00375108
iteration: 0, cost: 384789
iteration: 1, cost: 328197
iteration: 2, cost: 310605
cost increased: 313470, 310605
T21 = 
    0.999995  -0.00320847   0.00026232    0.0239358
  0.00320692     0.999979   0.00569348  0.000340532
-0.000280582  -0.00569261     0.999984    -0.137857
           0            0            0            1
direct method for single layer: 0.00635167
iteration: 0, cost: 448856
iteration: 1, cost: 446798
T21 = 
    0.999999 -0.000805785  0.000614737    0.0248108
  0.00080313      0.99999   0.00430696   0.00169772
-0.000618202  -0.00430646     0.999991    -0.138368
           0            0            0            1
direct method for single layer: 0.00479619
iteration: 0, cost: 579261
iteration: 1, cost: 578264
T21 = 
           1 -0.000576088   0.00053065    0.0223687
 0.000574016     0.999992   0.00389661   0.00352497
-0.000532891  -0.00389631     0.999992    -0.136198
           0            0            0            1
direct method for single layer: 0.00573347
T21 = 
           1 -0.000231715  0.000399276    0.0225729
 0.000230156     0.999992    0.0039006   0.00317675
-0.000400176   -0.0039005     0.999992    -0.136744
           0            0            0            1
direct method for single layer: 0.00204325
iteration: 0, cost: 520867
iteration: 1, cost: 451558
iteration: 2, cost: 426639
iteration: 3, cost: 416049
iteration: 4, cost: 411591
iteration: 5, cost: 410514
cost increased: 410832, 410514
T21 = 
   0.999826  -0.0109322   0.0151292 -0.00447886
   0.010763    0.999879   0.0112181 -0.00305909
   -0.01525  -0.0110533    0.999823   -0.194834
          0           0           0           1
direct method for single layer: 0.0112311
iteration: 0, cost: 576504
cost increased: 579174, 576504
T21 = 
   0.999829  -0.0114841   0.0144719 -0.00479152
  0.0113156    0.999868   0.0116715 -0.00501959
  -0.014604  -0.0115057    0.999827   -0.192742
          0           0           0           1
direct method for single layer: 0.00340097
iteration: 0, cost: 739639
iteration: 1, cost: 732122
iteration: 2, cost: 727067
iteration: 3, cost: 723957
T21 = 
   0.999793  -0.0139987   0.0147765 -0.00881123
  0.0138175    0.999829   0.0122976 -0.00885388
 -0.0149462  -0.0120909    0.999815    -0.19462
          0           0           0           1
direct method for single layer: 0.00258275
T21 = 
   0.999793  -0.0141379   0.0146219 -0.00824524
  0.0139585    0.999827   0.0122983 -0.00849472
 -0.0147932  -0.0120917    0.999817   -0.195236
          0           0           0           1
direct method for single layer: 0.00226886
iteration: 0, cost: 617259
iteration: 1, cost: 580249
iteration: 2, cost: 571224
iteration: 3, cost: 567753
iteration: 4, cost: 565462
cost increased: 565847, 565462
T21 = 
   0.999689  -0.0183219   0.0169163 -0.00298079
  0.0180605    0.999717   0.0154795  -0.0068204
 -0.0171952  -0.0151692    0.999737   -0.253313
          0           0           0           1
direct method for single layer: 0.00581337
iteration: 0, cost: 786046
iteration: 1, cost: 782685
iteration: 2, cost: 781001
iteration: 3, cost: 775082
iteration: 4, cost: 770541
iteration: 5, cost: 767106
iteration: 6, cost: 764084
iteration: 7, cost: 761340
cost increased: 764499, 761340
T21 = 
  0.999492 -0.0217308  0.0232922 -0.0248079
 0.0213156   0.999612  0.0179269 -0.0135738
-0.0236727 -0.0174213   0.999568  -0.244708
         0          0          0          1
direct method for single layer: 0.0144773
iteration: 0, cost: 937600
iteration: 1, cost: 932171
iteration: 2, cost: 928627
iteration: 3, cost: 925946
iteration: 4, cost: 923001
iteration: 5, cost: 921250
T21 = 
  0.999374 -0.0237868  0.0261876 -0.0343946
 0.0233525   0.999587   0.016765 -0.0109223
-0.0265756 -0.0161429   0.999516  -0.241336
         0          0          0          1
direct method for single layer: 0.011933
T21 = 
  0.999363 -0.0240834  0.0263341 -0.0345284
   0.02364   0.999576  0.0170217 -0.0114092
-0.0267329 -0.0163883   0.999508  -0.242106
         0          0          0          1
direct method for single layer: 0.00212517
iteration: 0, cost: 775750
iteration: 1, cost: 747633
iteration: 2, cost: 733562
iteration: 3, cost: 725257
iteration: 4, cost: 722220
iteration: 5, cost: 718842
iteration: 6, cost: 717742
iteration: 7, cost: 717008
iteration: 8, cost: 716693
iteration: 9, cost: 716040
T21 = 
  0.999351 -0.0216249  0.0288062 -0.0280944
 0.0209009   0.999464  0.0252014 -0.0230922
-0.0293358  -0.024583   0.999267  -0.310772
         0          0          0          1
direct method for single layer: 0.0138962
iteration: 0, cost: 931455
iteration: 1, cost: 923083
iteration: 2, cost: 919032
iteration: 3, cost: 917371
iteration: 4, cost: 914834
iteration: 5, cost: 912760
cost increased: 912799, 912760
T21 = 
  0.999454 -0.0192946  0.0268173 -0.0197849
 0.0187353   0.999605  0.0209536 -0.0182087
 -0.027211 -0.0204397   0.999421  -0.314051
         0          0          0          1
direct method for single layer: 0.0114514
T21 = 
  0.999459 -0.0191705  0.0267338 -0.0198762
 0.0186186   0.999611  0.0207438  -0.018036
-0.0271211 -0.0202348   0.999427  -0.314388
         0          0          0          1
direct method for single layer: 0.00235047
iteration: 0, cost: 1.20086e+06
iteration: 1, cost: 1.1915e+06
iteration: 2, cost: 1.18689e+06
iteration: 3, cost: 1.18287e+06
T21 = 
  0.999448 -0.0180128  0.0279324 -0.0217201
 0.0174133   0.999616  0.0215579 -0.0219891
  -0.02831 -0.0210596   0.999377  -0.319564
         0          0          0          1
direct method for single layer: 0.00888029

bug调试

!!!温馨提示 修改文件路径 😃
一堆报错

Consolidate compiler generated dependencies of target optical_flow
[ 25%] Building CXX object CMakeFiles/optical_flow.dir/optical_flow.cpp.o
[ 50%] Linking CXX executable optical_flow
[ 50%] Built target optical_flow
[ 75%] Building CXX object CMakeFiles/direct_method.dir/direct_method.cpp.o
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:109:79: error:decay_t’ is not a member of ‘std’
 bool is_weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
                                                                     ^~~~~~~
/usr/local/include/sigslot/signal.hpp:109:79: note: suggested alternative: ‘decay’
 bool is_weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
                                                                     ^~~~~~~
                                                                               decay
/usr/local/include/sigslot/signal.hpp:109:79: error:decay_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:109:79: note: suggested alternative: ‘decay’
 bool is_weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
                                                                     ^~~~~~~
                                                                               decay
/usr/local/include/sigslot/signal.hpp:109:87: error: template argument 1 is invalid
 weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
                                                                     ^
/usr/local/include/sigslot/signal.hpp:109:92: error:::value’ has not been declared
 weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
                                                                          ^~~~~
/usr/local/include/sigslot/signal.hpp:109:92: note: suggested alternative:
In file included from /usr/local/include/fmt/format.h:48:0,
                 from /usr/local/include/sophus/common.hpp:36,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/core.h:1208:35: note:   ‘fmt::v8::detail::value’
 template <typename Context> class value {
                                   ^~~~~
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:132:53: error:remove_pointer_t’ is not a member of ‘std’
                                                std::remove_pointer_t<T>>::value;
                                                     ^~~~~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:132:53: note: suggested alternative: ‘remove_pointer’
                                                std::remove_pointer_t<T>>::value;
                                                     ^~~~~~~~~~~~~~~~
                                                     remove_pointer
/usr/local/include/sigslot/signal.hpp:132:53: error:remove_pointer_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:132:53: note: suggested alternative: ‘remove_pointer’
                                                std::remove_pointer_t<T>>::value;
                                                     ^~~~~~~~~~~~~~~~
                                                     remove_pointer
/usr/local/include/sigslot/signal.hpp:132:70: error: template argument 2 is invalid
                                               std::remove_pointer_t<T>>::value;
                                                                     ^
/usr/local/include/sigslot/signal.hpp:132:75: error:::value’ has not been declared
                                               std::remove_pointer_t<T>>::value;
                                                                          ^~~~~
/usr/local/include/sigslot/signal.hpp:132:75: note: suggested alternative:
In file included from /usr/local/include/fmt/format.h:48:0,
                 from /usr/local/include/sophus/common.hpp:36,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/core.h:1208:35: note:   ‘fmt::v8::detail::value’
 template <typename Context> class value {
                                   ^~~~~
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:223:32: error:enable_if_t’ is not a member of ‘std’
 struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
                                ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:223:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:223:32: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:223:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:223:62: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::function_traits’
 struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
                                                              ^~
/usr/local/include/sigslot/signal.hpp:223:62: note:   expected a type, got ‘(<expression error> < is_func_v<T>)/usr/local/include/sigslot/signal.hpp:223:64: error: expected unqualified-id before ‘>’ token
 struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
                                                                ^
/usr/local/include/sigslot/signal.hpp:233:33: error:enable_if_t’ is not a member of ‘std’
 struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
                                 ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:233:33: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
                                 ^~~~~~~~~~~
                                 __enable_if_t
/usr/local/include/sigslot/signal.hpp:233:33: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:233:33: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
                                 ^~~~~~~~~~~
                                 __enable_if_t
/usr/local/include/sigslot/signal.hpp:233:63: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::function_traits’
 struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
                                                               ^~
/usr/local/include/sigslot/signal.hpp:233:63: note:   expected a type, got ‘(<expression error> < is_func_v<T>)/usr/local/include/sigslot/signal.hpp:233:65: error: expected unqualified-id before ‘>’ token
 struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
                                                                 ^
/usr/local/include/sigslot/signal.hpp:243:32: error:enable_if_t’ is not a member of ‘std’
 struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
                                ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:243:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:243:32: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:243:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:243:61: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::function_traits’
 struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
                                                             ^~
/usr/local/include/sigslot/signal.hpp:243:61: note:   expected a type, got ‘(<expression error> < is_pmf_v<T>)/usr/local/include/sigslot/signal.hpp:243:63: error: expected unqualified-id before ‘>’ token
 struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
                                                               ^
/usr/local/include/sigslot/signal.hpp:254:32: error:enable_if_t’ is not a member of ‘std’
 struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
                                ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:254:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:254:32: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:254:32: note: suggested alternative: ‘__enable_if_t’
 struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:254:72: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::function_traits’
 struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
                                                                        ^~
/usr/local/include/sigslot/signal.hpp:254:72: note:   expected a type, got ‘(<expression error> < has_call_operator_v<T>)/usr/local/include/sigslot/signal.hpp:254:74: error: expected unqualified-id before ‘>’ token
 struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
                                                                          ^
/usr/local/include/sigslot/signal.hpp: In function ‘sigslot::detail::func_ptr sigslot::detail::get_function_ptr(const T&):
/usr/local/include/sigslot/signal.hpp:269:26: error:decay_t’ is not a member of ‘std’
     function_traits<std::decay_t<T>>::ptr(t, d);
                          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:269:26: note: suggested alternative: ‘decay’
     function_traits<std::decay_t<T>>::ptr(t, d);
                          ^~~~~~~
                          decay
/usr/local/include/sigslot/signal.hpp:269:26: error:decay_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:269:26: note: suggested alternative: ‘decay’
     function_traits<std::decay_t<T>>::ptr(t, d);
                          ^~~~~~~
                          decay
/usr/local/include/sigslot/signal.hpp:269:34: error: template argument 1 is invalid
     function_traits<std::decay_t<T>>::ptr(t, d);
                                  ^
/usr/local/include/sigslot/signal.hpp:269:35: error: expected unqualified-id before ‘>’ token
     function_traits<std::decay_t<T>>::ptr(t, d);
                                   ^~
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:291:32: error:enable_if_t’ is not a member of ‘std’
 struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
                                ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:291:32: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:291:32: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:291:32: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
                                ^~~~~~~~~~~
                                __enable_if_t
/usr/local/include/sigslot/signal.hpp:291:66: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::object_pointer’
 struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
                                                                  ^~
/usr/local/include/sigslot/signal.hpp:291:66: note:   expected a type, got ‘(<expression error> < is_pointer_v<T*>)/usr/local/include/sigslot/signal.hpp:291:68: error: expected unqualified-id before ‘>’ token
 struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
                                                                    ^
/usr/local/include/sigslot/signal.hpp:298:31: error:enable_if_t’ is not a member of ‘std’
 struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
                               ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:298:31: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
                               ^~~~~~~~~~~
                               __enable_if_t
/usr/local/include/sigslot/signal.hpp:298:31: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:298:31: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
                               ^~~~~~~~~~~
                               __enable_if_t
/usr/local/include/sigslot/signal.hpp:298:65: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::object_pointer’
 struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
                                                                 ^~
/usr/local/include/sigslot/signal.hpp:298:65: note:   expected a type, got ‘(<expression error> < is_weak_ptr_v<T>)/usr/local/include/sigslot/signal.hpp:298:67: error: expected unqualified-id before ‘>’ token
 struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
                                                                   ^
/usr/local/include/sigslot/signal.hpp:306:31: error:enable_if_t’ is not a member of ‘std’
 struct object_pointer<T, std::enable_if_t<!trait::is_pointer_v<T> &&
                               ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:306:31: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T, std::enable_if_t<!trait::is_pointer_v<T> &&
                               ^~~~~~~~~~~
                               __enable_if_t
/usr/local/include/sigslot/signal.hpp:306:31: error:enable_if_t’ is not a member of ‘std’
/usr/local/include/sigslot/signal.hpp:306:31: note: suggested alternative: ‘__enable_if_t’
 struct object_pointer<T, std::enable_if_t<!trait::is_pointer_v<T> &&
                               ^~~~~~~~~~~
                               __enable_if_t
/usr/local/include/sigslot/signal.hpp:308:76: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class> struct sigslot::detail::object_pointer’
                                           trait::is_weak_ptr_compatible_v<T>>>
                                                                            ^~
/usr/local/include/sigslot/signal.hpp:308:76: note:   expected a type, got ‘(((<expression error> < (! is_pointer_v<T>)) && (! is_weak_ptr_v<T>)) && is_weak_ptr_compatible_v<T>)/usr/local/include/sigslot/signal.hpp:308:78: error: expected unqualified-id before ‘>’ token
                                           trait::is_weak_ptr_compatible_v<T>>>
                                                                              ^
/usr/local/include/sigslot/signal.hpp:398:41: error: ‘std::enable_if_t’ has not been declared
     explicit copy_on_write(U && x, std::enable_if_t<!std::is_same<std::decay_t<U>,
                                         ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:398:52: error: expected ‘,’ or ‘...’ before ‘<’ token
     explicit copy_on_write(U && x, std::enable_if_t<!std::is_same<std::decay_t<U>,
                                                    ^
/usr/local/include/sigslot/signal.hpp:532:18: error: ‘index’ function uses ‘auto’ type specifier without trailing return type
     auto index() const {
                  ^~~~~
/usr/local/include/sigslot/signal.hpp:532:18: note: deduced return type only available with -std=c++14 or -std=gnu++14
/usr/local/include/sigslot/signal.hpp:536:17: error: ‘index’ function uses ‘auto’ type specifier without trailing return type
     auto& index() {
                 ^
/usr/local/include/sigslot/signal.hpp:536:17: note: deduced return type only available with -std=c++14 or -std=gnu++14
/usr/local/include/sigslot/signal.hpp:793:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<function_traits<C>::must_check_object, bool>
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:799:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<!function_traits<C>::must_check_object, bool>
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:876:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Func> func;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot<Func, Args>::slot(sigslot::detail::cleanable&, F&&, Gid):
/usr/local/include/sigslot/signal.hpp:858:11: error: class ‘sigslot::detail::slot<Func, Args>’ does not have any field named ‘func’
         , func{std::forward<F>(f)} {}
           ^~~~
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot<Func, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:866:33: error: ‘func’ was not declared in this scope
         return get_function_ptr(func);
                                 ^~~~
/usr/local/include/sigslot/signal.hpp:866:33: note: suggested alternative: ‘Func’
         return get_function_ptr(func);
                                 ^~~~
                                 Func
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot<Func, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:871:23: error: ‘func’ was not declared in this scope
         return typeid(func);
                       ^~~~
/usr/local/include/sigslot/signal.hpp:871:23: note: suggested alternative: ‘Func’
         return typeid(func);
                       ^~~~
                       Func
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:908:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Func> func;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot_extended<Func, Args>::slot_extended(sigslot::detail::cleanable&, F&&, sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:888:11: error: class ‘sigslot::detail::slot_extended<Func, Args>’ does not have any field named ‘func’
         , func{std::forward<F>(f)} {}
           ^~~~
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot_extended<Func, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:898:33: error: ‘func’ was not declared in this scope
         return get_function_ptr(func);
                                 ^~~~
/usr/local/include/sigslot/signal.hpp:898:33: note: suggested alternative: ‘Func’
         return get_function_ptr(func);
                                 ^~~~
                                 Func
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot_extended<Func, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:903:23: error: ‘func’ was not declared in this scope
         return typeid(func);
                       ^~~~
/usr/local/include/sigslot/signal.hpp:903:23: note: suggested alternative: ‘Func’
         return typeid(func);
                       ^~~~
                       Func
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:945:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Pmf> pmf;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:946:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Ptr> ptr;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot_pmf<Pmf, Ptr, Args>::slot_pmf(sigslot::detail::cleanable&, F&&, P&&, sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:922:11: error: class ‘sigslot::detail::slot_pmf<Pmf, Ptr, Args>’ does not have any field named ‘pmf’
         , pmf{std::forward<F>(f)}
           ^~~
/usr/local/include/sigslot/signal.hpp:923:11: error: class ‘sigslot::detail::slot_pmf<Pmf, Ptr, Args>’ does not have any field named ‘ptr’
         , ptr{std::forward<P>(p)} {}
           ^~~
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::detail::slot_pmf<Pmf, Ptr, Args>::call_slot(Args ...):
/usr/local/include/sigslot/signal.hpp:927:12: error: ‘ptr’ was not declared in this scope
         ((*ptr).*pmf)(args...);
            ^~~
/usr/local/include/sigslot/signal.hpp:927:12: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:927:18: error: ‘pmf’ was not declared in this scope
         ((*ptr).*pmf)(args...);
                  ^~~
/usr/local/include/sigslot/signal.hpp:927:18: note: suggested alternative: ‘Pmf’
         ((*ptr).*pmf)(args...);
                  ^~~
                  Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot_pmf<Pmf, Ptr, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:931:33: error: ‘pmf’ was not declared in this scope
         return get_function_ptr(pmf);
                                 ^~~
/usr/local/include/sigslot/signal.hpp:931:33: note: suggested alternative: ‘Pmf’
         return get_function_ptr(pmf);
                                 ^~~
                                 Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘const void* sigslot::detail::slot_pmf<Pmf, Ptr, Args>::get_object() const:
/usr/local/include/sigslot/signal.hpp:935:31: error: ‘ptr’ was not declared in this scope
         return get_object_ptr(ptr);
                               ^~~
/usr/local/include/sigslot/signal.hpp:935:31: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot_pmf<Pmf, Ptr, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:940:23: error: ‘pmf’ was not declared in this scope
         return typeid(pmf);
                       ^~~
/usr/local/include/sigslot/signal.hpp:940:23: note: suggested alternative: ‘Pmf’
         return typeid(pmf);
                       ^~~
                       Pmf
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:982:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Pmf> pmf;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:983:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Ptr> ptr;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>::slot_pmf_extended(sigslot::detail::cleanable&, F&&, P&&, sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:958:11: error: class ‘sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>’ does not have any field named ‘pmf’
         , pmf{std::forward<F>(f)}
           ^~~
/usr/local/include/sigslot/signal.hpp:959:11: error: class ‘sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>’ does not have any field named ‘ptr’
         , ptr{std::forward<P>(p)} {}
           ^~~
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>::call_slot(Args ...):
/usr/local/include/sigslot/signal.hpp:965:12: error: ‘ptr’ was not declared in this scope
         ((*ptr).*pmf)(conn, args...);
            ^~~
/usr/local/include/sigslot/signal.hpp:965:12: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:965:18: error: ‘pmf’ was not declared in this scope
         ((*ptr).*pmf)(conn, args...);
                  ^~~
/usr/local/include/sigslot/signal.hpp:965:18: note: suggested alternative: ‘Pmf’
         ((*ptr).*pmf)(conn, args...);
                  ^~~
                  Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:969:33: error: ‘pmf’ was not declared in this scope
         return get_function_ptr(pmf);
                                 ^~~
/usr/local/include/sigslot/signal.hpp:969:33: note: suggested alternative: ‘Pmf’
         return get_function_ptr(pmf);
                                 ^~~
                                 Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘const void* sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>::get_object() const:
/usr/local/include/sigslot/signal.hpp:972:31: error: ‘ptr’ was not declared in this scope
         return get_object_ptr(ptr);
                               ^~~
/usr/local/include/sigslot/signal.hpp:972:31: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot_pmf_extended<Pmf, Ptr, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:977:23: error: ‘pmf’ was not declared in this scope
         return typeid(pmf);
                       ^~~
/usr/local/include/sigslot/signal.hpp:977:23: note: suggested alternative: ‘Pmf’
         return typeid(pmf);
                       ^~~
                       Pmf
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:1032:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Func> func;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1033:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<WeakPtr> ptr;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot_tracked<Func, WeakPtr, Args>::slot_tracked(sigslot::detail::cleanable&, F&&, P&&, sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:997:11: error: class ‘sigslot::detail::slot_tracked<Func, WeakPtr, Args>’ does not have any field named ‘func’
         , func{std::forward<F>(f)}
           ^~~~
/usr/local/include/sigslot/signal.hpp:998:11: error: class ‘sigslot::detail::slot_tracked<Func, WeakPtr, Args>’ does not have any field named ‘ptr’
         , ptr{std::forward<P>(p)}
           ^~~
/usr/local/include/sigslot/signal.hpp: In member function ‘bool sigslot::detail::slot_tracked<Func, WeakPtr, Args>::connected() const:
/usr/local/include/sigslot/signal.hpp:1002:17: error: ‘ptr’ was not declared in this scope
         return !ptr.expired() && slot_state::connected();
                 ^~~
/usr/local/include/sigslot/signal.hpp:1002:17: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::detail::slot_tracked<Func, WeakPtr, Args>::call_slot(Args ...):
/usr/local/include/sigslot/signal.hpp:1007:19: error: ‘ptr’ was not declared in this scope
         auto sp = ptr.lock();
                   ^~~
/usr/local/include/sigslot/signal.hpp:1007:19: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot_tracked<Func, WeakPtr, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:1018:33: error: ‘func’ was not declared in this scope
         return get_function_ptr(func);
                                 ^~~~
/usr/local/include/sigslot/signal.hpp:1018:33: note: suggested alternative: ‘Func’
         return get_function_ptr(func);
                                 ^~~~
                                 Func
/usr/local/include/sigslot/signal.hpp: In member function ‘const void* sigslot::detail::slot_tracked<Func, WeakPtr, Args>::get_object() const:
/usr/local/include/sigslot/signal.hpp:1022:31: error: ‘ptr’ was not declared in this scope
         return get_object_ptr(ptr);
                               ^~~
/usr/local/include/sigslot/signal.hpp:1022:31: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot_tracked<Func, WeakPtr, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:1027:23: error: ‘func’ was not declared in this scope
         return typeid(func);
                       ^~~~
/usr/local/include/sigslot/signal.hpp:1027:23: note: suggested alternative: ‘Func’
         return typeid(func);
                       ^~~~
                       Func
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:1082:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<Pmf> pmf;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1083:10: error:decay_t’ in namespace ‘std’ does not name a template type
     std::decay_t<WeakPtr> ptr;
          ^~~~~~~
/usr/local/include/sigslot/signal.hpp: In constructor ‘constexpr sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::slot_pmf_tracked(sigslot::detail::cleanable&, F&&, P&&, sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:1047:11: error: class ‘sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>’ does not have any field named ‘pmf’
         , pmf{std::forward<F>(f)}
           ^~~
/usr/local/include/sigslot/signal.hpp:1048:11: error: class ‘sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>’ does not have any field named ‘ptr’
         , ptr{std::forward<P>(p)}
           ^~~
/usr/local/include/sigslot/signal.hpp: In member function ‘bool sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::connected() const:
/usr/local/include/sigslot/signal.hpp:1052:17: error: ‘ptr’ was not declared in this scope
         return !ptr.expired() && slot_state::connected();
                 ^~~
/usr/local/include/sigslot/signal.hpp:1052:17: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::call_slot(Args ...):
/usr/local/include/sigslot/signal.hpp:1057:19: error: ‘ptr’ was not declared in this scope
         auto sp = ptr.lock();
                   ^~~
/usr/local/include/sigslot/signal.hpp:1057:19: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:1063:21: error: ‘pmf’ was not declared in this scope
             ((*sp).*pmf)(args...);
                     ^~~
/usr/local/include/sigslot/signal.hpp:1063:21: note: suggested alternative: ‘Pmf’
             ((*sp).*pmf)(args...);
                     ^~~
                     Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::detail::func_ptr sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::get_callable() const:
/usr/local/include/sigslot/signal.hpp:1068:33: error: ‘pmf’ was not declared in this scope
         return get_function_ptr(pmf);
                                 ^~~
/usr/local/include/sigslot/signal.hpp:1068:33: note: suggested alternative: ‘Pmf’
         return get_function_ptr(pmf);
                                 ^~~
                                 Pmf
/usr/local/include/sigslot/signal.hpp: In member function ‘const void* sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::get_object() const:
/usr/local/include/sigslot/signal.hpp:1072:31: error: ‘ptr’ was not declared in this scope
         return get_object_ptr(ptr);
                               ^~~
/usr/local/include/sigslot/signal.hpp:1072:31: note: suggested alternatives:
In file included from /usr/local/include/sophus/common.hpp:36:0,
                 from /usr/local/include/sophus/types.hpp:8,
                 from /usr/local/include/sophus/rotation_matrix.hpp:10,
                 from /usr/local/include/sophus/so3.hpp:7,
                 from /usr/local/include/sophus/se3.hpp:7,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:2:
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
                            ^~~
/usr/local/include/fmt/format.h:2687:28: note:   ‘fmt::v8::ptr’
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp: In member function ‘const std::type_info& sigslot::detail::slot_pmf_tracked<Pmf, WeakPtr, Args>::get_callable_type() const:
/usr/local/include/sigslot/signal.hpp:1077:23: error: ‘pmf’ was not declared in this scope
         return typeid(pmf);
                       ^~~
/usr/local/include/sigslot/signal.hpp:1077:23: note: suggested alternative: ‘Pmf’
         return typeid(pmf);
                       ^~~
                       Pmf
/usr/local/include/sigslot/signal.hpp: At global scope:
/usr/local/include/sigslot/signal.hpp:1115:27: error:conditional_t’ in namespace ‘std’ does not name a template type
     using cow_type = std::conditional_t<is_thread_safe<L>::value,
                           ^~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1119:32: error:conditional_t’ in namespace ‘std’ does not name a template type
     using cow_copy_type = std::conditional_t<is_thread_safe<L>::value,
                                ^~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1201:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<arg_list, Callable>, connection>
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1221:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<ext_arg_list, Callable>, connection>
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1241:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<arg_list, Pmf, Ptr> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1261:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<arg_list, Pmf, Ptr> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1281:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<ext_arg_list, Pmf, Ptr> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1310:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<!trait::is_callable_v<arg_list, Pmf> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1340:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<trait::is_callable_v<arg_list, Callable> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1376:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<(trait::is_callable_v<arg_list, Callable> ||
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1399:10: error:enable_if_t’ in namespace ‘std’ does not name a template type
     std::enable_if_t<!trait::is_callable_v<arg_list, Obj> &&
          ^~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1522:12: error: ‘cow_copy_type’ does not name a type; did you mean ‘lock_type’?
     inline cow_copy_type<list_type, Lockable> slots_reference() {
            ^~~~~~~~~~~~~
            lock_type
/usr/local/include/sigslot/signal.hpp:1529:36: error: ‘make_slot’ function uses ‘auto’ type specifier without trailing return type
     inline auto make_slot(A && ...a) {
                                    ^
/usr/local/include/sigslot/signal.hpp:1529:36: note: deduced return type only available with -std=c++14 or -std=gnu++14
/usr/local/include/sigslot/signal.hpp:1589:5: error: ‘cow_type’ does not name a type; did you mean ‘lock_type’?
     cow_type<list_type, Lockable> m_slots;
     ^~~~~~~~
     lock_type
/usr/local/include/sigslot/signal.hpp: In constructor ‘sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::signal_base(sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >&&):
/usr/local/include/sigslot/signal.hpp:1146:14: error: ‘m_slots’ was not declared in this scope
         swap(m_slots, o.m_slots);
              ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1146:14: note: suggested alternative: ‘m_block’
         swap(m_slots, o.m_slots);
              ^~~~~~~
              m_block
/usr/local/include/sigslot/signal.hpp: In member function ‘sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >& sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::operator=(sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >&&):
/usr/local/include/sigslot/signal.hpp:1155:14: error: ‘m_slots’ was not declared in this scope
         swap(m_slots, o.m_slots);
              ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1155:14: note: suggested alternative: ‘m_block’
         swap(m_slots, o.m_slots);
              ^~~~~~~
              m_block
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::operator()(U&& ...):
/usr/local/include/sigslot/signal.hpp:1180:9: error: ‘cow_copy_type’ was not declared in this scope
         cow_copy_type<list_type, Lockable> ref = slots_reference();
         ^~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1180:9: note: suggested alternative: ‘lock_type’
         cow_copy_type<list_type, Lockable> ref = slots_reference();
         ^~~~~~~~~~~~~
         lock_type
/usr/local/include/sigslot/signal.hpp:1180:32: error: expected primary-expression before ‘,’ token
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                ^
/usr/local/include/sigslot/signal.hpp:1180:42: error: expected primary-expression before ‘>’ token
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                          ^
/usr/local/include/sigslot/signal.hpp:1180:44: error: ‘ref’ was not declared in this scope
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                            ^~~
/usr/local/include/sigslot/signal.hpp:1180:44: note: suggested alternative:
In file included from /usr/include/c++/7/bits/std_function.h:44:0,
                 from /usr/include/c++/7/functional:58,
                 from /usr/local/include/opencv2/core/utility.hpp:60,
                 from /usr/local/include/opencv2/core.hpp:3282,
                 from /usr/local/include/opencv2/opencv.hpp:52,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:1:
/usr/include/c++/7/bits/refwrap.h:382:5: note:   ‘std::ref’
     ref(reference_wrapper<_Tp> __t) noexcept
     ^~~
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:1180:50: error: there are no arguments to ‘slots_reference’ that depend on a template parameter, so a declaration of ‘slots_reference’ must be available [-fpermissive]
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                                  ^~~~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1180:50: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
/usr/local/include/sigslot/signal.hpp: In member function ‘size_t sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::disconnect(const Callable&, const Obj&):
/usr/local/include/sigslot/signal.hpp:1423:41: error: use of ‘auto’ in lambda parameter declaration only available with -std=c++14 or -std=gnu++14
         return disconnect_if([&] (const auto &s) {
                                         ^~~~
/usr/local/include/sigslot/signal.hpp: In lambda function:
/usr/local/include/sigslot/signal.hpp:1424:21: error: base operand of ‘->’ is not a pointer
             return s->has_object(obj) && s->has_callable(c);
                     ^~
/usr/local/include/sigslot/signal.hpp:1424:43: error: base operand of ‘->’ is not a pointer
             return s->has_object(obj) && s->has_callable(c);
                                           ^~
/usr/local/include/sigslot/signal.hpp: In member function ‘size_t sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::disconnect(sigslot::group_id):
/usr/local/include/sigslot/signal.hpp:1439:46: error: ‘m_slots’ was not declared in this scope
         for (auto &group : detail::cow_write(m_slots)) {
                                              ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1439:46: note: suggested alternative: ‘m_block’
         for (auto &group : detail::cow_write(m_slots)) {
                                              ^~~~~~~
                                              m_block
/usr/local/include/sigslot/signal.hpp: In member function ‘size_t sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::slot_count():
/usr/local/include/sigslot/signal.hpp:1486:9: error: ‘cow_copy_type’ was not declared in this scope
         cow_copy_type<list_type, Lockable> ref = slots_reference();
         ^~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp:1486:9: note: suggested alternative: ‘lock_type’
         cow_copy_type<list_type, Lockable> ref = slots_reference();
         ^~~~~~~~~~~~~
         lock_type
/usr/local/include/sigslot/signal.hpp:1486:32: error: expected primary-expression before ‘,’ token
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                ^
/usr/local/include/sigslot/signal.hpp:1486:42: error: expected primary-expression before ‘>’ token
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                          ^
/usr/local/include/sigslot/signal.hpp:1486:44: error: ‘ref’ was not declared in this scope
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                            ^~~
/usr/local/include/sigslot/signal.hpp:1486:44: note: suggested alternative:
In file included from /usr/include/c++/7/bits/std_function.h:44:0,
                 from /usr/include/c++/7/functional:58,
                 from /usr/local/include/opencv2/core/utility.hpp:60,
                 from /usr/local/include/opencv2/core.hpp:3282,
                 from /usr/local/include/opencv2/opencv.hpp:52,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:1:
/usr/include/c++/7/bits/refwrap.h:382:5: note:   ‘std::ref’
     ref(reference_wrapper<_Tp> __t) noexcept
     ^~~
In file included from /usr/local/include/pangolin/utils/signal_slot.h:3:0,
                 from /usr/local/include/pangolin/windowing/window.h:35,
                 from /usr/local/include/pangolin/display/display.h:34,
                 from /usr/local/include/pangolin/pangolin.h:38,
                 from /home/lmf37/桌面/slambook2/ch8/direct_method.cpp:4:
/usr/local/include/sigslot/signal.hpp:1486:50: error: there are no arguments to ‘slots_reference’ that depend on a template parameter, so a declaration of ‘slots_reference’ must be available [-fpermissive]
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                                  ^~~~~~~~~~~~~~~
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::clean(sigslot::detail::slot_state*):
/usr/local/include/sigslot/signal.hpp:1504:46: error: ‘m_slots’ was not declared in this scope
         for (auto &group : detail::cow_write(m_slots)) {
                                              ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1504:46: note: suggested alternative: ‘m_block’
         for (auto &group : detail::cow_write(m_slots)) {
                                              ^~~~~~~
                                              m_block
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::add_slot(sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::slot_ptr&&):
/usr/local/include/sigslot/signal.hpp:1538:42: error: ‘m_slots’ was not declared in this scope
         auto &groups = detail::cow_write(m_slots);
                                          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1538:42: note: suggested alternative: ‘m_block’
         auto &groups = detail::cow_write(m_slots);
                                          ^~~~~~~
                                          m_block
/usr/local/include/sigslot/signal.hpp: In member function ‘size_t sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::disconnect_if(Cond&&):
/usr/local/include/sigslot/signal.hpp:1560:42: error: ‘m_slots’ was not declared in this scope
         auto &groups = detail::cow_write(m_slots);
                                          ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1560:42: note: suggested alternative: ‘m_block’
         auto &groups = detail::cow_write(m_slots);
                                          ^~~~~~~
                                          m_block
/usr/local/include/sigslot/signal.hpp:1564:28: error: range-based ‘for’ expression of type ‘auto’ has incomplete type
         for (auto &group : groups) {
                            ^~~~~~
/usr/local/include/sigslot/signal.hpp: In member function ‘void sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::clear():
/usr/local/include/sigslot/signal.hpp:1584:27: error: ‘m_slots’ was not declared in this scope
         detail::cow_write(m_slots).clear();
                           ^~~~~~~
/usr/local/include/sigslot/signal.hpp:1584:27: note: suggested alternative: ‘m_block’
         detail::cow_write(m_slots).clear();
                           ^~~~~~~
                           m_block
/usr/local/include/sigslot/signal.hpp: In instantiation of ‘void sigslot::signal_base< <template-parameter-1-1>, <template-parameter-1-2> >::operator()(U&& ...) [with U = {pangolin::VarState::Event}; Lockable = std::mutex; T = {pangolin::VarState::Event}]:
/usr/local/include/pangolin/var/varstate.h:264:23:   required from ‘std::map<std::__cxx11::basic_string<char>, std::shared_ptr<pangolin::VarValueGeneric> >::iterator pangolin::VarState::AddUpgradedVar(const std::shared_ptr<pangolin::VarValue<T> >&, const iterator&, bool) [with T = bool; std::map<std::__cxx11::basic_string<char>, std::shared_ptr<pangolin::VarValueGeneric> >::iterator = std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, std::shared_ptr<pangolin::VarValueGeneric> > >]/usr/local/include/pangolin/var/varstate.h:205:13:   required from ‘std::shared_ptr<pangolin::VarValueGeneric> pangolin::VarState::GetOrCreateVar(const T&, const pangolin::VarMeta&) [with T = bool]/usr/local/include/pangolin/var/var.h:83:50:   required from ‘pangolin::Var<T>::Var(const T&, const pangolin::VarMeta&) [with T = bool]/usr/local/include/pangolin/var/var.h:88:35:   required from ‘pangolin::Var<T>::Var(const string&, const T&) [with T = bool; std::__cxx11::string = std::__cxx11::basic_string<char>]/usr/local/include/pangolin/display/widgets.h:153:50:   required from here
/usr/local/include/sigslot/signal.hpp:1180:65: error: ‘slots_reference’ was not declared in this scope
         cow_copy_type<list_type, Lockable> ref = slots_reference();
                                                  ~~~~~~~~~~~~~~~^~
CMakeFiles/direct_method.dir/build.make:75: recipe for target 'CMakeFiles/direct_method.dir/direct_method.cpp.o' failed
make[2]: *** [CMakeFiles/direct_method.dir/direct_method.cpp.o] Error 1
CMakeFiles/Makefile2:110: recipe for target 'CMakeFiles/direct_method.dir/all' failed
make[1]: *** [CMakeFiles/direct_method.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2

代码300行,报错500行,额鹅鹅鹅 😦,只能一个个调了,搜了一下大部分都是库链接,和库版本问题,不过秉持能不改就不修,能小改绝不大改原则,一一踏平bug.

bug 虽然多,经过尝试发现一行可以解决
set(CMAKE_CXX_FLAGS "-std=c++11 ${SSE_FLAGS} -g -O3 -march=native")
修改为set(CMAKE_CXX_FLAGS "-std=c++14 -O2 ${SSE_FLAGS} -msse4")即可.
兴奋耶!😃

参考博客
  1. SLAM十四讲-ch8-直接法(包含手写单层、多层光流跟踪和直接法代码的注释)
  2. 视觉slam14讲——第8讲 视觉里程计2

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/866925.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-12
下一篇 2022-05-12

发表评论

登录后才能评论

评论列表(0条)

保存