艾伟:WM--GPS开发

简介:   前几天,有朋友托我给他写个GPS程序,就取经纬度坐标,以及将之转换成高斯直角坐标。花了一些时间,给他做了个小程序。  后来总结时,想起,很多网上朋友都会问及关于GPS开发的一些事。我这里先将我的程序解释下,然后再总结下,相关经验及个人看法。

  前几天,有朋友托我给他写个GPS程序,就取经纬度坐标,以及将之转换成高斯直角坐标。花了一些时间,给他做了个小程序。

  后来总结时,想起,很多网上朋友都会问及关于GPS开发的一些事。我这里先将我的程序解释下,然后再总结下,相关经验及个人看法。

  目前在一些移动设备中,都提供GPS功能,设备中都需要一个接收器,用来接收GPS信号。(类似于GPRS工作方式)。GPS一旦启动后,会自动连接卫星,接收信号,通过算法计算出位置等信息,然后以NMEA data的格式输出。GPS receiver就是接收卫星信号转换成NMEA data的设备。

  开发GPS有3种选择:
  1、直接使用串口连接GPS接收器
  2、GPS Intermediate Driver
  3、使用第三方类库(目前opennetcf提供相应类库)

  目前,WM5.0以上系统,都内置了GPS Intermediate Driver。通过它,我们能够很方便的取道GPS数据。

  关于GPS方面的文章可以参考:
  1、30 Days of .NET [Windows Mobile Applications] - Day 03: GPS Compass(GPS指南针)
  2.NET Compact Framework下的GPS NMEA data数据分析

  虽然GPS Intermediate Driver提供了我们非常快捷的取得GPS信息,但同时也有一定的弊端。

  那下面我讲介绍我如何在该项目中使用GPS的。

  我使用GPS Intermediate Driver,它能够快速开发,MS也提供了很强大的例子来方便我们使用。
在微软的WM SDK安装目录下有GPS工程。(Windows Mobile 6 SDK\Samples\PocketPC\CS\GPS)

  该Demo中
  GPS.cs:封装了GPS的操作类,比如Open(),Close(),Connect()。可以很快捷的使用。
  GpsDeviceState.cs:用于取得目前GPS设备的状态信息。
  GpsPosition.cs:每次GPS数据取得后,都会放入该类。
  LocationChangedEventArgs.cs:一旦位置改变,即可将新的GPSPosition取得到。

public   void  Open()
{
    
if  ( ! Opened)
    {
         
//  create handles for GPS events
         newLocationHandle  =  CreateEvent(IntPtr.Zero,  0 0 null );
         deviceStateChangedHandle 
=  CreateEvent(IntPtr.Zero,  0 0 null );
         stopHandle 
=  CreateEvent(IntPtr.Zero,  0 0 null );

         gpsHandle 
=  GPSOpenDevice(newLocationHandle, deviceStateChangedHan
dle, 
null 0 );

         
//  if events were hooked up before the device was opened, we'll need
         
//  to create the gps event thread.
          if  (locationChanged  !=   null   ||  deviceStateChanged  !=   null )
         {
             CreateGpsEventThread();
         }
    }
}

  通过调用CreateEvent,创建handles,然后调用GPSOpenDevice API,将handle传入,取到gps设备的handle
得到handle后,再创建一个线程来监听GPS数据及设备状态。通过调用CreateGpsEventThread方法。

private   void  CreateGpsEventThread()
{
    
//  we only want to create the thread if we don't have one created already 
    
//  and we have opened the gps device
     if  (gpsEventThread  ==   null   &&  gpsHandle  !=  IntPtr.Zero)
    {
        
//  Create and start thread to listen for GPS events
        gpsEventThread  =   new  System.Threading.Thread( new  System.Threading.
ThreadStart(WaitForGpsEvents));
        gpsEventThread.Start();
    }
}

  在WaitForGpsEvents方法中,就while不听的监听。
  当deviceStateChanged,就调用deviceStateChanged事件,然后取得当前设备状态。
  当locationChanged,就调用locationChanged事件,取得当前坐标。
  这样一个基本的GPS数据取得流程就算完成了。

以下为调用API的函数声明。

Code
[DllImport("gpsapi.dll")]
static extern IntPtr GPSOpenDevice(IntPtr hNewLocationData, IntPtr hDeviceStateChange, string szDeviceName, int dwFlags);

[DllImport(
"gpsapi.dll")]
static extern int  GPSCloseDevice(IntPtr hGPSDevice);

[DllImport(
"gpsapi.dll")]
static extern int  GPSGetPosition(IntPtr hGPSDevice, IntPtr pGPSPosition, int dwMaximumAge, int dwFlags);

[DllImport(
"gpsapi.dll")]
static extern int  GPSGetDeviceState(IntPtr pGPSDevice);

[DllImport(
"coredll.dll")]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, int bManualReset, int bInitialState, StringBuilder lpName);

[DllImport(
"coredll.dll")]
static extern int CloseHandle(IntPtr hObject);

const int waitFailed = -1;
[DllImport(
"coredll.dll")]
static extern int WaitForMultipleObjects(int nCount, IntPtr lpHandles, int fWaitAll, int dwMilliseconds);

const int eventSet = 3;
[DllImport(
"coredll.dll")]
static extern int EventModify(IntPtr hHandle, int dwFunc);

  有时候,我们往往不需要简单的GPS的经纬度,我们或许需要更多的数据。这时候就需要转换。
比如,在我这个应用中,需要取得对应的高斯直角坐标。

  当然我们需要通过一系列的数学运算得到。
  我们需要设置一个重要子午线的坐标,然后根据该坐标计算得到。

public   static   void  ConvertBLToXY( double  bl1,  double  bl2,  ref   double  x,  ref   double  y)
{
    
if  (enableBLToXY)
    {
        
try
        {
            
// a2 输入中央子午线,以度.分形式输入,如115度30分则输入115.30; 起算数据l0 
            
// f2 以度小数形式输入经度值, l 
            
// e2 以度小数形式输入纬度值,b 
            
// s2 计算结果,横坐标y 
            
// t2 计算结果,纵坐标x 
            
// 投影带号计算 n=[l/6]+1 如:测得经度103.xxxx,故n=[103.x/6]+1=17+1=18 
            
// 中央经线经度 l0 = n*6-3 = [l/6]*6+3 
             double  a2, f2, e2, s2, t2;
            a2 
=  centerLine;
            f2 
=  bl1;
            e2 
=  bl2;
            e2 
=  x;
            t2 
=  y;
            
double  b2, h2, i2, j2, k2, l2, m2, n2, o2, p2, q2, r2;

            b2 
=  ( int )(a2)  +  (( int )(a2  *   100 -  ( int )(a2)  *   100 /   60   +  (a2  *   10000   -
(
int )(a2  *   100 *   100 /   3600 ;
            
// 把l0化成度(a2) 
            
// g2 = f2 - b2 ' l -l0 
            
// h2 = g2 / 57.2957795130823 '化作弧度
            
// 将经差的单位化为弧度
            h2  =  (f2  -  b2)  /   57.2957795130823 ;
            i2 
=  Math.Tan(e2  /   57.2957795130823 );
            j2 
=  Math.Cos(e2  /   57.2957795130823 );
            k2 
=   0.006738525415   *  j2  *  j2;
            l2 
=  i2  *  i2;
            m2 
=   1   +  k2;
            n2 
=   6399698.9018   /  Math.Sqrt(m2);
            o2 
=  h2  *  h2  *  j2  *  j2;
            p2 
=  i2  *  j2;
            q2 
=  p2  *  p2;
            r2 
=  ( 32005.78006   +  q2  *  ( 133.92133   +  q2  *   0.7031 ));
            s2 
=  ((((l2  -   18 *  l2  -  ( 58   *  l2  -   14 *  k2  +   5 *  o2  /   20   +  m2  -  l2)  *
o2 
/   6   +   1 *  n2  *  (h2  *  j2);
            
// 在计算的基础上加上了“带号”(18)和“东移”(500km) 
            s2  =  s2  +   18500000 ;
            
// 计算结果,横坐标y 
            t2  =   6367558.49686   *  e2  /   57.29577951308   -  p2  *  j2  *  r2  +  ((((l2  -   58 )
 
*  l2  +   61 *  o2  /   30   +  ( 4   *  k2  +   5 *  m2  -  l2)  *  o2  /   12   +   1 *  n2  *  i2  *  o2  /   2 ;
            
// 计算结果,纵坐标x 

            x 
=  s2;
            y 
=  t2;
        }
        
catch  (Exception ex)
        {
            MessageBox.Show(ex.Message);
            x 
=   0 ;
            y 
=   0 ;
        }
    }
}

 

  以上就是我的GPS应用程序的主体代码介绍。希望对大家有用。

  可能根据每个项目的实际状况不一致,我的个人意见如下:
  1、项目中GPS部分取得的数据简单的话,可以直接采用GPS Intermediate Driver
  2、最好自己封装下直接使用串口连接GPS接收器的功能。
  3、地图定位,可以借助Google。
  4、注意释放内存,因为多数都需要调用非托管
  5、一定要用线程处理。

  最后,附上应用程序CAB包。很多人写打包程序觉得有时候有困难,其实,一个简单的打包CAB程序相对很简单。现在很多WM设备,基本稳妥地还是用基于.net cf2.0为主。所以大家工程发布最好还是以.net cf2.0吧,因为有些设备安装.net cf3.5不稳定导致。

目录
相关文章
|
6月前
|
编解码 开发工具 vr&ar
RT-Thread 瑞萨 智能家居网络开发:RA6M3 HMI Board 以太网+GUI技术实践
RT-Thread 瑞萨 智能家居网络开发:RA6M3 HMI Board 以太网+GUI技术实践
252 4
|
6月前
|
编解码 开发工具 vr&ar
DP活动:以太网HMI线下培训RA6M3 HMI Board[MQTT Squareline LVGL]
DP活动:以太网HMI线下培训RA6M3 HMI Board[MQTT Squareline LVGL]
112 1
|
传感器 数据采集 物联网
基于小熊派光强传感器BH1750状态机驱动项目升级(带LCD屏显示)
基于小熊派光强传感器BH1750状态机驱动项目升级(带LCD屏显示)
95 0
|
传感器 自然语言处理 监控
快速开发一个带APP的红外体温检测枪(基于AliOS Things Inside的Wi-Fi模组)
非接触红外测温在医疗,环境监测、个人健康等领域得到越来越广泛的应用。本文将向大家介绍如何通过AliOS Things Inside的WiFi模组,快速完成体温检测,流程涵盖从传感器数据采集,到阿里云IoT智能生活平台接入,以及快速构建App完成监控。希望通过阿里云IoT提供的从设备端到云端应用的全套解决方案,快速帮助智能设备厂商,构建出可以替代人力的自动化人体测温设备和方案,在防控中降低人员接触风险,提升排查效率。
快速开发一个带APP的红外体温检测枪(基于AliOS Things Inside的Wi-Fi模组)
|
物联网 C# Windows
张高兴的 Windows 10 IoT 开发笔记:HC-SR04 超声波测距模块
  HC-SR04 采用 IO 触发测距。下面介绍一下其在 Windows 10 IoT Core 环境下的用法。   项目运行在 Raspberry Pi 2/3 上,使用 C# 进行编码。     1.
1335 0
|
索引
艾伟:WM有约(二):配置信息
Written by Allen Lee   添加配置文件 首先,向项目添加一个Options.xml文件,这个文件将会用来储存应用程序的配置信息: 图 1 接着,把Options.xml的Copy to Output Directory属性的值改为Copy if newer: 图 2 然后,就是为Options.
851 0
|
传感器 物联网 Windows
张高兴的 Windows 10 IoT 开发笔记:红外温度传感器 MLX90614
  GitHub : https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/MLX90614
1731 0