zoukankan      html  css  js  c++  java
  • WMGPS开发[轉]

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

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

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

    开发GPS有3种选择:
    1。直接使用串口连接GPS接收器
    2。GPS Intermediate Driver
    2。使用第三方类库(目前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, 00null);
             deviceStateChangedHandle 
    = CreateEvent(IntPtr.Zero, 00null);
             stopHandle 
    = CreateEvent(IntPtr.Zero, 00null);

             gpsHandle 
    = GPSOpenDevice(newLocationHandle, deviceStateChangedHandle, null0);

             
    // 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

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

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

     

    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;
            t2 
    = x;
            s2 
    = 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不稳定导致。

    程序下载:GPSSystem.rar
    运行环境:VS2008
    + WM6.0 + .net cf2.0
    Author:AppleSeeker(冯峰)
    Date:2009-05-30

  • 相关阅读:
    centos7 /etc/rc.local需要chmod +x /etc/rc.d/rc.local
    epel源
    yum 源
    socket
    CentOS 7使用systemctl如何补全服务名称
    keepalive脑裂的处理,从节点发现访问的虚拟IP就报警,同时尝试发送内容到主节点服务器关闭keepalive和nginx,或者关机
    nginx的 keepalive_timeout参数是一个请求完成之后还要保持连
    kickstart安装步骤
    kickstart
    因客户机IP与服务器IP不在同一网段导致无盘客户机开机卡tftp,提示:PXE-E11: ARP timeout
  • 原文地址:https://www.cnblogs.com/ronli/p/1735141.html
Copyright © 2011-2022 走看看