6

我正在开发一个 AS3 AIR for Android 应用程序。“我的问题是:给定 GPS 位置,我想检索运动方向(北、西北、西、西南、南、东南、东、东北)”

我想要如何使用 2 个不同的 GPS 读数来推断行进方向的代码。然后,我想将该数据用于 360 度。

我想我了解如何获得大致的方向,例如北、南、东和西。我会得到 2 个单独的 GPS 读数并比较类似的东西......

查看在第 1 次或第 2 次 GPS 读数中 X 是否更大。查看在第 1 次或第 2 次 GPS 读数中 Y 是否更大。从这里我应该可以看到大方向。比较 X1 和 X2 的差异与 Y1 和 Y2 的差异。然后您可以看到用户最常朝哪个方向前进。然后显示方向。

我不确定如何获取数据并将其用于像指南针一样的 360 度解释……有人可以帮忙吗?

工作守则------------------------------------------------ -------------------------------------------

package 

{
import flash.display.Sprite;
// Geolocation sensor stuff
import flash.sensors.Geolocation; 
import flash.events.GeolocationEvent;
//Timer setup stuff for setting frequesncy of GPS Update
import flash.utils.Timer;
import flash.events.TimerEvent;

// Sprite and Textfield display
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;


    public class FlashTest extends Sprite 

    {
        //Variable to check if current or prior Geolocation Event fired
        private var gpsCheck:int = 1;
        public var dLon:Number


        //latitude and longitude in degrees (RAW info from Geolocation)
        public var gpsLat1:Number
        public var gpsLon1:Number
        private var gpsLat2:Number
        private var gpsLon2:Number
        public var bearing:Number


        // Latitude and longitude in radians converted from Degrees
        public var gpsLat1R:Number
        public var gpsLon1R:Number
        private var gpsLat2R:Number
        private var gpsLon2R:Number     
        private var yy:Number  
        private var xx:Number          


        public function FlashTest() 

        {
            // Text box for displaying results
            var my_txt:TextField = new TextField();
                my_txt.wordWrap=true; 
                my_txt.width = 300;
                my_txt.height = 300;
                 addChild(my_txt);

            /*
            //If GPS is on device create Geolocation object named "my_geo"
            //Request updates from my_geo every 2000 milliseconds. Run onGeoUpdate function
            //when Event is triggered. After that create the text box for displaying data.
            if (Geolocation.isSupported)
            {
                var my_geo:Geolocation = new Geolocation();
                my_geo.setRequestedUpdateInterval(2000);                
                my_geo.addEventListener(GeolocationEvent.UPDATE, onGeoUpdate);
                var my_txt:TextField = new TextField();
                my_txt.wordWrap=true; 
                my_txt.width = 300;
                my_txt.height = 300;
                addChild(my_txt);
            } 
            // If GPS is not supported on device display "No GPS Signal" 
            else
            {
                addChild(my_txt);
                my_txt.wordWrap=true; 
                my_txt.width = 300;
                my_txt.height = 300;
                addChild(my_txt);
                my_txt.text = "No GPS Signal ";
            }
            */


            // False GPS reading being passed for testing 
            //COMMENT THESE LINES OUT STARTING HERE---
                gpsLat1 =  42.1234584;
                gpsLon1 = -83.1234577;
                gpsLat2 =  42.1234583;
                gpsLon2 = -83.1234577;
           // END OF WHAT SHOULD BE COMMENTED OUT---

           // Equations to convert all RAW Geolocation information over to radians 
                gpsLat1R = gpsLat1 * Math.PI / 180;
                gpsLon1R = gpsLon1 * Math.PI / 180;
                gpsLat2R = gpsLat2 * Math.PI / 180;
                gpsLon2R = gpsLon2 * Math.PI / 180;
          // The rest of the math     
                dLon = gpsLon1 - gpsLon2;
                yy = Math.sin(dLon) * Math.cos(gpsLat2R);
                xx = Math.cos(gpsLat1R) * Math.sin(gpsLat2R) - Math.sin(gpsLat1R) * Math.cos(gpsLat2R) * Math.cos(dLon);
                bearing = Math.atan2(yy, xx) * 180 / Math.PI;
         // Run The Geoupdate function                
            onGeoUpdate();


        // onGeoUpdate basically displays the information that was collected and converted.
        // This is where you will put what you want the code to do with the results
            function onGeoUpdate():void
            {
            my_txt.text = "My Latitude is "+gpsLat1+ " and my Longitude is "+gpsLon1+ 
            "My 2nd Latitude is "+gpsLat2+" and my 2nd Longitude is "+gpsLon2+ 
            " Bearing is " +bearing;

            }            
        }
    }
}
4

3 回答 3

6

您需要的公式(两个点的lon1lon2经度和lat1lat2纬度)在许多地方都有给出 - 例如,在http://www.movable-type.co.uk/scripts/latlong.html。数学是这样的(将其转换为您喜欢的语言......):

dLon = lon2 - lon1;
y = sin(dLon) * cos(lat2);
x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) *cos(dLon);
bearing = atan2(y, x) * 180 / Pi;

注意atan2将结果减少到 [-pi, pi] 之间的值。乘以180/pi数字后将在 [-180,180] 之间。为了获得 0 到 360 之间的值,您可以这样做,例如:

if (bearing < 0) bearing += 360;

我希望您可以填写为您完成这项工作所需的任何其他详细信息。

编辑我用你给的数字写了一点代码:这是 Matlab,但它应该很容易阅读:

% bearings
lat1 = 42.1234584;
lat2 = 42.1234583;
lon1 = -83.1234577;
lon2 = -83.1234510;

% convert to radians:
g2r = pi/180;
lat1r = lat1 * g2r;
lat2r = lat2 * g2r;
lon1r = lon1 * g2r;
lon2r = lon2 * g2r;
dlonr = lon2r - lon1r;
y = sin(dlonr) * cos(lat2r);
x = cos(lat1r)*sin(lat2r) - sin(lat1r) * cos(lat2r)*cos(dlonr);

% compute bearning and convert back to degrees:
bearing = atan2(y, x) / g2r;

fprintf(1,'x: %+.3e\ny: %+.3e\nbearing: %.3f\n', x, y, bearing);

这导致输出:

x: -1.745e-09
y: +8.673e-08
bearing: 91.153

如您所见,x它们y很小-它们代表您移动的“地球圆周的一部分”(似乎向东大约 3.5 米......)。您应该能够使用这些数字调试您的实现。

请注意,GPS 的“绝对”精度可能很差(在您的情况下,不确定性 > 100 m),但“相对”精度仍然很好(它测量两个位置之间的差异远优于 100 m)。

于 2013-08-29T20:55:09.510 回答
2

如果您使用的是 Location API,那么当您的位置更改时,您会收到一个回调,为您提供一个Location对象,您可以获得bearing从 0-360 度移动的方向

于 2013-08-29T20:47:07.483 回答
0

我使用了“面包屑”解决方案。

我将child mc 添加到我当前的位置。当我搬家时,新的 mc 与以前的 mc 进行了比较。

所以首先我在固定地图上找到我的坐标,然后找到我的“你在这里”。然后在我移动时放置面包屑......然后比较这些面包屑以找到航向。

// geolocation
function onGeoUpdate(event:GeolocationEvent):void{

MapHolder.Star.x = MapHolder.Map.x + (event.longitude - (Min_Longitude)) / ((Max_Longitude) - (Min_Longitude)) * 940;
MapHolder.Star.y = MapHolder.Map.y + 800 - (event.latitude - Min_Latitude) / (Max_Latitude - Min_Latitude) * 800;

/// then create new and previous
var  MapHolderStarxold = MapHolder.Star.x;
var  MapHolderStaryold = MapHolder.Star.y;

///breadcrumbs
        var randomMc:Number = Math.floor(Math.random()*myArray.length);
        var mc:MovieClip =  new myArray[randomMc];
        MapHolder.addChild(mc);

         mc.x = MapHolder.Star.x;
         mc.y = MapHolder.Star.y;

         MapHolder.dirArrow.x = MapHolderStarxold;
         MapHolder.dirArrow.y = MapHolderStaryold;


   //// MapHolder.Star point   
        // find out mouse coordinates to find out the angle
var cyB:Number = mc.y - MapHolder.dirArrow.y; 
var cxB:Number = mc.x - MapHolder.dirArrow.x;
// find out the angle
var RadiansB:Number = Math.atan2(cyB,cxB);
// convert to degrees to rotate
var DegreesB:Number = RadiansB * 180 / Math.PI;
// rotate
MapHolder.dirArrow.rotation = DegreesB; }
于 2013-10-21T17:25:41.423 回答