2009/02/13

距離校正はつらいよ(8)

こんにちは、ソフト班Shinpukuです。

距離校正の話は今日で終わりです。

では、距離校正の実験を始めます。

0.3m~5.0mを計測した結果が下のグラフです。青色の点が1回目(サンプリング)、ピンクの点が2回目(実測値)です。

思い通り。

素晴らしい出来です。

ただ、残念なのは、5m以上のメジャーが無かったことです。

まぁ、でも実際、5m以上離れると「1ピクセル動いたら1メートル」の世界になるので、距離を求めても、おそらく精度はあまり良くないでしょう。

実際はこの様ように映ります
以上で距離校正の話を終わります。

2009/02/12

距離校正はつらいよ(7)

こんにちは、ソフト班Shinpukuです。

まずは下のグラフを見てください。赤が指数近似、青が多項式近似です。



指数近似は距離が離れるにしたがって誤差が大きくなっていくのに対し、多項式近似では遠距離でも安定して近似できています。精度もなかなかのものです。

でも、ちょっと待ってください。

多項式近似の近距離部分、中心からのピクセル数で言うと25ピクセルより前の部分です。

ピクセル数が小さくなっているのにも関わらず、距離が大きくなっています。

ここなんですよ、多項式近似の怖いところは。

この改善についてはいろいろ考えました。

例えば「近・中距離は指数、遠距離は多項式」とか、「指数と多項式の平均」とか。

ですが、どれも理想的な形にならないんですよ。書くコードの量も無駄に増えてしまいうわけですし。

そこでですね、見えない部分にダミーデータを配置するようにしました。さらに、6次多項式にして精度を上げます。

最終的な結果はコチラ↓


す ば ら し い。

キレイな近似曲線が出ています。

コレいけんるんじゃないですか?

2009/02/11

距離校正はつらいよ(6)

こんにちは、ソフト班Shinpukuです。

ここを参考にして作った「n次多項式近似のプログラム」です。

const int num = 16;

double distance[num] = {0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5};

double pixels[num] = { 21, 27, 31, 37, 42, 44, 46, 50, 62, 68, 74, 76, 80, 82, 84, 84, 86};

// n次多項式近似 ///////////////////////////////////////////////////////
const int N = 5; // N-1次の多項式近似
double x[N];
double a[N][N+1];
double b[1][N+1];

for (int i = 0; i < N; i++) {
    for (int j = 0; j < N + 1; j++) {
        a[i][j] = 0.0;
    }
}
for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
        for (int k = 0; k < num; k++) {
            a[i][j] += pow((double)pixels[k], (double)(i + j));
        }
    }
}
for (int i = 0; i < N; i++) {
    for (int j = 0; j < num; j++) {
        a[i][N] += pow((double)pixels[j], (double)i) * distance[j];
    }
}
for (int i = 0; i < N; i++) {
    double m = 0;
    int pivot = i;
    for (int j = i; j < N; j++) {
        if (fabs(a[j][i]) > m) {
            m = fabs(a[j][i]);
            pivot = j;
        }
    }
    if (pivot != i) {
        for(int j = 0; j < N+1; j++) {
            b[0][j] = a[i][j];
            a[i][j] = a[pivot][j];
            a[pivot][j] = b[0][j];
        }
    }
}
for (int k = 0; k < N; k++) {
    double p = a[k][k];
    a[k][k] = 1;
    for (int j = k+1; j < N+1; j++) a[k][j] /= p;
    for (int i = k+1; i < N; i++) {
        double q = a[i][k];
        for (int j = k+1; j < N+1; j++) a[i][j] -= q*a[k][j];
        a[i][k] = 0;
    }
}
for (int i = N-1; i >= 0; i--) {
    x[i] = a[i][N];
    for (int j = N-1; j > i; j--) x[i] -= a[i][j]*x[j];
}
//////////////////////////////////////////////////////////////////////

これで、
r = 中心からのピクセル数
y = x[4]*r*r*r*r+ x[3]*r*r*r+ x[2]*r*r+ x[1]*r+ x[0];
で距離yがでます。

2009/02/10

距離校正はつらいよ(5)

こんにちは、ソフト班Shinpukuです。

まだ距離校正しています。

先日の実験の失敗は、
1. サンプル数が少なかった
2. サンプルを採る位置が悪かった
3. ロボットの位置が悪かった
4. そもそも指数近似の問題ではなかった
なのだと思います。

まずは1.と2.について。

サンプル数を78個。0.3m~8.0mを0.1m間隔で採って見ました。


あれ?サンプル少ない時とあまり変わりませんね

やはり距離が離れるに従って、距離精度が落ちています。

これは仕方がないことなのでしょう。

次は3.についてです。

試行錯誤の結果、ロボットの前方(少し凹んでいる所)にメジャーの9cmを合わせて距離校正を行うと、自己位置がちゃんと出るようになりました。


「自己位置」っていきなり出てきましたけど、これはアレですよ。ロボットの座標です。

距離校正の最終的な目標というのは、ボールの距離がどうのというではなく、白線の距離を正確に求めることなのです。

そういう意味では指数近似では力不足といったところです。

そこで4.なのですよ。

これについては・・・禁断のn次多項式を使うしかありません。

できればこれは使いたくなかった・・・!

理由は後ほど。

2009/02/09

距離校正はつらいよ(4)

こんばんは、ソフト班Shinpukuです。

今日は指数近似を用いた距離校正プログラムの実験です。

でも、その前に・・・

ロボットのカメラが少し傾いていたので、機械班の人に直してもらいました。


さて、距離校正の実験です。


前回と同じく16サンプル採って、理論値と比較してみました。

図中のピンクが距離校正用サンプルで、これを元に近似式を作っています。

その上で、2回目の計測を行ったのが青の点です。

1.0m~3.5mはうまく出ています。

近距離と遠距離がイマイチです。

近距離の精度が悪いのは計測方法が間違っていたのでしょうか?

まぁ、これは何とかなるでしょう。

問題は遠距離です。

誤差0.8mって何ですか?

ていうか遠距離はムリですよ。

解像度240×240ですよ。

ムチャ言わないで下さいよ。

2009/02/08

距離校正はつらいよ(3)

こんにちは、ソフト班Shinpukuです。

指数近似のプログラム書きましたよ。

#include <stdio.h>
#include <math.h>

#define DATA_NUM 17

int main(void)
{
    //距離
    double distance[DATA_NUM] = {0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.5,
                                                                    2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5};

    // 中心からのピクセル数
    double pixels[DATA_NUM] = {21, 27, 31, 37, 42, 44, 46, 50, 62, 68, 74,
                                                               76, 80, 82, 84, 84, 86};

    double X[DATA_NUM], Y[DATA_NUM];
    double sumX, sumX2;
    double sumY, sumXY;

    // XとY初期化
    for (int i = 0; i < DATA_NUM; i++) {
        X[i] = pixels[i];
        Y[i] = log(distance[i]);
        
    }

    // Σたち
    sumX = sumX2 = sumY = sumXY = 0;
    for (int i = 0; i < DATA_NUM; i++) {
        sumX += X[i];
        sumX2 += X[i]*X[i];
        sumY += Y[i];
        sumXY += X[i]*Y[i];
    }

    // 最小2乗計算
    double A1 = (sumX*sumY - DATA_NUM*sumXY)/
                                (sumX*sumX - DATA_NUM*sumX2);

    double A0 = (-sumX2*sumY + sumX*sumXY)/
                                (sumX*sumX - DATA_NUM*sumX2);

    double alpha = exp(A0);
    double beta = A1;

    printf("alpha = %f\n", alpha);
    printf("beta = %f\n", beta);

    return 0;
}

α=0.122702
β=0.042482
と出て、

x=中心からのピクセル数
y = α * exp(β * x)
で距離yが出ます。

2009/02/07

距離校正はつらいよ(2)

こんにちは、ソフト班Shinpukuです。

距離校正の話の続きです。

具体的にどうやって距離を算出するかといいますと、ボール等を用いて、「中心から○○ピクセルの位置は△△メートル」というデータを複数回をサンプリングして近似式を作り、それとカメラ画像を照らし合わせているのです。

こんな感じに↓

以前は職人の手によって調整されていたようです。

しかし、それでは試合に間に合わないので、距離校正の単純化が求められるようになりました。

「サンプル数が少なくても高精度」というやつですか。

夢のような距離校正プログラムですね。

試しにデータを採って見ましょう。

16サンプル採って、Excelに近似曲線を出してもらいました。

指数近似がイイ感じです。

やるじゃないか、Excel。

2009/02/06

距離校正はつらいよ(1)

みなさん、お久しぶりです。

ソフト班Shinpukuです。

新年最初の投稿です。

今更「明けまして~」とか書いても何だか変な気がするので、早速ですが技術的なことをお話します。

ロボットに搭載されている全方位カメラの特性についてです。



オレンジのボールがどの方向にあるかはわかりますよね?

では距離はどうでしょう?

およそ1m、かな?程度にしかわからないと思います。

そう、それなんですよ。

これを解決するのが距離校正なのです。