加载中…
个人资料
无名指
无名指
  • 博客等级:
  • 博客积分:0
  • 博客访问:508,521
  • 关注人气:150
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
博文
分类: Matlab

Axes Transformations 坐标转换

今天闲来无事想起来以前在MATLAB中进行坐标变换都自己编写了坐标转换函数,MATLAB中应该会有吧,找了下帮助果真有,其实在MATLAB的AerospaceToolBox中封装好了很多坐标转换函数,可以直接调用完成对坐标系相对关系的描述。

angle2dcm

Create direction cosine matrix from rotation angles

由旋转角度创建方向余弦矩阵

Syntax

dcm = angle2dcm(rotationAng1, rotationAng2, rotationAng3)
dcm = angle2dcm(rotationAng1, rotationAng2, rotationAng3, rotationSequence)

Description

dcm = angle2dcm(rotationAng1, rotationAng2, rotationAng3) calculates the direction cosine matrix given three sets of rotation angles. 由三个旋转角计算方向余弦矩阵

dcm = angle2dcm(rotationAng1, rotationAng2, rotationAng3, rotationSequence) calculates the direction cosine matrix using a rotation sequence.由特定的旋转序列计算方向余弦矩阵

 

这里的旋转角是指右手系下的旋转方向为正如图

而得出的方向余弦矩阵dcm 是由原坐标系经旋转后到新坐标系的转换矩阵。

例如在导航专业中用到的导航坐标系到载体坐标系的旋转就可以用此函数求的,而求的的方向余弦矩阵为导航坐标系转向载体坐标系的,即Cnb

Inputs

rotationAng1

m-by-1 array of first rotation angles, in radians. 第一个旋转角

rotationAng2

m-by-1 array of second rotation angles, in radians.  第二个旋转角

rotationAng3

m-by-1 array of third rotation angles, in radians.第三个旋转角

rotationSequence

String that defines rotation sequence. For example, the default 'ZYX' represents a sequence where rotationAng1 is z-axis rotation, rotationAng2 is y-axis rotation, and rotationAng3 is x-axis rotation.

定义旋转序列的字符串。例如默认的'ZYX'表示了一个这样的旋转顺序:rotationAng1是绕Z轴旋转,rotationAng2 是绕y轴旋转,rotationAng3绕x轴旋转。共有如下几种形式:

'ZYX'
'ZYZ'
'ZXY'
'ZXZ'
'YXZ'
'YXY'
'YZX'
'YZY'
'XYZ'
'XZY'
'XYX'
'XZX'
'ZYX' (default)

Outputs

dcm

3-by-3-by-m matrix containing m direction cosine matrices.

3X3的方向余弦矩阵

 

Examples

将原坐标系axis1先沿着z轴旋转20度,沿着x轴旋转30度,再沿着y轴旋转45度,得到新的坐标系axis2。

那么在坐标系axis1中的点A(2,3,4)在新的坐标系axis2中的坐标B用以下方法来求得:

A=[2;3;4];

dcm=angle2dcm(20*pi/180,30*pi/180,45*pi/180,'ZXY');

B=dcm*A

>> B =
   0.359820367873134
   3.848996778596074
   3.749100305569416

 即B坐标为(0.359820367873134,3.848996778596074,3.749100305569416) 

在这里,方向余弦矩阵有个性质,即:方向余弦矩阵是正交的,就是其逆等于其转置  dcm'=inv(dcm);

所以如果需要坐标反向转换,只需要这样用:

dcm_inv=dcm';

C=dcm_inv*B;

>> C =
   2.000000000000000
   3.000000000000000
   4.000000000000000

 

阅读    收藏 
标签:

杂谈

分类: c#

请勿转载,我会不断的更新和修改。

修改日志:

1 20091112创建文档

2 20091113发送函数介绍,数据的接收,上位机基本功能的完成

 

 

一、创建Windows窗体项目

 

二、添加SerialPort组件

    

三、默认产生serialPort1对象

四、设置串口属性

三种方法(本实例用第三种)

1.设置下面的属性

2.代码实现

3.用我封装的一个类来实现

                 C# 封装了用于对 Serialport类属性的配置类及其保存窗

五、串口操作(打开关闭)

        按上述步骤初始化串口之后进行串口的打开和关闭操作

打开关闭串口的函数包含在SerialPort类中,利用SerialPort对象来引用

serialPort1.Open();         

serialPort1.Close();

例如:在程序中添加一个打开串口按钮btn_open,btn_open.Text初始化为"打开串口"

在btn_open响应函数中加入以下代码

        private void btn_open_Click(object sender, EventArgs e)
        {
            if (btn_open.Text == "打开串口")
            {
                btn_open.Text = "关闭串口";
                serialPort1.Open();
            }
            else
            {
                btn_open.Text = "打开串口";
                serialPort1.Close();
            }
        }

此时形成的界面截图如下:

此时程序的代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AHRSmanager;

namespace testOfserialPort
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

           
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
         
        }

        private void btn_SerialportSet_Click(object sender, EventArgs e)
        {
            using (串口设置窗口 frmConfig = new 串口设置窗口())
            {
                frmConfig.ShowDialog();
            }
        }

        private void btn_open_Click(object sender, EventArgs e)
        {
            if (btn_open.Text == "打开串口")
            {
                串口设置窗口.ReadSerialPortSet(serialPort1);    //串口初始化
                btn_open.Text = "关闭串口";
                serialPort1.Open();
            }
            else
            {
                btn_open.Text = "打开串口";
                serialPort1.Close();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            btn_open.Text = "打开串口";
        }
       
       
    }
}

 

这时该程序已经具有开关串口的作用,可以用  单PC机虚拟串口互连方法 介绍的方法进行串口测试(串口互联模式)

运行程序,点击串口配置按钮,进行参数配置,点击打开串口,VSPM就将显示串口的打开和关闭.

 

六、数据的发送

(一) 十六进制数据发送

      使用方法见  C#中用SerialPort类中的Write()方法发送十六进制数

1.为程序添加发送按钮,命名为btn_send,为程序添加文本输入框tb_send

2.在btn_send的回调函数中添加以下代码

        private void btn_send_Click(object sender, EventArgs e)
        {
            Byte[] BSendTemp = new Byte[1]; //建立临时字节数组对象
            BSendTemp[0] = Byte.Parse(this.tb_send.Text);//由文本框读入想要发送的数据
            this.serialPort1.Write(BSendTemp, 0, 1);//发送数据   
        }

3.测试

将串口配置为COM3,打开VSPM和串口调试助手,调试助手为COM4

打开串口COM3,将要发送的数写入输入文本框(0-255),点击发送在串口调试助手中就会出现相应的十六进制数据显示

 
(二) 字符串数据发送
1 为程序添加CheckBox cB_Hex,如若选中则发送Hex数据,如若未选则发送String数据。
2 将btn_send的响应函数btn_send_Click修改为:
        private void btn_send_Click(object sender, EventArgs e)
        {
            if (this.cB_Hex.Checked == true)
            {
                Byte[] BSendTemp = new Byte[1]; //建立临时字节数组对象
                BSendTemp[0] = Byte.Parse(this.tb_send.Text);//由文本框读入想要发送的数据
                this.serialPort1.Write(BSendTemp, 0, 1);//发送数据  
            }
            else
            {
                string serialStringTemp = this.tb_send.Text;
                this.serialPort1.WriteLine(serialStringTemp);
            }
        }
3 运行程序,取消Checkbox的选择
4 发送字符串,下面为测试图
5 这里主要利用了WriteLine函数,这个函数在Console中也有定义,用发基本一样。
七、数据的接收
(A)结构介绍
数据的接收大体有两种方案:1 主动定时读取;2 事件响应驱动
1 主动定时读取
    这种方式的适应能力较弱,当数据来源为定时并且不是很快的情况时可以考虑采用这种方法,这种方法主要适用于数据采集系统而不适用于随机事件发生时的通信或控制系统。
当然,这种方法的缺点是如果接收的数据不是定时的,则读取定时器的触发频率就要很小,这样才能保证及时的读取串口缓冲区。这也将大大的浪费系统资源。 
2 事件响应驱动
   这种方式是串口通信上位机制作的主要方式,其采用中断思想而成,当串口输入缓冲区中的字节数据大于某个设定的个数时,触发串口输入中断,这时在中断程序中读取串口输入缓冲区中的数据,具有实时性和灵活性,是个常用的较好的方法。本文也是采用这种方法来进行串口输入缓冲区的实时数据读取。
(B)事件响应驱动下的串口输入缓冲区数据读取
.NET中封装了SerialPort 类 表示串行端口资源。

命名空间:   System.IO.Ports
程序集:  System(在 System.dll 中)

除了前面用到的串口常规属性设置(BuadRate,PortName),这里用到了一个新的串口属性:

 

ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubproperty.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReceivedBytesThreshold 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数。

 

这个ReceiveBytesThreshold属性即是设置串口输入缓冲区中的数据字节大于ReceiveBytesThreshold时触发DataReceived事件。

用法:

<1>在设计器双击串口serialport1的DataReceived事件,在代码中就会自动加入serialPort1_DataReceived函数作为DateReceived的事件触发函数。

<2>作为测试,先将serialport1.ReceiveBytesThreshold设为1,即串口输入缓冲区有数就触发DataReceived事件。

<3>加入RichTextBox rTB_receive作为串口接收数据的显示组件

<4>在DataReceived事件响应函数中读取串口输入缓冲区中的数据

        string serialReadString;
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            serialReadString += serialPort1.ReadExisting();

        }

这里serialReadString即为读取到串口输入缓冲区的数据。

要想将其显示到RichTextBox rTB_receive中,这里出现了一个跨线程的问题,因为DataReceived事件是在辅助线程中被激发的,所以要将数据显示到rTB_receive的主线程中就要进行一定的处理,处理方法如下:

C#中SerialPort类中DataReceived事件GUI实时处理方法

 
将DataReceived事件响应函数修改为如下:

        string serialReadString;
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            serialReadString = serialPort1.ReadExisting();
            this.rTB_receive.Invoke
                (
                new MethodInvoker
                    (

                      delegate
                      {

                          this.rTB_receive.AppendText(serialReadString);
                      }

                    )

                );

        }

这时就可以按字符串收发了!
<5> 测试图,打开上位机和调试助手,点击调试助手的发送按钮,上位机就会相应的显示接收到的数据.
<6> 这时候就完成了基本上位机功能的编写
至此工程文件:
 
串口数据的读取还涉及到其他的读取函数,
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif Read 已重载。 从 SerialPort 输入缓冲区中读取。
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReadByte SerialPort 输入缓冲区中同步读取一个字节。
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReadChar SerialPort 输入缓冲区中同步读取一个字符。
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReadExisting 在编码的基础上,读取 SerialPort 对象的流和输入缓冲区中所有立即可用的字节。
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReadLine 一直读取到输入缓冲区中的 NewLine 值。
ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_system/icons/CFW.gif ReadTo

一直读取到输入缓冲区中的指定 value 的字符串。

 根据需要自己选择就行了,很简单,就不再啰嗦了。
 
阅读    收藏 
标签:

c

绘图

zedgraph

分类: c#

该控件来自于CodeProject

http://www.codeproject.com/KB/graphics/zedgraph.aspx

我大多的.NET程序的绘图程序都用的是这个控件。下面是这个控件的文档翻译及其基本使用方法。

A flexible charting library for .NET   By JChampion

一个灵活的.NET绘图库
Looking for a way to draw 2D line graphs with C#? Here's yet another charting class library with a high degree of configurability, that is also easy to use.

正在寻找利用C#画二维线型图像的方法吗?这个就是高度可配置的绘图类库,当然,他也是非常容易用的。 

Introduction

ZedGraph是一个类库,为Windows Forms 设计的用户控件,该控件可以通过专业的数据资料创建2D线、Bar和Pie图像。该类库提供高度的灵活性——几乎每一个图像的部分都能由用户修改。于此同时,通过为所有图像的属性提供缺省值使类库的用法保持简单。类库中包括选择合适的刻度因数范围和基于被显示值的的数据范围的步长值的代码。此外,ZedGraph 兼容于.NET 2.0和VS.NET 2005.

ZeGraph 是作为开源开发工程在SourceForge被维护的。该网站包括该项目的wiki、文档、更新历史和所有的发行版本。

Wiki上含有一套简单的图像实例由公开的代码完成(许多的例子包括C#和VB代码)。

Background

    我们可以寻找到很多的绘图类库,但是似乎没有一个能够满足我的需要。我发现MSCHART太诡异了,许多其他的选项都不具有可配置性但我需要达到一种精致的外观。当然,许多商业开发包能够做这种花招,但是我需要某种免费的东东。由此,ZedGraph产生了!

    这个类库将可以产生各种线型、条形、图形分割统计图表在Form上,考虑到位置矩形和一些数据点(翻译的有点诡异,没太看明白)。ZedGraph处理二维线形或散点图形,所彩的百分数条形图形,误差条形图像,日本烛台图形和图形分割统计图表——他现在还不能处理2.5D或3D表面图形。可以通过坐标轴标签、标题、图例标签、文字标签、箭头、镜像等对象修饰图像。

ZedGraphWiki 和online class documentation 提供了大量的有用的信息,针对其提供更多的信息,ZedGraph 有大量的选项没有在这个入门文档中提供。

Using ZedGraph as a UserControl 

将ZedGraph作为一个控件可由Visual Studio.NET的控件工具箱中获取。 要创建ZedGraph,首先要打开Visual Studio.NET,创建一个新的Forms项目。打开form设计器使其出现在当前窗口,如下图

右击工具箱->选择项

点击浏览定位到 zedgraph.dll文件,并添加。

一旦添加了此文件,你会看到ZedGraphControl选项在工具箱中。如下图

  1. 在项目主菜单->选择添加引用->添加ZedGraph.dll,然后点击OK,重复这个过程添ZedGraph.Web.dll,这将包括所有的ZedGraph功能在你的工程中。
  2. 添加using ZedGraph;语句到你的主Form代码中
  3. 在Form设计器中,从工具箱中拖拽ZedGraphControl到From上,按照你的意愿修改其大小和位置。你现在在你的Form中就有了一个ZedGraph控件。如下图
  4. 所有的ZedGraph功能都可以通过ZedGraphControl.MasterPane属性来访问,提供ZedGraphControl.GraphPane来引用第一个GraphPane在主MasterPane列表中。(下面会解释这句话的意思)。
  5. 在Form设计器中双击Form(不是ZedGraphControl)。这将会放置一个Form1_Load()模板在你的代码文件中。
  6. 在Form设计器中,激活Form后定位到属性中的事件如图,双击Resizes事件,这时Form1_Resize相应的函数模板将出现在在代码文件中
  7. 修改Form1_Load()和Form1_Resize()方法,按照下面的代码添加CreateGraph() and SetSize() 方法。(这里假定你的控件名称为zedGraphControl1)
  8. //  form 'Resize'  的事件相应方法

    private void Form1_Resize( object sender, EventArgs e )

         SetSize();

    //SetSize() 是独立于Resize()的,所以我们能够独立的调用他通过Form1_Load() 方法。

    //这将保留10像素环绕控件的外部边缘,定制这些使之适合你的需要。
    private void SetSize()

         zedGraphControl1.Location = new Point( 10, 10 ); 

         //保留一个小的页面空白在控件的周围
         zedGraphControl1.Size = new Size( ClientRectangle.Width - 20, 
                                                         ClientRectangle.Height - 20 );


    // Load事件的相应函数
    private void Form1_Load( object sender, EventArgs e )

         // 装载图像 
         CreateGraph( zedGraphControl1 ); 

         //设定控件的大小填充form 
         SetSize();


    // 创建图像
    private void CreateGraph( ZedGraphControl zgc )

         //得到GraphPane的引用
         GraphPane myPane = zgc.GraphPane; 
     
         // 设置标题 
         myPane.Title.Text = "My Test Graph\n(For CodeProject Sample)"; 
         myPane.XAxis.Title.Text = "My X Axis"; 
         myPane.YAxis.Title.Text = "My Y Axis"; 
         //生成正弦函数的数据集合 
         double x, y1, y2; 
         PointPairList list1 = new PointPairList(); 
         PointPairList list2 = new PointPairList(); 
         for ( int i = 0; i < 36; i++ ) 
         { 
                x = (double)i + 5; 
                y1 = 1.5 + Math.Sin( (double)i * 0.2 ); 
                y2 = 3.0 * ( 1.5 + Math.Sin( (double)i * 0.2 ) ); 
                list1.Add( x, y1 ); 
                list2.Add( x, y2 ); 
         } 
         //用钻石符合形状生成红色的曲线和图例

         LineItem myCurve = myPane.AddCurve( "Porsche", 
                     list1, Color.Red, SymbolType.Diamond ); 
         //利用圆型的符号生成蓝色的曲线和图例
         LineItem myCurve2 = myPane.AddCurve( "Piper", 
                     list2, Color.Blue, SymbolType.Circle ); 
         //告诉ZedGraph 去重新描绘坐标轴当数据变化时
         zgc.AxisChange();
    }

  9. 每次添加或改变数据的时候调用AxisChange()方法。这将告诉ZedGraph去重新计算坐标轴的范围,(注意:这是AxisChange()的功能——你可以在任何你喜欢的时候调用这个方法,他会基于当前坐标点数据集合来更新坐标范围,如果你不希望坐标轴被重新调节,你也可以避免调用AxisChange())

8. 执行效果

 Enhancing the graph

 

ZedGraph 允许你通过多种途径更改图形的属性,图像的每个部分都被打包成一个类结构体,这个结构体有可更改的属性去控制图形的输出。下面就是一些在ZedGraph中提供的类(注意这些类是XML文档,详细的细节中每个类请看ZedGraph documentation

 

 Class

 Description

 MasterPane

这是一个管理多个GraphPane对象的类,继承于PaneBase。MasterPane类的应用是可选的,因为GraphPane类能够直接用于单个面板。提供布局、排列和单个GraphPane对象的管理的方法
 GraphPane 图像的主要类,继承自PaneBase。包含所有其他的类作为属性。多用于控制图像面板的标题、窗框架和坐标轴框架、背景等属性。

 XAxis, YAxis, Y2Axis

Axis类的子类。这些类包括了很多坐标轴显示的形式,包括:刻度、网格、颜色、画笔、字体、标签和类型。

 Scale

通过Axis类声明的一个类实例。包括刻度范围、步长、格式和刻度的显示选项。由Linear, Log, Text, Date, Ordinal, Exponent, LinearAsOrdinal, and DateAsOrdinal scales的不同而不同。

 Legend

此类为描述位置、字体、颜色等性质的类,用于绘制图例

 CurveItem

一个对应单条曲线并包含数据的抽象基类。LineItem, BarItem, HiLowBarItem, ErrorBarItem, PieItem, StickItem, OHLCBarItem, and JapaneseCandleStickItem 都继承于此类。

 CurveList

一个集合类维护了一个CurveItem的对象链表。在链表中的曲线的顺序控制着 Z-顺序为了绘图。在链表中最后的曲线将会出现在其她的曲线之后。

 GraphObj

这是一个抽象的基类,他包含了多种的追加图像对象在一个分块中的位置信息。TextObj, ImageObj, LineObj, ArrowObj, EllipseObj, BoxObj, and PolyObj 都继承自GraphObj.

 GraphObjList

一个维护GraphObj链表的集合类。

 FontSpec

包括字体信息的功能类,主要是关于图像上字体的颜色、角度、大小、样式、框架和字体的背景填充。每一个包含字体信息的类将会包含一个或几个FontSpec的对象去相应的描述相关联的字体。

 Fill

包括背景颜色特性的功能类。每一个含有色彩填充能力的对象都包含一个或多个Fill对象去相应的描述相关联的颜色填充。

 Border

包括边框特性的功能类。每一个含有边框描述能力的对象都包含一个或多个Border对象去相应的描述相关联的边框线形和颜色。

 Location

 一个通用的类,此类处理图像对象在图形中的位置。

 PointPair

 一个封装了一对double型数据的数据结构,其表征了一个(x,y)的数据点,这是在每个CurveItem中值数组的内部的存储格式。

 PointPairList

 一个集合类维护了一个PointPair对象的数据链表。

 

 

 XDate

 此类封装了单独的数据时间值(Double)

通过访问上面的每一个类的属性来修改图像。例如,如果你包括下面的代码在你的CreateGraph()方法中, 放在前述的代码示例之后,输出图像将会相应的改变。

            // 改变标题的颜色

            myPane.Title.FontSpec.FontColor = Color.Green;

            //对图像添加灰色网格
            myPane.XAxis.MajorGrid.IsVisible = true;
            myPane.YAxis.MajorGrid.IsVisible = true;
            myPane.XAxis.MajorGrid.Color = Color.LightGray;
            myPane.YAxis.MajorGrid.Color = Color.LightGray;

            //改变图例的位置

            myPane.Legend.Position = ZedGraph.LegendPos.Bottom;

            //使两个曲线线性变细
            myCurve.Line.Width = 2.0F;
            myCurve2.Line.Width = 2.0F;

            //在曲线下填充区域
            myCurve.Line.Fill = new Fill(Color.White, Color.Red, 45F);
            myCurve2.Line.Fill = new Fill(Color.White, Color.Blue, 45F);

            //增加符号的大小然后填充其为白色

            myCurve.Symbol.Size = 8.0F;
            myCurve2.Symbol.Size = 8.0F;
            myCurve.Symbol.Fill = new Fill(Color.White);
            myCurve2.Symbol.Fill = new Fill(Color.White);

            //对坐标轴框架添加背景倾斜填充(其实就是坐标轴的背景图)

            // Add a background gradient fill to the axis frame
            myPane.Chart.Fill = new Fill(Color.White,
                Color.FromArgb(255, 255, 210), -45F);

            // 添加说明文字和箭头
            TextObj myText = new TextObj("Interesting\nPoint", 230F, 70F);
            myText.FontSpec.FontColor = Color.Red;
            myText.Location.AlignH = AlignH.Center;
            myText.Location.AlignV = AlignV.Top;
            myPane.GraphObjList.Add(myText);
            ArrowObj myArrow = new ArrowObj(Color.Red, 12F, 230F, 70F, 280F, 55F);
            myPane.GraphObjList.Add(myArrow);

最终的效果如下所示:

 

  

 

 

阅读    收藏 
标签:

杂谈

分类: c#

即是所谓的IEEE754标准,这也是大多数硬件存储浮点数的标准。单精度浮点数占4个字节,表示范围为:在负数的时候是从 -3.402823E38 到 -1.401298E-45,而在正数的时候是从 1.401298E-45 到 3.402823E38 。

 

在C#中的转换函数为:

1,由四个字节的十六机制数组转浮点数:

          byte[] bytes = new byte[4];

          BitConverter.ToSingle(bytes, 0);

2,由浮点数转数组:

byte[] bytes = BitConverter.GetBytes(floatValue);

 

这种转换方法经常用于串口通讯中,表示范围足够各种传感器数值传输及工控场合,将要发送的浮点数据转换为4个字节的十六机制数,然后由串口发出,在接收端再将其转换为浮点数。

单片机或非.net环境下使用转换程序则不能调用BitConverter类!

提供以下代码以供转换:

未修改过的如下:可以在C#中直接调用而不用库函数

       public static float ToFloat(byte[] data)
        {
            float a = 0;
            byte i;
            byte[] x = data;
            unsafe
            {
                void* pf;
                fixed (byte* px = x)
                {
                    pf = &a;
                    for (i = 0; i < data.Length; i++)
                    {
                        *((byte*)pf + i) = *(px + i);
                    }
                }
            }
               

           
            return a;
        }    

        public static byte[] ToByte(float data)
        {
            unsafe
            {
                byte* pdata = (byte*)&data;
                byte[] byteArray = new byte[sizeof(float)];
                for (int i = 0; i < sizeof(float); ++i)
                    byteArray[i] = *pdata++;
           
                return byteArray;
            }
        }    

 

如果对工程进行直接编译会报出一下错误:这是因为C#默认不提供指针支持,只有在不安全代码的形式下才可以用指针。

 

 错误 1 不安全代码只会在使用 /unsafe 编译的情况下出现 E:\Visual Studio 2008\Projects\TEST\testOfFloatConsolt\testOfFloatConsolt\Program.cs 26 13 testOfFloatConsolt
这时选择VS的菜单栏中的项目->"Project"属性->生成->常规->允许不安全代码  勾选即可

 

 单片机串口通讯浮点转换函数

我在AVR串口通信协议中用到了这部分,直接将单片机的运算结果(浮点类型)转换为(字节类型)嵌入串口通信协议中,上传至上位机。

下面为符合IEEE754标准将浮点数转换为四个字节的数组的函数源代码:已经用于mega16单片机的串口通信中。

WinAVR-20090313测试通过:

void FloatToByte(float floatNum,unsigned char* byteArry)
{
    char* pchar=(char*)&floatNum;
    for(int i=0;i<sizeof(float);i++)
    {
     *byteArry=*pchar;
     pchar++;
     byteArry++;
    }
}

 下面为符合IEEE754标准的由四个字节型数组转化为相应的浮点数

WinAVR-20090313测试通过:

    float ByteToFloat(unsigned char* byteArry)
{
  return *((float*)byteArry);
}

 

 调用测试方法:其中USART_Transmit();为向串口发送的函数。

    unsigned char floatToByte[4];
    FloatToByte(12.15,floatToByte);
    float a=ByteToFloat(floatToByte);
    FloatToByte(a,floatToByte);
    USART_Transmit(floatToByte[0]);    
    USART_Transmit(floatToByte[1]);                            
    USART_Transmit(floatToByte[2]);
    USART_Transmit(floatToByte[3]);

 

在上位机用串口进行读取时调用

BitConverter.ToSingle(bytes, 0);

就会转换成12.15,测试方法可以随着需求改变。

阅读    收藏 
分类: Matlab



一,matlab中生成随机数主要有三个函数:rand, randn,randi

1,rand  生成均匀分布的伪随机数。分布在(0~1)之间

   主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数

             rand(m,n,'double')生成指定精度的均匀分布的伪随机数,参数还可以是'single'

             rand(RandStream,m,n)利用指定的RandStream(我理解为随机种子)生成伪随机数

2,randn 生成标准正态分布的伪随机数(均值为0,方差为1)

   主要语法:和上面一样

3, randi 生成均匀分布的伪随机整数

   主要语法:randi(iMax)在开区间(0,iMax)生成均匀分布的伪随机整数

             randi(iMax,m,n)在开区间(0,iMax)生成mXn型随机矩阵

             r = randi([iMin,iMax],m,n)在开区间(iMin,iMax)生成mXn型随机矩阵

示例验证:

均值分布

         概率分布图:

            y=rand(1,3000000);
            hist(y,2000);

           

         散点图:

            y=rand(1,3000000);
            plot(y)

            

 

 

正态分布

         概率分布图:

           y=randn(1,3000000);
           hist(y,2000);

           

 

         散点图:

           y=randn(1,3000000);
           plot(y);

          

二,关于随机种子,伪随机数的重复生成

正常情况下每次调用相同指令例如rand生成的伪随机数是不同的,

例如:

rand(1,3)

rand(1,3)

matlab的输出为:

ans =
   0.139043482536049   0.734007633362635   0.194791464843949
ans =
   0.602204766324215   0.937923745019422   0.149285414707192

如何使两个语句生成的随机数相等呢?

Matlab帮助中的下面章节有所叙述:

Managing the Default Stream

管理默认(缺省)流

 

rand, randn, and randi draw random numbers from an underlying random number stream, called the default stream. The @RandStream class allows you to get a handle to the default stream and control random number generation.

rand,randn,和randi 从一个基础的随机数流中得到随机数,叫做默认流。你可以通过 @RandStream 类得到默认流的句柄从而控制随机数的生成。

Get a handle to the default stream as follows:

以下为得到默认流句柄的代码:

defaultStream=RandStream.getDefaultStream

defaultStream = 

mt19937ar random stream (current default)
             Seed: 0
         RandnAlg: Ziggurat

Return the properties of the stream object with the get method:
用get方法返回流对象属性:
get(defaultStream)
             Type: 'mt19937ar'
       NumStreams: 1
      StreamIndex: 1
        Substream: 1
             Seed: 0
            State: [625x1 uint32]
         RandnAlg: 'Ziggurat'
       Antithetic: 0
    FullPrecision: 1

The State property is the internal state of the generator. You can save the State of defaultStream.
state属性是发生器的内部状态,你可以保存默认流的状态:
myState=defaultStream.State;


Using myState, you can restore the state of defaultStream and reproduce previous results.
利用myState你可以恢复默认流状态重新生成前面的结果:
myState=defaultStream.State;
A=rand(1,100);
defaultStream.State=myState;
B=rand(1,100);
isequal(A,B)

ans =

     1
你也可以直接使用@RandStream 类的reset静态方法重置种子状态来获取相同的随机生成序列,下面是示例代码:

stream = RandStream.getDefaultStream;%获取默认的随机种子(暂时这么叫,帮助有详细解释)
reset(stream);%重置
rand(stream,1,3)
reset(stream);%重置
rand(stream,1,3)

matlab的输出为:

ans =
   0.814723686393179   0.905791937075619   0.126986816293506
ans =
   0.814723686393179   0.905791937075619   0.126986816293506

可以看出生成的随机码是相等的,这样可以用于重复实验上来

阅读    收藏 
标签:

杂谈

分类: c#

C# 中List类的Find,Exists,FindAll,FindIndex ,FindLast ,FindLastIndex等方法的应用举例

以Exists为例,MSDN中是这样叙述的

ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/xna.gif Exists

确定 List<(Of <(T>)>) 是否包含与指定谓词所定义的条件相匹配的元素。

 

       我一直都认为编写MSDN文档的人语文是好的令人发指啊!

       相信很多人都深有体会,这里每个字都认识,放一起完全不知所云,看了好多例子才知道是怎么回事,不知道是我肤浅,还是技术总是要深奥。

       总结一下,写了一个通俗点的例子,希望能对看到的人有用。

 

     static void Main(string[] args)//主函数即入口函数,不知道什么意思的面壁吧!
                {
                        List<decimal> list1=new List<decimal>();//此处<>内是泛型的概念,不知道
                                                                            //的话找本教材看下吧,感觉就像是宏

                                                                                                     // 替换
                        for(int i=0; i<100;i++)                         //生成链表
                        {
                                list1.Add(i);
                        }
                                

                        if (list1.Exists(MatchPRE))//调用方法,谓词匹配函数的调用,这是调用您自定义的函

                                                                                                                                         //数MatchPRE
                                Console.WriteLine("ok");//若list1中存在99,则输出ok
                        else
                                Console.WriteLine("fail");//若list1中不存在99,则输出fail
                        Console.ReadLine();
                }
                private static bool MatchPRE(decimal p)//条件匹配函数,list1中每个元素都会传入P中

                                                                                            //匹配后函数返回
                {
                       if (p == 99)//此句为匹配条件,如果匹配,返回,你可以随意更改成你想要的值
                                return true;
                        else
                        {
                                return false;
                        }
                }

 

例程源代码

 

20090928更新

关于List(T).Sort方法,MSDN是这样叙述的。

 

  名称 说明
ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/xna.gif Sort()()() 使用默认比较器对整个 List<(Of <(T>)>) 中的元素进行排序。
ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/xna.gif Sort(Comparison<(Of <(T>)>)) 使用指定的 System..::.Comparison<(Of <(T>)>) 对整个 List<(Of <(T>)>) 中的元素进行排序。
ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/xna.gif Sort(IComparer<(Of <(T>)>)) 使用指定的比较器对整个 List<(Of <(T>)>) 中的元素进行排序。
ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/pubmethod.gif ms-help://MS.MSDNQTR.v90.chs/fxref_mscorlib/icons/xna.gif Sort(Int32, Int32, IComparer<(Of <(T>)>)) 使用指定的比较器对 List<(Of <(T>)>) 中某个范围内的元素进行排序。
 
 
1.你可一采用第一个方法,这个方法为默认方法,对于T为数时将List的成员按照从小到大排列。
2.如果不符合要求则你需要使用第二个方法,实现Comparison<(Of <(T>)>) 泛型委托。即下面的例子
3.也可是利用实现比较器接口的方法实现,即最后两种方法。
 

List.Sort应用例程:实现比较泛型委托

                static void Main(string[] args)
                {
                       Random _random = new Random();//随机对象
                        List<int> _iList = new List<int>();//列表对象
                        for (int i = 0; i < 10; i++)
                        {
                                _iList.Add( _random.Next(0,10)); //随机函数创建列表
                        }
                        Console.WriteLine("排序前");
                        for (int i = 0; i < 10; i++)
                        {
                                Console.WriteLine(_iList[i]);//排序前输出
                        }

                        _iList.Sort(CompareListBig);//执行排序
                        Console.WriteLine("排序后");
                        for (int i = 0; i < 10; i++)
                        {
                                Console.WriteLine(_iList[i]);//排序后输出
                        }
                        Console.ReadLine();
                }
                private static int CompareListBig(int _a,int _b)//由大到小
                {
                        int _temp = _a - _b;
                        if (_temp < 0) return 1;
                        if (_temp > 0) return -1;
                        return 0;
                }
                private static int CompareListSmall(int _a, int _b)//由小到大
                {
                        int _temp = _a - _b;
                        if (_temp> 0) return 1;
                        if (_temp < 0) return -1;
                         return 0;
                }

阅读    收藏 
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有