从旧的坐标和x和y计算新的坐标

7
我在现实生活中有以下物品的设置:
雷达是静态的,也就是说它总是处于相同的位置。A项可以移动,其位置可以是任何地方。我可以从雷达中读取A与雷达之间的x和y坐标。我编写了以下类来描述每个物品的位置:
public class Position {
    public enum Direction {
        EAST, WEST, NORTH, SOUTH
    };

    public final Direction latitudeDirection, longitudeDirection;
    public final float latitude, longitude, altitude;

    public Position(Direction latitudeDirection, Direction longitudeDirection,
            float latitude, float longitude, float altitude) {
        this.latitudeDirection = latitudeDirection;
        this.longitudeDirection = longitudeDirection;
        this.latitude = latitude;
        this.longitude = longitude;
        this.altitude = altitude;
    }

    public Position(float radarX, float radarY) {
        // TODO: Implement the question here
        this.altitude = Config.RADAR_POSITION.altitude;
    }

}

class Config {
    // Position of the radar
    public static final Position RADAR_POSITION = new Position(
            Position.Direction.NORTH, // Latitude direction
            Position.Direction.EAST, // Longitude direction
            55.0f, // Latitude
            13.0f, // Longitude
            60.0f); // Altitude

    // Facing direction of the radar in degrees. 0° is north, advancing
    // clockwise.
    public static final float RADAR_FACING_DIRECTION = 10.0f;
}

现在给定雷达的地理坐标,相对于雷达的A点的xy坐标,以及雷达相对于北方的朝向,我该如何计算A点的绝对地理坐标?
由于x和/或y的最大值不超过几百米,因此地球的曲率不是问题。

你的问题相当于将图像旋转10度。这方面有很多文献资料。旋转后,您需要添加雷达(原点)的坐标。 - SJuan76
但那是错误的。地理坐标是相对于地球核心的度数。我的雷达坐标只是米。我不能把它们加在一起。 - dimme
1
假设(x,y)是当前坐标“A”。如果您知道雷达相对于地球旋转的角度(theta),则可以轻松找到新坐标(xnew,ynew):xnew = x * cos(theta) - y * sin(theta); ynew = x * sin(theta) + y * cos(theta); - Vishal K
好的,我认为你的问题是关于参考框架的旋转。对于最后一个问题,通用横向墨卡托投影法将东向和北向坐标表示为米。将其转换为UTM坐标系,加上这些值,再转换回地理坐标系即可解决问题。或者,也可以很容易地找到相对纬度每秒经度对应的米数(在所有经度上,纬度秒的长度都是固定的)。 - SJuan76
6个回答

3
作为一个例子,您可以使用三角函数创建三角形来查找A的坐标:
在这种情况下,Ax = (y)(cos 10) - (x)(cos 80),您可以类似地计算出Ay。
这样,您永远不会被度数限制,而是在米制单位中工作。
强大的解决方案是Vishal在OP中发表的评论,当我正在绘制和扫描时发布的。
xnew = x * cos(theta) - y * sin(theta); 
ynew = x * sin(theta) + y * cos(theta);

2
一般来说,您可以按照以下步骤进行:
  1. 将雷达位置(纬度、经度、高度)转换为以米为单位的地心坐标系(ECEF)
  2. 然后可以在该度量系统中使用/组合任何描述雷达旋转和物体位置的旋转和平移参数/矩阵
  3. 将新获取的xzy坐标返回到纬度/经度/高度
有许多资源可用于此类转换,请查看此链接:http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf 如果需要的话,还可以引入场景坐标系(ENU)。这是一个相当好的概述,描述了UTM、ECEF、ENU和大地坐标(纬度/经度/高度)之间的关系:http://www.dirsig.org/docs/new/coordinates.html 如果您需要ECEF与大地坐标转换的示例代码,请查看matlab代码http://www.mathworks.de/de/help/map/ref/ecef2geodetic.html,或使用像GDAL(http://www.gdal.org/)这样的库。


1
我认为可以通过以下方式实现:将 xy 坐标转换为极坐标 rtheta(以雷达为原点)。减去雷达的旋转角度,再转回笛卡尔坐标系。然后只需转换为纬度和经度,并添加雷达的坐标即可。
double r = Math.hypot(radarX, radarY);
double theta = Math.atan2(radarY, radarX);
theta -= Math.toRadians(Config.RADAR_FACING_DIRECTION);
float x = (float) r * Math.cos(theta);
float y = (float) r * Math.sin(theta);
longitude = metersToLongitude(Config.RADAR_POSITION, y) + Config.RADAR_POSITION.longitude;
latitude = metersToLatitude(Config.RADAR_POSITION, x) + Config.RADAR_POSITION.latitude;

我在维基百科上找到了关于纬度和经度一度长度的公式。纬度一度长度在任何地方都相同,但经度在靠近极地的地方会变小。
static float metersToLatitude(Position near, float meters) {
    return meters / 110.6*1000;
}

static float metersToLongitude(Position near, float meters) {
    float lat = Math.toRadians(near.latitude);
    return meters /
        (111132.954 - 559.822 * Math.cos(2*lat) + 1.175 * Math.cos(4*lat));
}

很不幸,这似乎无法运行,我无法弄清原因。
如果您想以正东/西/北/南度表示您的坐标,您还需要检查它们是否为负数,并在这种情况下反转它们和方向。

谢谢。你的回答给了我灵感。你可以在下面找到我用过的代码。 - dimme

1

最终我解决了它。代码如下附上。由于 Samuel Edwin Ward 的回答启发了我,所以我将接受他的答案。

public Position(float radarX, float radarY) {

    // Convert A's position to distance and bearing in relation to the North 
    double objDistance = (Math.hypot(radarX, radarY) / 6367500 /* Mean earth radius */);
    double objBearing = (Math.atan2(radarY, radarX) + Math.toRadians(Config.RADAR_BEARING));

    // Convert the Radar's geographic coordinates to radians
    double latitudeRadar = Math.toRadians(Config.RADAR_POSITION.latitude);
    double longitudeRadar = Math.toRadians(Config.RADAR_POSITION.longitude);

    // Calculate A's geographic coordinates in radians
    double latitudeObject = Math.asin(Math.sin(latitudeRadar)*Math.cos(objDistance) + 
            Math.cos(latitudeRadar)*Math.sin(objDistance)*Math.cos(objBearing));
    double longitudeObject = longitudeRadar + Math.atan2(Math.sin(objBearing)*Math.sin(objDistance)*Math.cos(latitudeRadar), 
            Math.cos(objDistance)-Math.sin(latitudeRadar)*Math.sin(latitudeObject));

    // Normalize to -180 ... +180 degrees
    longitudeObject = (longitudeObject+3*Math.PI) % (2*Math.PI) - Math.PI;  

    // Set the A's coordinates in degrees
    this.latitude = (float) Math.toDegrees(latitudeObject);
    this.longitude = (float) Math.toDegrees(longitudeObject);

    // Set the rest of the arguments
    this.latitudeDirection = Config.RADAR_POSITION.latitudeDirection;
    this.longitudeDirection = Config.RADAR_POSITION.longitudeDirection;
    this.altitude = Config.RADAR_POSITION.altitude;
}

尽快摆脱这些计量单位真是太聪明了。我为什么没想到呢? - Samuel Edwin Ward
这是否足够准确,考虑到地球并非一个球体? - Samuel Edwin Ward
如果您看到经度计算考虑了纬度,那么它适用于椭球体。 - dimme

0

您可以将雷达的所有坐标系旋转-10°,然后只需将雷达的x/y坐标添加到A对象的坐标中即可。


正如我之前所说,那是错误的。地理坐标是相对于地球核心的度数。我的雷达坐标是以米为单位的。我不能将这两个值相加。 - dimme
抱歉,我误解了文本,请让我再想一想 g - D.R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接