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代码解析(插补运算,圆弧等分)

 

 

原文地址:https://www.cnblogs.com/tangyuanjie/p/14304615.html