您的位置:首页 > 编程语言 > C#

C# 姿态显示程序 Opengl SerialPort

2013-01-05 20:58 288 查看
  结合Opengl和SerialPort控件写了这个姿态显示程序,程序较简单,前面有篇简单的四轴上位机模拟显示四轴状态

也可以看看.本程序界面如下:





我这里是用的 51单片机模拟输出 欧拉角,上位机接收参数,并显示姿态.过几天有时间了解

算传感器中的数据传给上位机.软件就不共享了,核心代码共享给大家,对有一定编程基础的人

有参考作用.

核心代码一:绘图部分,绘制显示的这部分

public override void glDraw()
{

// Here's Where We Do All The Drawing
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);                            // Clear Screen And Depth Buffer
GL.glLoadIdentity();                                                            // Reset The Current Modelview Matrix,单位化
//gluLookAt本身有一个全局固定坐标系,不随模型的变换而变换,实图变换必需在任何模型变换之前被调用.
// GL.glMatrixMode(GL.GL_MODELVIEW);
GL.gluLookAt(0.0, 0.0, 0.0, -30.0, -10.0, -100.0, 0.0, 1.0, 0.0);    //设置视点
//模型变换 是局部坐标系统
//局部轴是还物体固连的
GL.glTranslatef(-2.0f, -1.0f, -6.0f);

//画圆锥
//创建二次曲面对象,X轴的箭头
GL.glTranslatef(1.5f, -2.0f, -2.0f);     //移动过来再移动回去
GL.glRotatef(90, 0.0f, 1.0f, 0.0f);
GLUquadric gluNewQuadric;
gluNewQuadric = GL.gluNewQuadric();
GL.gluQuadricNormals(gluNewQuadric, GL.GLU_SMOOTH); // 使用平滑法线
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.gluCylinder(gluNewQuadric, 0.1f, 0.0f, 0.5f, 32, 32);
GL.glRotatef(-90, 0.0f, 1.0f, 0.0f);
GL.glTranslatef(-1.5f, 2.0f, 2.0f);
//创建二次曲面对象,Y轴的箭头
GL.glTranslatef(-2.0f, 1.5f, -2.0f);     //移动过来再移动回去
GL.glRotatef(-90, 1.0f, 0.0f, 0.0f);
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.gluCylinder(gluNewQuadric, 0.1f, 0.0f, 0.5f, 32, 32);
GL.glRotatef(90, 1.0f, 0.0f, 0.0f);
GL.glTranslatef(2.0f, -1.5f, 2.0f);
//创建二次曲面对象,Z轴的箭头
GL.glTranslatef(-2.0f, -2.0f, 4.0f);     //移动过来再移动回去
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.gluCylinder(gluNewQuadric, 0.1f, 0.0f, 0.5f, 32, 32);
GL.glTranslatef(2.0f, 2.0f, -4.0f);

//在这里绘制坐标系统
//设置线的粗细
GL.glLineWidth(2.0f);
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(-2.0f, -2.0f, -2.0f);
GL.glVertex3f(1.5f, -2.0f, -2.0f);
GL.glEnd();

GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(-2.0f, -2.0f, -2.0f);
GL.glVertex3f(-2.0f, 1.5f, -2.0f);
GL.glEnd();

GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(-2.0f, -2.0f, -2.0f);
GL.glVertex3f(-2.0f, -2.0f, 4.0f);
GL.glEnd();

//绘制正方体

GL.glRotatef(x, 1.0f, 0.0f, 0.0f);                                            // Rotate The Quad On The X, Y, And Z Axes
GL.glRotatef(y, 0.0f, 1.0f, 0.0f);
GL.glRotatef(z, 0.0f, 0.0f, 1.0f);

//一次模型变换会改变局部坐标系统
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
GL.glBegin(GL.GL_QUADS);            // Draw A Quad

//1 正前
//     GL.glColor3f(0.0f, 1.0f, 0.0f);                                            // Set The Color To Gree
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(-1.5f, 0.5f, 1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(1.5f, 0.5f, 1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(1.5f, -0.5f, 1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(-1.5f, -0.5f, 1.0f);                                            //
GL.glEnd();

//2 后
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[1]);
GL.glBegin(GL.GL_QUADS);
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(-1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(1.5f, -0.5f, -1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(-1.5f, -0.5f, -1.0f);                                            //
GL.glEnd();
//左
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[2]);
GL.glBegin(GL.GL_QUADS);
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(-1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(-1.5f, -0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(-1.5f, -0.5f, 1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(-1.5f, 0.5f, 1.0f);                                            //
GL.glEnd();
//右
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[3]);
GL.glBegin(GL.GL_QUADS);
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(1.5f, -0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(1.5f, -0.5f, 1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(1.5f, 0.5f, 1.0f);                                            //
GL.glEnd();
//上
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[4]);
GL.glBegin(GL.GL_QUADS);
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(-1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(1.5f, 0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(1.5f, 0.5f, 1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(-1.5f, 0.5f, 1.0f);                                            //
GL.glEnd();
//下
GL.glBindTexture(GL.GL_TEXTURE_2D, textures[5]);
GL.glBegin(GL.GL_QUADS);
GL.glTexCoord2f(0.0f, 0.0f);
GL.glVertex3f(-1.5f, -0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 0.0f);
GL.glVertex3f(1.5f, -0.5f, -1.0f);                                            //
GL.glTexCoord2f(1.0f, 1.0f);
GL.glVertex3f(1.5f, -0.5f, 1.0f);                                            //
GL.glTexCoord2f(0.0f, 1.0f);
GL.glVertex3f(-1.5f, -0.5f, 1.0f);                                            //
GL.glEnd();                // Done Drawing The Cube

GL.glColor3f(1.0f,1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(2f, 0f, 0.0f);
GL.glVertex3f(-2f, 0f, 0f);
GL.glEnd();
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(0f, 2f, 0.0f);
GL.glVertex3f(0f, -2f, 0.0f);
GL.glEnd();
GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(0f, 0f, 2f);
GL.glVertex3f(0f, 0f, -2);
GL.glEnd();

}


核心代码二:串口数据接收部分 编码为这个 serialPort1.Encoding = Encoding.GetEncoding("iso-8859-1") 否则不能接收 为负的数,比如你传的是 -30

private void SynReceiveData(object serialPortobj)
{
//  int lengh;
char[] receive_char = new char[9];
while (true)
{
try
{
data = serialPort1.ReadLine();
}
catch(Exception ex)
{
break;
}
//   int temp_int = serialPort1.Read(char_read,0,9);
//  data = serialPort1.read
//string temp = serialPort1.ReadLine();
if (data.Length == 9)
{
receive_char = data.ToArray();
if (receive_char[0] == 'a')
{
//   receive_char[1] = (char)0xff;
//   receive_char[2] = (char)0xf1;
angle[0] = (Int16)((Int16)(receive_char[1] << 8) + (Int16)receive_char[2]);  //Pitch
angle[1] = (Int16)((Int16)(receive_char[4] << 8) + (Int16)receive_char[5]);  //Roll
angle[2] = (Int16)((Int16)(receive_char[7] << 8) + (Int16)receive_char[8]);  // Yaw
myGLView.X = (int)angle[0];    //opengl 类中的角度
myGLView.Y = (int)angle[1];
myGLView.Z = (int)angle[2];
SetText(angle[0].ToString(), angle[1].ToString(), angle[2].ToString());
}
}

}
}


核心代码三:跨线程访问题."线程间操作无效: 从不是创建控件“label1”的线程访问它。"

/// <summary>
/// 跨线程调用
/// </summary>
/// <param name="text1"></param>
/// <param name="text2"></param>
/// <param name="text3"></param>
private void SetText(string text1, string text2, string text3)
{
try
{
if (label1.InvokeRequired)
{
SetTextHandler set = new SetTextHandler(SetText);//委托的方法参数应和SetText一致
label1.BeginInvoke(set, new object[] { text1, text2, text3 }); //此方法第二参数用于传入方法,代替形参text
}
else
{
label1.Text = "Pitch:" + text1;
}
if (label2.InvokeRequired)
{
SetTextHandler set = new SetTextHandler(SetText);//委托的方法参数应和SetText一致
label1.Invoke(set, new object[] { text1, text2, text3 }); //此方法第二参数用于传入方法,代替形参text
}
else
{
label2.Text = "Roll  :" + text2;
}
if (label3.InvokeRequired)
{
SetTextHandler set = new SetTextHandler(SetText);//委托的方法参数应和SetText一致
label3.Invoke(set, new object[] { text1, text2, text3 }); //此方法第二参数用于传入方法,代替形参text
}
else
{
label3.Text = "Yaw :" + text3;
}
}
catch(Exception ex)
{
return;
}
}


上位传给上位机数据格式 'a''+''+''b''+''+''c''+''+''\n' a 是单个字符 '+'是传送的数据 ,高8位在前.

下位机51程序如下:

#include <REG51.H>
#include "com.h"

void main()
{  unsigned char *array;
unsigned char par[10];
bit flag_1=1,flag_2=1,flag_3=1;
int pitch=0,yaw=0,roll=1;
int i,k;

init_uart();
while(1)
{

par[0]='a';
par[3]='b';
par[6]='c';
par[9]='\n';

//模拟生成 pitch
if(flag_1)
{
pitch++;
//ReadLine()方法不能读取大于126的char
if(pitch==90)flag_1=0;
}
else
{
pitch--;
if(pitch==-90)flag_1=1;
}
//模拟生成 roll
if(flag_2)
{
roll++;
if(roll==90)flag_2=0;
}
else
{
roll--;
if(roll==-90)flag_2=1;
}
//模拟生成 yaw
if(flag_3)
{
yaw++;
if(yaw==90)flag_3=0;
}
else
{
yaw--;
if(yaw==-90)
flag_3=1;
}

par[1]=(pitch&0xff00)>>8;
par[2]=pitch&0x00ff;
par[4]=(roll&0xff00)>>8;
par[5]=roll&0x00ff;
par[7]=(yaw&0xff00)>>8;
par[8]=yaw&0x00ff;

for(i=0 ; i<10;i++)
{
sendchar(par[i]);						        //这里是把数据从串口发送出去
}
for( k=50;k>0;k--)
{
int j=50;
while(j--);
}
}
}


总结: 目前程序写到这只是一个过度阶段,下面是用 51单片机或是写ARM9裸机程序,读取姿态传感器中数据计算出欧拉角或着是四元数,

再传给上位机.

博文为本人所写.转载请表明出处.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: