Math 有限制的三边测量?

Math 有限制的三边测量?,math,distance,triangulation,approximation,trilateration,Math,Distance,Triangulation,Approximation,Trilateration,我需要帮助解决一个问题,这个问题是在我的一个小机器人实验中出现的,基本思想是,每个小机器人都有能力近似计算从它们自己到物体的距离,但是我得到的近似值太粗糙了,我希望能计算出更精确的值 所以: 输入:顶点列表(v_1,v_2,…v_n),顶点v_*(机器人) 输出:未知顶点的坐标v.*(对象) 每个顶点v_1到v_n的坐标都是众所周知的(通过调用顶点上的getX()和getY()来提供),通过调用可以获得到v_*的大致范围getApproximateDistance(v_*),函数getAppro

我需要帮助解决一个问题,这个问题是在我的一个小机器人实验中出现的,基本思想是,每个小机器人都有能力近似计算从它们自己到物体的距离,但是我得到的近似值太粗糙了,我希望能计算出更精确的值

所以:
输入:顶点列表
(v_1,v_2,…v_n)
,顶点
v_*
(机器人)
输出:未知顶点的坐标
v.*
(对象)

每个顶点
v_1
v_n
的坐标都是众所周知的(通过调用顶点上的
getX()
getY()
来提供),通过调用可以获得到
v_*
的大致范围
getApproximateDistance(v_*)
,函数
getApproximateDistance()
返回两个变量,即:
MindDistance
maxDistance
-实际距离就在这两者之间

因此,我一直试图获得
v_*
的坐标,就是使用三边测量法,但是我似乎找不到一个公式来计算有限制的三边测量法(下限和上限),所以这才是我真正想要的(数学不是很好,我自己想出来)

注意:三角测量是一种替代方法吗?
注:我可能很想知道一种方法,性能/准确性权衡

数据示例:

[Vertex . `getX()` . `getY()` . `minDistance` . `maxDistance`]
[`v_1`  .  2       .  2       .  0.5          .  1  ]
[`v_2`  .  1       .  2       .  0.3          .  1  ]
[`v_3`  .  1.5     .  1       .  0.3          .  0.5]
显示数据的图片:

很明显,
v_1
的近似值可能比
[0.5;1]
更好,因为上述数据创建的图形是环空的小切口(受
v_3
限制),但是我如何计算它,并可能在该图形中找到近似值(该图形可能是凹面的)


这是否更适合MathOverflow?

我会从“max/min”切换到尝试最小化错误函数。这就引出了所讨论的问题,这个问题比一系列复杂形状相交更容易处理。(如果一个机器人的传感器出了问题,并且给出了一个不可能的值,那该怎么办?这种变化通常会给出一个合理的答案。)

我会选择一种简单的离散方法。一个环空的隐式公式很简单,如果多个环空的数量较多,则可以使用基于扫描线的方法稍微有效地计算多个环空的交点

为了通过快速计算获得高精度,可选择使用多分辨率方法(即首先在低分辨率下开始,然后在高分辨率下仅重新计算接近有效点的样本)

我编写的一个小型python玩具可以在大约0.5秒内生成一个400x400像素的交叉区域图像(如果使用C,这种计算将获得100倍的加速)

800x800分辨率图像的计算部分大约需要8毫秒(我不确定它是硬件加速的)

如果只计算交叉点的重心,则根本没有内存分配

typedef struct TReading {
    double x, y, r0, r1;
} Reading;

int hit(double xx, double yy,
        Reading *readings, int num_readings)
{
    while (num_readings--)
    {
        double dx = xx - readings->x;
        double dy = yy - readings->y;
        double d2 = dx*dx + dy*dy;
        if (d2 < readings->r0 * readings->r0) return 0;
        if (d2 > readings->r1 * readings->r1) return 0;
        readings++;
    }
    return 1;
}

int computeLocation(Reading *readings, int num_readings,
                    int resolution,
                    double *result_x, double *result_y)
{
    // Compute bounding box of interesting zone
    double x0 = -1E20, y0 = -1E20, x1 = 1E20, y1 = 1E20;
    for (int i=0; i<num_readings; i++)
    {
        if (readings[i].x - readings[i].r1 > x0)
          x0 = readings[i].x - readings[i].r1;
        if (readings[i].y - readings[i].r1 > y0)
          y0 = readings[i].y - readings[i].r1;
        if (readings[i].x + readings[i].r1 < x1)
          x1 = readings[i].x + readings[i].r1;
        if (readings[i].y + readings[i].r1 < y1)
          y1 = readings[i].y + readings[i].r1;
    }

    // Scan processing
    double ax = 0, ay = 0;
    int total = 0;
    for (int i=0; i<=resolution; i++)
    {
        double yy = y0 + i * (y1 - y0) / resolution;
        for (int j=0; j<=resolution; j++)
        {
            double xx = x0 + j * (x1 - x0) / resolution;
            if (hit(xx, yy, readings, num_readings))
            {
                ax += xx; ay += yy; total += 1;
            }
        }
    }
    if (total)
    {
        *result_x = ax / total;
        *result_y = ay / total;
    }
    return total;
}
typedef结构踏步{
双x,y,r0,r1;
}阅读;
智力命中(双xx,双yy,
读数*读数,整数读数)
{
while(num_读数--)
{
双dx=xx-读数->x;
双dy=yy-读数->y;
双d2=dx*dx+dy*dy;
如果(d2<读数->r0*读数->r0)返回0;
如果(d2>读数->r1*读数->r1)返回0;
阅读++;
}
返回1;
}
int计算位置(读取*读数,int num_读数,
int分辨率,
双*结果(x,双*结果(y)
{
//计算感兴趣区域的边界框
双x0=-1E20,y0=-1E20,x1=1E20,y1=1E20;
对于(int i=0;i x0)
x0=读数[i].x-读数[i].r1;
如果(读数[i].y-读数[i].r1>y0)
y0=读数[i]。y-读数[i]。r1;
如果(读数[i].x+读数[i].r1对于(int i=0;i不确定您的情况,但在典型的机器人应用程序中,您将定期读取传感器并处理数据。如果是这种情况,您将尝试根据嘈杂的数据估计位置,这是一个常见问题。简单来说(不太严格)方法,您可以获取现有位置,并将其朝着或远离每个已知点进行调整。将测量到目标的距离减去当前到目标的距离,乘以该差值(误差)通过0和1之间的某个值,并将估计位置向目标移动那么远。对每个目标重复此操作。然后每次获得一组新的测量值时重复此操作。乘法器的效果类似于低通滤波器,较小的值将使您获得更稳定的位置估计,对移动的响应较慢。对于距离,我们e最小值和最大值的平均值。如果可以对一个目标的范围设置更严格的界限,则可以将该目标的乘数增加到更接近1的值


这当然是一个粗糙的位置估计器。数学方面的人可能更严格,但也更复杂。解决方案肯定与相交区域和几何形状无关。

机器人传感器读数会被检查,任何不可用的值都不会被包括在三边测量中。前往math.stackexchange.com-他们会到处都是!即使把图片作为输出很好,我该如何修改它以输出坐标?-正如io分析中所描述的,我的机器人也没有使用gpu硬件运行,很遗憾;)可能平均(重心)是一个原因
img = QImage(res, res, QImage.Format_RGB32)
dc = QPainter(img)
dc.fillRect(0, 0, res, res, QBrush(QColor(255, 255, 255)))
dc.setPen(Qt.NoPen)
dc.setBrush(QBrush(QColor(0, 0, 0)))
for x, y, r0, r1 in data:
    xa1 = (x - r1 - x0) * res / (x1 - x0)
    xb1 = (x + r1 - x0) * res / (x1 - x0)
    ya1 = (y - r1 - y0) * res / (y1 - y0)
    yb1 = (y + r1 - y0) * res / (y1 - y0)
    xa0 = (x - r0 - x0) * res / (x1 - x0)
    xb0 = (x + r0 - x0) * res / (x1 - x0)
    ya0 = (y - r0 - y0) * res / (y1 - y0)
    yb0 = (y + r0 - y0) * res / (y1 - y0)
    p = QPainterPath()
    p.addEllipse(QRectF(xa0, ya0, xb0-xa0, yb0-ya0))
    p.addEllipse(QRectF(xa1, ya1, xb1-xa1, yb1-ya1))
    p.addRect(QRectF(0, 0, res, res))
    dc.drawPath(p)
typedef struct TReading {
    double x, y, r0, r1;
} Reading;

int hit(double xx, double yy,
        Reading *readings, int num_readings)
{
    while (num_readings--)
    {
        double dx = xx - readings->x;
        double dy = yy - readings->y;
        double d2 = dx*dx + dy*dy;
        if (d2 < readings->r0 * readings->r0) return 0;
        if (d2 > readings->r1 * readings->r1) return 0;
        readings++;
    }
    return 1;
}

int computeLocation(Reading *readings, int num_readings,
                    int resolution,
                    double *result_x, double *result_y)
{
    // Compute bounding box of interesting zone
    double x0 = -1E20, y0 = -1E20, x1 = 1E20, y1 = 1E20;
    for (int i=0; i<num_readings; i++)
    {
        if (readings[i].x - readings[i].r1 > x0)
          x0 = readings[i].x - readings[i].r1;
        if (readings[i].y - readings[i].r1 > y0)
          y0 = readings[i].y - readings[i].r1;
        if (readings[i].x + readings[i].r1 < x1)
          x1 = readings[i].x + readings[i].r1;
        if (readings[i].y + readings[i].r1 < y1)
          y1 = readings[i].y + readings[i].r1;
    }

    // Scan processing
    double ax = 0, ay = 0;
    int total = 0;
    for (int i=0; i<=resolution; i++)
    {
        double yy = y0 + i * (y1 - y0) / resolution;
        for (int j=0; j<=resolution; j++)
        {
            double xx = x0 + j * (x1 - x0) / resolution;
            if (hit(xx, yy, readings, num_readings))
            {
                ax += xx; ay += yy; total += 1;
            }
        }
    }
    if (total)
    {
        *result_x = ax / total;
        *result_y = ay / total;
    }
    return total;
}