5

私は問題を解決する助けを必要としています。問題は私の小さなロボット実験の1つで発生しました。基本的な考え方は、各小さなロボットが自分自身からオブジェクトまでの距離を概算する能力を持っているということです。取得が非常に粗いので、もっと正確なものを計算したいと思っています。

だから:
入力:頂点のリスト(v_1, v_2, ... v_n)、頂点v_*(ロボット)
出力:未知の頂点v_*(オブジェクト)の座標

の各頂点v_1v_n座標はよく知られており(呼び出しによって提供されgetX()getY()頂点上にあります)、v_*呼び出しによっておおよその範囲を取得することができます。getApproximateDistance(v_*)、関数getApproximateDistance()は2つの変数変数を返します。minDistanceおよび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]

データを表示する画像:http://img52.imageshack.us/img52/6414/unavngivetcb.png

上記のデータが作成する図は環の小さなカット(によって制限される)であるため、の近似v_1がより良い可能性があることは明らかですが、それをどのように計算し、おそらくその図内で近似を見つけるのでしょうか(この図はおそらく凹面)?[0.5; 1]v_3

これはMathOverflowに適していますか?

4

3 に答える 3

1

I would go for a simple discrete approach. The implicit formula for an annulus is trivial and the intersection of multiple annulus if the number of them is high can be computed somewhat efficently with a scanline based approach.

For getting high accuracy with a fast computation an option could be using a multiresolution approach (i.e. first starting in low-res and then recomputing in high-res only samples that are close to a valid point.

A small python toy I wrote can generate a 400x400 pixel image of the intersection area in about 0.5 secs (this is the kind of computation that would get a 100x speedup if done with C).

enter image description here

# x, y, r0, r1
data = [(2.0, 2.0, 0.5, 1.0),
        (1.0, 2.0, 0.3, 1.0),
        (1.5, 1.0, 0.3, 0.5)]

x0 = max(x - r1 for x, y, r0, r1 in data)
y0 = max(y - r1 for x, y, r0, r1 in data)
x1 = min(x + r1 for x, y, r0, r1 in data)
y1 = min(y + r1 for x, y, r0, r1 in data)

def hit(x, y):
    for cx, cy, r0, r1 in data:
        if not (r0**2 <= ((x - cx)**2 + (y - cy)**2) <= r1**2):
            return False
    return True

res = 400
step = 16
white = chr(255)
grey = chr(192)
black = chr(0)
img = [black] * (res * res)

# Low-res pass
cells = {}
for i in xrange(0, res, step):
    y = y0 + i * (y1 - y0) / res
    for j in xrange(0, res, step):
        x = x0 + j * (x1 - x0) / res
        if hit(x, y):
            for h in xrange(-step*2, step*3, step):
                for v in xrange(-step*2, step*3, step):
                    cells[(i+v, j+h)] = True

# High-res pass
for i in xrange(0, res, step):
    for j in xrange(0, res, step):
        if cells.get((i, j), False):
            img[i * res + j] = grey
            img[(i + step - 1) * res + j] = grey
            img[(i + step - 1) * res + (j + step - 1)] = grey
            img[i * res + (j + step - 1)] = grey
            for v in xrange(step):
                y = y0 + (i + v) * (y1 - y0) / res
                for h in xrange(step):
                    x = x0 + (j + h) * (x1 - x0) / res
                    if hit(x, y):
                        img[(i + v)*res + (j + h)] = white

open("result.pgm", "wb").write(("P5\n%i %i 255\n" % (res, res)) +
                               "".join(img))

Another interesting option could be using a GPU if available. Starting from a white picture and drawing in black the exterior of each annulus will leave at the end the intersection area in white.

For example with Python/Qt the code for doing this computation is simply:

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)

and the computation part for an 800x800 resolution image takes about 8ms (and I'm not sure it's hardware accelerated).

If only the barycenter of the intersection is to be computed then there is no memory allocation at all. For example a "brute-force" approach is just a few lines of C

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

And on my PC can compute the barycenter with resolution = 100 in 0.08 ms (x=1.50000, y=1.383250) or with resolution = 400 in 1.3ms (x=1.500000, y=1.383308). Of course a double-step speedup could be implemented even for the barycenter-only version.

于 2011-05-29T20:30:15.537 に答える
0

ケースについてはよくわかりませんが、一般的なロボット工学アプリケーションでは、センサーを定期的に読み取り、データを処理します。その場合、ノイズの多いデータに基づいて位置を推定しようとしていますが、これは一般的な問題です。単純な(それほど厳密ではない)方法として、既存の位置を取得して、既知の各ポイントに近づけたり遠ざけたりすることができます。ターゲットまでの測定距離からターゲットまでの現在の距離を引いたものを取り、そのデルタ(エラー)に0から1の間の値を掛けて、推定位置をターゲットに向かって移動します。ターゲットごとに繰り返します。次に、新しい測定セットを取得するたびに繰り返します。乗数はローパスフィルターのような効果があり、値が小さいほど、動きに対する応答が遅くなり、より安定した位置推定が可能になります。距離については、最小値と最大値の平均を使用します。1つのターゲットまでの範囲をより狭くすることができる場合は、そのターゲットだけの乗数を1に近づけることができます。

もちろん、これは大まかな位置推定器です。数学の人はおそらくもっと厳密かもしれませんが、もっと複雑になることもあります。解決策は、交差する領域や幾何学的形状の操作とはまったく関係ありません。

于 2011-06-01T14:21:42.910 に答える