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;
}