pangolin学习笔记1

主要针对:SLAM可视化绘图库——Pangolin教程(一)_yuntian_li的博客-CSDN博客_slam可视化绘图库的讲解进行学习一、基础操作基本步骤:
创建窗口->启用深度测试->创建相机视图(包括相机参数和相机位姿)->创建交互视图->清空颜色和缓存->绘制图案->推进窗口事件

#include <pangolin/pangolin.h>
int main( int /*argc*/, char** /*argv*/ )
{
    pangolin::CreateWindowAndBind("Main",640,480);    //创建一个窗口
    glEnable(GL_DEPTH_TEST);    // 启用深度测试

    pangolin::OpenGlRenderState s_cam(    // 创建一个观察相机视图
        pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100),
        pangolin::ModelViewLookAt(-5,5,-5, 0,0,0, pangolin::AxisY)
    );

    pangolin::Handler3D handler(s_cam);   //    创建交互视图
    pangolin::View& d_cam = pangolin::CreateDisplay()
            .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
            .SetHandler(&handler);
    while( !pangolin::ShouldQuit() )
    {
        // 清空颜色和深度缓存,如果不清空就会保留上一帧的图形
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        d_cam.Activate(s_cam);
        // 绘制图案
        // 运行帧推进窗口事件.
        pangolin::FinishFrame();
    }
    return 0;
}

1、创建一个窗口
pangolin::CreateWindowAndBind("Main",640,480);//名称为Main的窗口,大小为640*480
2、启用深度测试
glEnable(GL_DEPTH_TEST);
3、创建一个观察相机视图
ProjectMatrix(int h, int w, int fu, int fv, int cu, int cv, int znear, int zfar) 
参数依次为观察相机的图像高度、宽度、4个内参以及最近和最远视距
ModelViewLookAt(double x, double y, double z,double lx, double ly, double lz, AxisDirection Up)
参数依次为相机所在的位置,以及相机所看的视点位置(一般可设置在原点) 后续能改,不重要。
4、创建交互视图
pangolin::Handler3D handler(s_cam);   //    创建交互视图
pangolin::View& d_cam = pangolin::CreateDisplay()
        .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
        .SetHandler(&handler);
用于显示相机所拍摄到的内容.SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f) 前四个参数表示视图在视窗中的位置(这么写是在屏幕中央)
5、清空颜色和深度缓存,如果不清空就会保留上一帧的图形
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
d_cam.Activate(s_cam);//激活相机显示(打开相机镜头盖子?)
6、推进事件进行
pangolin::FinishFrame();

额外:
画线: (给两点,自动连线)

glLineWidth(3);//线宽
glBegin (GL_LINES);//开始画线
glColor3f ( 0.8f,0.f,0.f );//颜色
glVertex3f( -1,-1,-1 );//线起点         glVertex3f( 0,-1,-1 );//线终点
glEnd();//结束画线

画正方形:

pangolin::glDrawColouredCube(-0.5,0.5);//参数决定位置与边长,正方体中心在二者均值中间(x=y=z),二者之差为边长

二、带控件的窗口
创建窗口->启用深度测试->创建相机视图->分割视窗->创建交互视图->创建控制面板->创建控制面板的控件选项->->清空颜色和缓存->绘制图案->推进窗口事件
创建控制面板:

pangolin::CreatePanel("ui").SetBounds(0.0, 1.0, 0.0, pangolin::Attach::Pix(UI_WIDTH));
pangolin::CreatePanel(<控制面板名>).SetBounds(<面板位置(0~1相对位置,pangolin::Attach::Pix()像素绝对位置)>);

控件对象:
Pangolin将所有“控件”视为一个pangolin::Var对象,该对象是一个模板类,我们可以向其中传递自定义的类型模板,亦可使用Pangolin预先定义的类模板。
常用的pangolin::Var对象如下:

1、pangolin::Var<bool> A_Button("ui.a_button", false, false); //按钮
pangolin::Var<bool> <对象名称>(<%{控制面板名}.标签名(用于显示)>, <初始值>, <true:选框,false:按钮>); 
2、pangolin::Var<double> Double_Slider("ui.a_slider", 3, 0, 5); //double滑条
pangolin::Var<int/double/float> <对象名称>(<%{控制面板名}.标签名(用于显示)>, <初始值>, <最小值(默认0)>, <最大值(默认1)>, <是否对数显示:true or false(默认false)>);
3、pangolin::Var<std::string> A_string("ui.a_string", "Hello");//显示
pangolin::Var<std::string> <对象名称>(<%{控制面板名}.标签名(用于显示)>,<显示内容>) //不能互动,纯粹是显示
4、pangolin::Var<std::function<void()>> reset("ui.Reset", SampleMethod);// 类似按钮控件,实现一些简单的功能(参数传输很麻烦)
pangolin::Var<std::function<void()>> <对象名称>(<%{控制面板名}.标签名(用于显示)>, <函数名>)
应用的函数一般是:void <函数名>() 一般都是简单的操作,可能用于快捷键比较多.

控件回调函数:

注:需要在循环while(!pangolin::ShouldQuit()){}中写!
1、按钮
if(pangolin::Pushed(A_Button))
    std::cout << "Push button A." << std::endl;
if(pangolin::Pushed(<对象名称>))
    <操作>;
2、选框
if(<对象名称>)
    Int_Slider = Double_Slider;
if(A_Checkbox)
    <操作>;
绑定快捷键:
1、调节值
pangolin::RegisterKeyPressCallback(pangolin::PANGO_CTRL + 'b', pangolin::SetVarFunctor<double>("ui.a_slider", 3.5));
pangolin::RegisterKeyPressCallback(<按键>, <赋值>);

2、执行函数
pangolin::RegisterKeyPressCallback(pangolin::PANGO_CTRL + 'r', SampleMethod);
pangolin::RegisterKeyPressCallback(<按键>, <std::function<void(void)> 函数>);

其他指令:
pangolin::SaveWindowOnRender("window");//保存整个界面,保存名称为window.jpg
d_cam.SaveOnRender("cube");//保存整个交互视图,保存名称为cube.jpg
pangolin::DisplayBase().RecordOnRender("ffmpeg:[fps=50,bps=8388608,unique_filename]//screencap.avi");//保存视频

三、多视图与图片显示
…->创建相机视图->创建多视图->创建容器读取图像->…->读取图像->显示图像
创建多视图:
pangolin的多视图是通过叠加来实现,SetBounds()表示边界,SetHandler()表示交互视图,SetLock()表示锁定视图,要注意的是pangolin坐标原点在左下角!!!!!
pangolin::View& <视图名> = pangolin::Display(<显示名>).SetBounds(<边界 底, 顶, 左, 右>, <分辨率>).SetHandler(new pangolin::Handler3D(<相机视图名>)); 
分辨率为正,图片会通过裁剪来满足分辨率.分辨率为负,则会将图片拉伸来满足分辨率
.SetLock(pangolin::LockLeft, pangolin::LockTop);锁定视图的方位

创建用来读取图像的容器:
pangolin::GlTexture imgTexture1(752, 480, GL_RGB, false, 0, GL_BGR, GL_UNSIGNED_BYTE);//创建glTexture容器用于读取图像
pangolin::GlTexture imgTexture1(<图像宽度>, <图像高度>, <pangolin图像格式>, <线性采样?>, <边界大小>, <gl图像存储格式>, <gl数据格式>);
pangolin图像格式一般为GL_RGB;线性采样不知道具体指什么;gl图像存储格式因为在opencv中图像为BGR,数据格式为uint8

pangolin::View& d_cam = pangolin::Display("cam")
    .SetBounds(0., 1., 0., 1., -752/480.)
    .SetHandler(new pangolin::Handler3D(s_cam));

pangolin::View& cv_img_1 = pangolin::Display("image_1")//752,480 是视窗尺寸
    .SetBounds(2/3.0f, 1.0f, 0., 1/3.0f, 752/480.)
    .SetLock(pangolin::LockLeft, pangolin::LockTop);

pangolin::View& cv_img_2 = pangolin::Display("image_2")
    .SetBounds(0., 1/3.0f, 2/3.0f, 1.0, 752/480.)
    .SetLock(pangolin::LockRight, pangolin::LockBottom);

读入图片
cv::Mat img1 = cv::imread("../build/img1.png");
imgTexture1.Upload(img1.data, GL_BGR, GL_UNSIGNED_BYTE);//加载图片

显示图像
cv_img_1.Activate();
glColor3f(1.0f, 1.0f, 1.0f); // 设置默认背景色,对于显示图片来说,不设置也没关系
imgTexture1.RenderToViewportFlipY(); // 需要反转Y轴,否则输出是倒着的(主要是gl和pangolin的坐标系y轴上相反)

四、绘制数据曲线
创建窗口->创建数据存储对象->设置图例->创建数据视图->创建数据->推进窗口事件
1、创建存储数据的log对象
pangolin::DataLog log;  
pangolin::DataLog <对象名>; 
2、设置数据图例
std::vector<std::string> labels;
labels.push_back(std::string("sin(t)"));
labels.push_back(std::string("cos(t)"));
labels.push_back(std::string("sin(t)+cos(t)"));
log.SetLabels(labels);

std::vector<std::string> <标签变量>;
<标签变量>.push_back(<标签>)
<DataLog 对象名>.SetLabels(<标签变量>);

3、创建数据视图
pangolin::Plotter plotter(&log,0.0f,4.0f*(float)M_PI/tinc,-4.0f,4.0f,(float)M_PI/(4.0f*tinc),0.5f);
plotter.SetBounds(0.0, 1.0, 0.0, 1.0);
plotter.Track("$i");//坐标轴自动滚动

pangolin::Plotter plotter(&<DataLog 对象名>,<左边界>,<右边界>,<下边界>,<上边界>,<x轴刻度>,<y轴刻度>);

4、创建数据
log.Log(sin(t),cos(t),sin(t)+cos(t)) //数据个数要和图例对应
<DataLog 对象名>.log(<数据>)

补充:如何对区域进行上色:
plotter.AddMarker(pangolin::Marker::Vertical, 50*M_PI, pangolin::Marker::LessThan, pangolin::Colour::Blue().WithAlpha(0.2f) );//将x<50*M_PI的区域上色-蓝色,透明度0.2
plotter.AddMarker(pangolin::Marker::Horizontal, 3, pangolin::Marker::GreaterThan, pangolin::Colour::Red().WithAlpha(0.2f) );//将y>3的区域上色-红色,透明度0.2
plotter.AddMarker(pangolin::Marker::Horizontal, 3, pangolin::Marker::Equal, pangolin::Colour::Green().WithAlpha(0.2f) );//将y=3的线上色-绿色,透明度0.2

pangolin::DisplayBase().AddDisplay(plotter);//应用到显示视图中

plotter.AddMarker(<区域方向>, <值>, <绘图方向>, <颜色>);
<区域方向>分为纵向pangolin::Marker::Horizontal;横向:pangolin::Marker::Vertical
<绘图方向>分为小于pangolin::Marker::LessThan;大于pangolin::Marker::GreaterThan;等于pangolin::Marker::Equal
<颜色>pangolin::Colour(r,g,b,a)     红,绿,蓝,透明度

五、绘制相机位姿

#include <pangolin/pangolin.h>
#include <stdio.h>
using namespace std;

int main(int argc, char** argv){
    // 读取数据集与数据集检测
    FILE* fp_gt = fopen("/home/smz/dataset/MH_01_easy/mav0/state_groundtruth_estimate0/data.csv", "r");
    if(fp_gt == nullptr){
        cout << "failed to open file !\n";
        return -1;
    }
    // 跳过第一行 ,第一行是表头
    char fl_buf[1024];
    fgets(fl_buf, sizeof(fl_buf), fp_gt);
    // 创建数据寄存器,这个和data.csv数据格式相关,
    ulong time_stamp(0);
    double px(0.), py(0.), pz(0.);
    double qw(0.), qx(0.), qy(0.), qz(0.);
    double vx(0.), vy(0.), vz(0.);
    double bwx(0.), bwy(0.), bwz(0.), bax(0.), bay(0.), baz(0.);
    vector<Eigen::Vector3d> traj;//用于保存位姿,位姿点就是每帧绘图的参考点
    // 初始化视窗并开启深度测试
    pangolin::CreateWindowAndBind("camera_pose", 752 * 2, 480 * 2);
    glEnable(GL_DEPTH_TEST);
    // 创建相机视图
    pangolin::OpenGlRenderState s_cam_ = pangolin::OpenGlRenderState(
        pangolin::ProjectionMatrix(752 * 2, 480 * 2, 420, 420, 320, 240, 0.1, 1000),
        pangolin::ModelViewLookAt(5, -3, 5, 0, 0, 0, pangolin::AxisZ)
    );
    // 创建交互视图
    pangolin::View& d_cam_ = pangolin::CreateDisplay()
        .SetBounds(0., 1., 0., 1., -752/ 480.)
        .SetHandler(new pangolin::Handler3D(s_cam_));
    
    while (!feof(fp_gt))
    {
        // 清空颜色和深度缓存,打开相机
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        d_cam_.Activate(s_cam_);
        // 读取数据
        fscanf(fp_gt, "%lu,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
            &time_stamp, &px, &py, &pz,
            &qw, &qx, &qy, &qz,
            &vx, &vy, &vz,
            &bwx, &bwy, &bwz,
            &bax, &bay, &baz);

        Eigen::Quaterniond quat(qw, qx, qy, qz); //q存储四元数
        Eigen::Vector3d pos(px, py, pz); // 存储位姿
        traj.push_back(pos); //保存到vector容器中

          // -------- 绘制坐标系 -------- //
        glLineWidth(3);
        glBegin ( GL_LINES );
        glColor3f( 1.0f,0.0f,0.0f );
        glVertex3f( 0,0,0 );      glVertex3f( 1,0,0 );
        glColor3f( 0.0f,1.0f,0.0f );
        glVertex3f( 0,0,0 );      glVertex3f( 0,1,0 );
        glColor3f( 0.0f,0.0f,1.0f );
        glVertex3f( 0,0,0 );      glVertex3f( 0,0,1 );
        glEnd();
        // -------- 绘制随位姿变化的相机模型 -------- //
        // 构建位姿变换矩阵,pangolin中为列主序
        Eigen::Matrix3d R = quat.toRotationMatrix();// 四元数->旋转矩阵

        glPushMatrix();// 告诉pangolin,程序要存入矩阵。  在PopMatrix()之前,出现的所有glVertex3*坐标都要乘以这个矩阵。
        std::vector<GLdouble> Twc = {R(0, 0), R(1,0), R(2, 0), 0.,
                                R(0, 1), R(1, 1), R(2, 1), 0.,
                                R(0, 2), R(1, 2), R(2, 2), 0.,
                                pos.x(), pos.y(), pos.z(), 1.};//需要存入的矩阵,即位姿矩阵
        glMultMatrixd(Twc.data());// 存入位姿矩阵
       // 绘制相机轮廓线
        const float w = 0.2;
        const float h = w * 0.75;
        const float z = w * 0.6;

        glLineWidth(2); //线宽
        glBegin(GL_LINES);//开始绘制直线
        glColor3f(0.0f,1.0f,1.0f); //线的颜色
        glVertex3f(0,0,0);        glVertex3f(w,h,z);
        glVertex3f(0,0,0);        glVertex3f(w,-h,z);
        glVertex3f(0,0,0);        glVertex3f(-w,-h,z);
        glVertex3f(0,0,0);        glVertex3f(-w,h,z);
        glVertex3f(w,h,z);        glVertex3f(w,-h,z);
        glVertex3f(-w,h,z);        glVertex3f(-w,-h,z);
        glVertex3f(-w,h,z);        glVertex3f(w,h,z);
        glVertex3f(-w,-h,z);    glVertex3f(w,-h,z);
        glEnd(); //停止绘制
        glPopMatrix(); // 退出模式
        // -------- 绘制相机轨迹 --------//
        glLineWidth(2);
        glBegin(GL_LINES);
        glColor3f(0.f, 1.f, 0.f);
        for(size_t i=0; i<traj.size() - 1; i++){
            glVertex3d(traj[i].x(), traj[i].y(), traj[i].z());
            glVertex3d(traj[i+1].x(), traj[i+1].y(), traj[i+1].z());
        }// 由于每次循环会擦掉所有信息,因此是从起点开始绘制轨迹,直到绘制到当前帧
        glEnd();
    
        pangolin::FinishFrame();// 绘制更新的帧
        
        if(pangolin::ShouldQuit())//关掉窗口,则退出程序
            break;
    }

    return 0;
}

目前存在问题:1、Framebuffer with requested attributes not available. Using available framebuffer. You may see visual artifacts  

不影响pangolin的使用,并且查了资料解决不了这个问题,先这么放着吧,以后换一台装了显卡驱动的再试试。

后续:看一下pangolin其他的参考,把博主的task7做了它

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值