Qt中动态显示六轴机械臂的STL三维模型

运动仿真

刚好手头有个项目要用Qt做一个六轴机械臂的控制系统,ROS虽然好用,但是RVIZ在Qt里面集成有点困难,就自己用STL模型在Qt里面做了个简单的运动仿真。

STL模型

首先要对机械臂三维模型进行简化,尽量把不需要的孔和复杂结构给直接去掉,这样得到的模型文件会小很多,在处理的时候速度也可以加快,要不然会比较卡顿,尤其在零件比较多的时候。六轴机械臂分成了10个零件,分成了连杆和关节。
再有就是坐标的问题,在导出STL模型的时候一定要设置好导出坐标系,因为要做运动仿真,最好是按照建立的DH坐标系导出,关节与连杆均是,在solidworks中建立好DH坐标系,然后导出STL模型,导出的时候选择好导出坐标系,这样在后面拼接和运动仿真的时候不需要坐标变换,直接通过正运动学公式即可连接起来。导出格式二进制和ASCII格式都可以,ASCII格式相对好操作一点。

openGL显示STL

网上看的显示STL大都用openGL来显示,这方面我也不太会,github大法好
参考链接:github大佬的链接
链接放在这,需要的自取:https://github.com/vladkrylov/STLViewer

虽然我不会写,但是还是可以看懂的,这里简单说一下:

ASCII格式的STL文件

ASCII码格式的STL文件逐行给出三角面片的几何信息,每一行以1个或2个关键字开头。在STL文件中的三角面片的信息单元 facet 是一个带矢量方向的三角面片,STL三维模型就是由一系列这样的三角面片构成。整个STL文件的首行给出了文件路径及文件名。在一个 STL文件中,每一个facet由7 行数据组成,facet normal 是三角面片指向实体外部的法矢量坐标,outer loop 说明随后的3行数据分别是三角面片的3个顶点坐标,3顶点沿指向实体外部的法矢量方向逆时针排列。

STL的ASCII文件形式:

  facet normal -9.941380e-001 -1.081190e-001 -7.282242e-016
    outer loop
      vertex   3.711158e+001 8.168877e+000 2.470000e+001
      vertex   3.800000e+001 0.000000e+000 1.500000e+001
      vertex   3.800000e+001 0.000000e+000 2.470000e+001
    endloop
  endfacet

如图为基座的STL模型
基座STL模型

读取STL文件

这一块实在没啥好说的,虽然我也很想说说,但是确实没啥好说的,直接参考大佬的代码就可以了
代码在头文件里面定义了两个类,一个用来读facet的数据,Model类则是前一个的集合,读取整个文件模型
读取过程也比较简单,从文件开头读,读到关键字,然后去关键字后面找数据,存起来就完事了,存到Model类里面
读文件的过程可以参考Qt读txt文件的过程,从第一行读到最后一行
看吧,确实没啥好说的

openGL中显示STL模型

在STL显示过程中需要先对openGL进行设置,有个坑在这说下:

  1. 光源问题,光源的设置是一个比较麻烦的问题,这个可以参考网上的东西做一个比较好的光源,我在这只用了一个简单的光源,看起来也还可以
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	
	glEnable(GL_COLOR_MATERIAL);
	glLightModeli( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );//设置材料属性,表面漫射反射之类的
	
	static GLfloat lightPosition[4] = { 1.f, 1.0f, 1.f, 0.f };
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
  1. 调节视角:
    //旋转与平移视角
    glMatrixMode(GL_MODELVIEW);
    glScalef(0.15*scale, 0.15*scale, 0.15*scale);//调节视角大小比例
    glRotatef(xRot / 2.0f, 1.0f, 0.0f, 0.0f);//调节视角,与鼠标和键盘回调函数结合使用
    glRotatef(yRot / 2.0f, 0.0f, 1.0f, 0.0f);
    glRotatef(zRot / 2.0f, 0.0f, 0.0f, 1.0f);
    glTranslated(tran_x, tran_y, 0);//平移视角
//回调函数
void AppGLWidget::mousePressEvent(QMouseEvent *event)
{
    mouseLastPos = event->pos();
}

void AppGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - mouseLastPos.x();
    int dy = event->y() - mouseLastPos.y();
    mouseLastPos = event->pos();

    xRot += dy;
    yRot += dx;
    update();
}

void AppGLWidget::wheelEvent(QWheelEvent *event)
{
    scale *= 1 + event->delta() * (s0 - 1);
    update();
}

void AppGLWidget::keyPressEvent(QKeyEvent * event)
{
    switch (event->key()) {
        case Qt::Key_Up:
        tran_y += 10;
        break;
        case Qt::Key_Down:
        tran_y -= 10;
        break;
        case Qt::Key_Left:
        tran_x += 10;
        break;
        case Qt::Key_Right:
        tran_x -= 10;
        break;
        case Qt::Key_R:
        tran_x = 0;tran_y = 0;
        break;
        case Qt::Key_A:
        zRot += 10;
        break;
        case Qt::Key_D:
        zRot -= 10;
        break;

    }

    update();
}
  1. 画图函数如下:
void AppGLWidget::DrawOneModel(Model m, size_t indexR, size_t indexP)
{
    QVector3D n;
    QVector3D v;
    STLTriangle t;
    Matrix3d R;
    Vector3d P;
    Vector3d vert;//顶点

	//根据零件编号选择旋转与平移矩阵进行运动学坐标变换
    if(indexR == 0 && indexP == 0)
    {
        R = Matrix3d::Identity(3, 3);
        P = Vector3d::Zero(3, 1);
    }
    else
    {
        R = kollkine.getRotation(indexR);
        P = kollkine.getPosition(indexP);
    }

    for(int i = 0; i < m.GetNTriangles(); ++i) {
        t = m.GetTriangle(i);
        glBegin(GL_TRIANGLES);
            n = t.GetNormal();
            glNormal3f(n.x(), n.y(), n.z());
            for(size_t j=0; j<3; ++j) {
                v = t.GetVertex(j);
                vert<<v.x(), v.y(), v.z();
                vert = R*vert+P;//对顶点进行旋转平移变换
                glColor4f(0.8f*indexP/10, 0.8f*indexP/10, 0.5f*indexP/10, 0.0f);//上色
                //set the display position
                glVertex3f(vert(0),
                           vert(1),
                           vert(2));
            }
        glEnd();
    }
}

运动学变换

这方面比较简单,学过机器人学应该都能理解,就正运动学进行坐标变换即可,但是需要将运动学的DH坐标系和STL的导出坐标系一致方可。
这里正运动学计算用的是Eigen库,使用方法的链接贴在这:Eigen
在Qt里面使用只需要把Eigen的包下载下来,然后在.pro文件里包含下路径就可以

INCLUDEPATH += F:\qtmodel\STLViewer-master\eigen-3.3.9\Eigen
//计算正运动学
void Kinematics::cal_kinematics(void)
{

    for(size_t i=0; i<7; i++)
    {
        T[i] <<  cos(angle[i]), -sin(angle[i]), 0, a[i],
                 sin(angle[i])*cos(A[i]), cos(angle[i])*cos(A[i]),  -sin(A[i]),  -sin(A[i])*d[i],
                 sin(angle[i])*sin(A[i]), cos(angle[i])*sin(A[i]),  cos(A[i]),   cos(A[i])*d[i],
                 0, 0, 0, 1;
    }

    T[1]=T[0]*T[1];
    T[2]=T[1]*T[2];
    T[3]=T[2]*T[3];
    T[4]=T[3]*T[4];
    T[5]=T[4]*T[5];
    T[6]=T[5]*T[6];

    for(size_t i=0; i<7; i++)
    {
        R[i] << T[i].block(0, 0, 3, 3);
        P[i] << T[i].block(0, 3, 3, 1);
    }
}

两个坑

  1. Eigen在C++类里用静态矩阵的时候会报错,没法运行,奇怪的是在debugger模式下可以运行,可能是什么内存的原因,我也不太懂,解决方法就是在类里加这么一句话:
	public:
	    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  1. 回调函数的调用会有焦点的问题,当时在写键盘回调的时候就一直触发不了,后来在对象中加了这么两句话才解决
    setFocusPolicy(Qt::StrongFocus);
    installEventFilter(this);

最终效果

最终效果大概就这样,这个光实在是很诡异(我实在是懒得调了…),但是毕竟谁会嫌弃自己的孩子丑呢对吧
六轴机械臂显示效果

  • 10
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
### 回答1: 使用MFC和OpenGL来读取并显示STL三维模型需要以下几个步骤: 1. 创建一个新的MFC项目,选择对话框应用程序作为模板。 2. 将OpenGL库文件添加到项目,并进行相关配置,以便在对话框使用OpenGL绘图。 3. 在对话框添加一个静态文本框和一个自定义的OpenGL绘图区域。 4. 创建一个自定义的OpenGL绘图类,用于在绘图区域显示STL模型。在该类,定义一个透视投影矩阵、模型矩阵和视图矩阵,通过OpenGL函数来加载和渲染STL文件的三角形。 5. 在对话框类,添加一个自定义的OpenGL绘图类的成员变量,并在OnInitDialog()函数对其进行初始化。 6. 在OnInitDialog()函数,调用自定义OpenGL绘图类的初始化函数,传入STL模型文件的路径,将模型加载到内存。 7. 在OnPaint()函数,调用自定义OpenGL绘图类的绘制函数,将模型渲染到OpenGL绘图区域。 8. 处理对话框的事件,例如按钮点击事件,调用自定义OpenGL绘图类的相应函数进行操作,如旋转、平移等。 9. 在应用程序类的InitInstance()函数,创建对话框类的对象,并显示对话框。 通过以上步骤,可以实现在MFC应用程序读取并显示STL三维模型。 ### 回答2: MFC是Microsoft Foundation Classes的缩写,是一种用于Windows平台的C++应用程序框架。OpenGL是一种跨平台的图形API,用于开发图形和计算机视觉应用程序。STL(Standard Template Library)是C++的一部分,提供了一组通用的数据结构和算法。 要在MFC应用程序读取并显示STL三维模型,可以按照以下步骤进行操作: 1. 首先,创建一个MFC应用程序项目,并在项目添加OpenGL支持。这可以通过在项目属性启用OpenGL选项来实现。 2. 在MFC应用程序创建一个窗口,用于显示3D模型。这可以通过创建一个自定义的CStatic控件,并在其上绘制OpenGL图形来实现。 3. 接下来,编写代码来读取STL文件的数据。STL文件包含三角形网格的顶点和法线信息。可以使用标准的文件处理函数来读取和解析STL文件的内容,并将其存储在一个适当的数据结构。 4. 通过OpenGL的API函数,将STL模型数据绘制到窗口。可以使用OpenGL的顶点数组和绘制函数来绘制三角形网格的各个面。 5. 最后,将OpenGL绘制的结果显示在MFC窗口。可以通过重载绘图消息处理函数,并在其调用OpenGL的绘制函数来实现。 需要注意的是,由于MFC和OpenGL都是底层的图形库,对于初学者来说,可能需要一定的编程经验和对图形编程的理解。这个过程可能需要一些时间和尝试来完善和调试。 ### 回答3: 在 MFC 使用 OpenGL 来读取并显示 STL 三维模型可以通过以下步骤实现: 1. 添加准备创建 OpenGL 窗口的代码。在 MFC 的窗体类,可以使用 `COpenGLControl` 类或 `CView` 类来实现 OpenGL 窗口。 2. 创建一个函数来读取 STL 三维模型文件。你可以使用 STL 文件解析库,例如 `std::ifstream` 类来读取 STL 文件的内容。 3. 在创建的 OpenGL 窗口,使用 OpenGL 函数来绘制三维模型。你可以使用 `glBegin`、`glEnd` 和 `glVertex3f` 等函数来绘制模型的顶点和三角面片。 4. 在 OpenGL 窗口,将读取到的 STL 三维模型数据传入 OpenGL 函数来进行绘制。你可以使用 `glColor3f` 函数来设置模型的颜色。 5. 在 MFC 的窗体类,实现绘制 OpenGL 窗口的函数。通过重写 `OnDraw` 或 `OnPaint` 函数,调用 OpenGL 窗口的绘制函数。 6. 在 MFC 的窗体类,重写 `OnCreate` 函数来初始化 OpenGL 窗口,调用读取和显示 STL 模型的函数。 7. 在 MFC 的窗体类,为了在窗口显示 OpenGL 窗口,重写 `OnSize` 函数,并调用 OpenGL 窗口的调整大小函数。 通过上述步骤,你可以在 MFC 使用 OpenGL 来读取并显示 STL 三维模型。你可以进一步优化代码,例如添加相机控制、光照设置等来增强模型显示效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值