• robot-program-offline-master(五轴机器人离线仿真)


    删除代码项目里面的ui开头的文件重新编译就不会出错;

     

    模型

    左边导航

     

     

    Dockwidget

    点击联调按钮加载analysiswidget

    绘图使用customplot

    STLView 解析STL文件 使用多线程解析

    顶点

    //三角形片类,主要由三个顶点坐标和一个法向量组成

    class MyTriangle

    {

    public:

    MyPoint normal,vertex1,vertex2,vertex3;

    };

     

     

    //解析STL文件生成triangleVector数组

    bool STLView::readSTL(const QString &fname){

    QFile file(fname);

    if ( file.open(QFile::ReadOnly | QFile::Text)) //仅读和文字

    {

    QTextStream in( &file );

    MyTriangle triangle;

    QString line;

    int trianglePartNums = 0;

     

    while ( !in.atEnd() )

    {

    line = in.readLine();

    QVector<QString> words;

     

    //分割一行,生成words字符串数组返回字符个数

    int num = CommonFun::splitString(line,' ',words);

     

    //解析一行

    for(int i = 0; i < num; i++)

    {

    //集齐4个参数,添加一个三角片

    if(trianglePartNums == 4)

    {

    triangleVector.push_back(triangle);

    trianglePartNums = 0;

    }

    if(words[i] == "normal")

    {

    triangle.normal.x = words[i+1].toDouble();

    triangle.normal.y = words[i+2].toDouble();

    triangle.normal.z = words[i+3].toDouble();

    trianglePartNums++;

    break;

    }

    if(words[i] == "vertex")

    {

    if(trianglePartNums == 1)

    {

    triangle.vertex1.x = words[i+1].toDouble();

    triangle.vertex1.y = words[i+2].toDouble();

    triangle.vertex1.z = words[i+3].toDouble();

    }

    if(trianglePartNums == 2)

    {

    triangle.vertex2.x = words[i+1].toDouble();

    triangle.vertex2.y = words[i+2].toDouble();

    triangle.vertex2.z = words[i+3].toDouble();

     

    }

    if(trianglePartNums == 3)

    {

    triangle.vertex3.x = words[i+1].toDouble();

    triangle.vertex3.y = words[i+2].toDouble();

    triangle.vertex3.z = words[i+3].toDouble();

    }

    trianglePartNums++;

    break;

    }

    }

    }

    file.close();

    return true;

    }

    else

    {

    qWarning() << fname << ": STL 文件打开失败";

    return false;

    }

     

    }

     

     

    void STLView::run()

    {

    switch(type)

    {

    case LanxunCoordRobot:

    lanxunCoordView[n].readSTL(QString(":/stl/lanxunCoordRobot/%1.STL").arg(n+1));

    break;

    case Lanxun5JointRobot:

    lanxun5JointView[n].readSTL(QString(":/stl/lanxun5JointRobot/%1.STL").arg(n+1));

    break;

    case Lanxun6JointRobot:

    lanxun6JointView[n].readSTL(QString(":/stl/lanxun6JointRobot/%1.STL").arg(n));

    break;

    }

    }

    OpenglWidget 使用gllist生成

     

    void OpenglWidget::makeObject()

    {

    qDebug()<<"makeObject";

    double div = scaleNum;

    int listNum = 0;

     

    //如果没有工件,就少一个显示列表

    /*if(artifacts == NULL){

    listNum = num;

    }else{

    listNum = num + 1;

    }*/

    listNum=(!artifacts)?num:++num;

     

    /**************************************************************************

    OpenGL中用正整数来区分不同的显示列表,为防止重复定义已经存在的显示列表号,

    使用glGenLists函数来自动分配一个没有被使用过的显示列表编号。

    参数指定要分配几个显示列表,返回值是被分配的显示列表中的最小编号,若返回0表示分配失败

    **************************************************************************/

    gllist[0] = glGenLists(listNum);

     

    for(int i = 1; i < listNum; i++){

    gllist[i] = gllist[0] + i;

    }

     

    for(int n = 0; n < num; n++){

    //开始装入:第一个参数标示当前正在操作的显示列表号

    //第二个参数有两种取值GL_COMPILE和GL COMPILE_AND_EXECUTE,

    //前者声明当前显示列表只是装入相应OpenGL语句,不执行;后者表示在装入的同时,执行一遍当前显示列表。

    glNewList(gllist[n], GL_COMPILE );

     

    qglColor(color[n]);

    glBegin(GL_TRIANGLES);

    for(int i = 0; i < (view[n]).triangleVector.size();i++) {

    glNormal3f((view[n]).triangleVector[i].normal.x , (view[n]).triangleVector[i].normal.y ,(view[n]).triangleVector[i].normal.z);

    glTexCoord2f(0, 0);

    glVertex3f((view[n]).triangleVector[i].vertex1.x / div ,(view[n]).triangleVector[i].vertex1.y/ div ,

    (view[n]).triangleVector[i].vertex1.z / div );

    glTexCoord2f( 0.5, 1.0 );

    glVertex3f((view[n]).triangleVector[i].vertex2.x / div ,(view[n]).triangleVector[i].vertex2.y / div,

    (view[n]).triangleVector[i].vertex2.z / div );

    glTexCoord2f( 1.0, 0 );

    glVertex3f((view[n]).triangleVector[i].vertex3.x / div,(view[n]).triangleVector[i].vertex3.y / div ,

    (view[n]).triangleVector[i].vertex3.z / div );

    }

    glEnd();

    glEndList();

    }

     

    if(artifacts){

    //创建显示列表并付给list

    glNewList(gllist[num], GL_COMPILE );

    qglColor(color[num]);

    /**************************************************************************

    * glNormal3f设置当前法线数组

    * glTexCoord2f绘制图形时指定纹理的坐标,为了将纹理正确的映射到四边形上,必须将纹理的四个角映射到四边形的四个角

    * glVertex3f指定3D顶点,一般与glTexCoord2f同时使用,先纹理后顶点

    * glBegin(GL_TRIANGLES)多组独立填充三角形

    **************************************************************************/

    glBegin(GL_TRIANGLES);

     

    for(MyTriangle it: artifacts->triangleVector) {

    glNormal3f(it.normal.x,it.normal.y ,it.normal.z);

    //左下角的纹理与顶点映射

    glTexCoord2f(0, 0);

    glVertex3f(it.vertex1.x / div ,it.vertex1.y/ div ,it.vertex1.z / div );

    //中间点

    glTexCoord2f( 0.5, 1.0 );

    glVertex3f(it.vertex2.x / div ,it.vertex2.y / div,it.vertex2.z / div );

    //右下角

    glTexCoord2f( 1.0, 0 );

    glVertex3f(it.vertex3.x / div,it.vertex3.y / div ,it.vertex3.z / div );

    /*

    for(int i = 0; i < artifacts->triangleVector.size();i++) {

    glNormal3f(artifacts->triangleVector[i].normal.x , artifacts->triangleVector[i].normal.y ,artifacts->triangleVector[i].normal.z);

    //左下角的纹理与顶点映射

    glTexCoord2f(0, 0);

    glVertex3f(artifacts->triangleVector[i].vertex1.x / div ,artifacts->triangleVector[i].vertex1.y/ div ,

    artifacts->triangleVector[i].vertex1.z / div );

    //中间点

    glTexCoord2f( 0.5, 1.0 );

    glVertex3f(artifacts->triangleVector[i].vertex2.x / div ,artifacts->triangleVector[i].vertex2.y / div,

    artifacts->triangleVector[i].vertex2.z / div );

    //右下角

    glTexCoord2f( 1.0, 0 );

    glVertex3f(artifacts->triangleVector[i].vertex3.x / div,artifacts->triangleVector[i].vertex3.y / div ,

    artifacts->triangleVector[i].vertex3.z / div );

    */

    }

     

    glEnd();

    glEndList();

    }

    qDebug()<<"makeObject";

     

    }

     

    OpenglWidget 按键 鼠标 滚轮

    通过改变关节角度重新绘制

    OpenglWidget 文字

    示教窗口

    示教窗口 列表

    列表右键菜单

     

    示教窗口 点动 逆解求关节角度

     

     

    机器人正逆解

     

    SimulationParse

     

    Opengl绘制(使用GLlist)

     

     

     

    数据包解析

     

    //提取数据,数据包结构包括,(指令,指令长度,6个坐标,8关节值)

    int Parser::getValue(const QStringList & list)

    {

    if(list.size() < 2)

    return -1;

    if(list.size() != list[1].toInt())

    return -1;

     

    if(list[0] == "UC"){

    cmd = CoordJoint;

    for(int i=2;i<16;++i){

    if(i<8){

    coord[i-2] = list[i].toDouble();

    }else{

    joint[i-8] = list[i].toDouble();

    }

    }

    // for(int i = 2;i < 8;i++){

    // coord[i - 2] = list[i].toDouble();

    // }

    // for(int i = 8; i < 16; i++){

    // joint[i - 8] = list[i].toDouble();

    // }

    return 0;

    }

     

    if(list[0] == "M7"){

    qDebug() << "开火";

    cmd = OpenFire;

    return 0;

    }

     

    if(list[0] == "M8"){

    qDebug() << "关火";

    cmd = CloseFire;

    return 0;

    }

     

    if(list[0] == "EE"){

    qDebug() << "连接";

    cmd = ConnectCmd;

    return 0;

    }

    else

    return -1;

    }

     

    数据发送(使用套接字)

     

    数据曲线绘制

     

     

    矩阵运算(机器人正逆解)

    各种旋转矩阵

    逆运动学结算由解析解公式代入即可

    G代码解析(插补运算,圆弧等分)

     

     

  • 相关阅读:
    浏览器为何禁止跨域(同源策略)
    viewPager
    How to remove focus without setting focus to another control?
    android ANR
    解决Ubuntu系统中文乱码显示问题
    USB 3.0规范中译本 第6章 物理层
    库&框架-----CDN网络引用总结
    18_如何排错
    17_今日回顾
    16_sql注入的原理及处理
  • 原文地址:https://www.cnblogs.com/tangyuanjie/p/14304615.html
Copyright © 2020-2023  润新知