質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C#

    7121questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

楕円体フィッティングによるセンサキャリブレーションについて

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 543

takano20771

score 49

現在,加速度センサ・地磁気センサの計測値を楕円体へのフィッティングを行う事で,オフセットと感度補正を行おうとしています.回転を含まない楕円体の式を以下のように定義して,最小二乗法を使って解こうとしています.

(x - p)^2 / a^2 + (y - q)^2 / b^2 + (z - r)^2 / c^2 = 1

上記の式を,展開し,一般形(?)に変形しました.

Ay^2 + Bz^2 + Cx + Dy + Ez + F = 0

この左辺を二乗したものを評価関数としてA~Fで偏微分し,以下のような式が続く連立方程式としてA~
Fを求められるプログラムを書きました.
Σ(Ay^4 + By^2z^2 + Cxy^2 + Dy^3 + Ey^2z + Fy^2)= -Σx^2y^2

ソースが以下です.

    public class Fitting {
        private Matrix matrix = new Matrix(6, 6);
        private double[] right = new double[6];

        /// <summary>
        /// 与えられた計測値セットの数を取得する
        /// </summary>
        public int Samples { get; private set; } = 0;

        /// <summary>
        /// 与えられた計測値を元に方程式のパラメータを更新する
        /// </summary>
        /// <param name="args">3軸のセンサ計測値</param>
        public void Update(double[] args) {
            // 有効な引数かチェック
            if (args.Length != 3) {
                throw new ArgumentException();
            }

            // 計測値セット数の加算
            this.Samples++;

            // 方程式のパラメータを更新する
            var common = new double[6];
            common[0] = Math.Pow(args[1], 2);
            common[1] = Math.Pow(args[2], 2);
            common[2] = args[0];
            common[3] = args[1];
            common[4] = args[2];
            common[5] = 1;

            for (int i = 0; i < 6; i++){
                for (int j = 0; j < 6; j++){
                    this.matrix[i, j] += common[i] * common[j];
                }

                this.right[i] -= common[i] * Math.Pow(args[1], 2);
            }
        }

        /// <summary>
        /// これまでの入力から楕円体のパラメータを計算して返す
        /// </summary>
        public double[] ComputeCoefficient(){
            // 引数が有効かをチェック
            if(this.matrix.Rows != 6 || this.right.Length != 6){
                throw new ArgumentException();
            }

            // 逆行列を計算し,逆行列がなければ例外を投げる
            if(!this.matrix.Inverse(out Matrix inv)){
                throw new ArithmeticException();
            }

            // 連立方程式の解を求める
            var result = new double[6];
            for (int i = 0; i < 6; i++){
                for (int j = 0; j < 6; j++){
                    result[i] += inv[i, j] * this.right[j];
                }
            }

            var A = result[0];
            var B = result[1];
            var C = result[2];
            var D = result[3];
            var E = result[4];
            var F = result[5];

            var p = -C / 2;
            var q = -D / (2 * A);
            var r = -E / (2 * B);

            var a = Math.Sqrt(p * p + A * q * q + B * r * r - F);
            var b = Math.Sqrt(a * a / A);
            var c = Math.Sqrt(a * a / B);

            return new double[] { p, q, r, a, b, c };
        }
}

Main関数では,7点以下のデータセットをそれぞれUpdateに放り込み,
ComputeCoefficientでパラメータ計算を行っております.

x y z
1     0     1.572792206
0     1     3.033130074
0     0     3.269848481
0.2     0.7     3.189204043
1     0.4     1.572792206
0.2     0.2     3.284962311
0.9     0.1     2.093739111

パラメータとしては,もともと
a = 1, b = 2, C = 3, p = 0.1, q = 0.2, r = 0.3
として,与えており,そこから導出されるデータセットなので,誤差もほぼ無く求められるのではないかと思っているのですが,全く異なるパラメータが計算される状況となっております.

考え方やソースコードでどこか誤りはありますでしょうか.
一応,連立方程式は検算を行い,正しい計算結果が得られることを確認しました.

また,データセットについても入力間違いが存在していないことを確認しております.

Matrixクラスについては,自前で実装しており,余因子展開をつかって逆行列を求めるように実装しております.

または,もっと簡単な方法がございましたら,お教え頂けると幸いです.
よろしくお願いいたします.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

原因は解明しきれませんでしたが,自己解決いたしました.

http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/tech91.html

こちらのURLで解説されている式を用いたところ,それらしき値を得られ,特に,回転成分(xy, yz, xzの項)を0としてプログラムしてみたところ,うまく行きました.展開式としては,質問欄のA~Fを置き換え,以下のようにしたものと成っております.

Ax^2 + By^2 + Cz^2 + Dx + Ey + Fz = 1

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

(x - p)^2 / a^2 + (y - q)^2 / b^2 + (z - r)^2 / c^2 = 1
上記の式を,展開し,一般形(?)に変形しました.
Ay^2 + Bz^2 + Cx + Dy + Ez + F = 0 

x^2項どっか行っちゃってます。


行列計算は自分で実装するよりライブラリ使ったほうが楽です。
.NETならMath.NETなど

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    arduinoと温度センサ

    arduinoと温度センサ arduinoで温度センサを自作しようと考えています。 そこで、7セグLED温度センサのPICをarduinoで代用出来ないかと考えました。マイコン→A

  • 解決済

    xamarin.forms xamlのEntryの枠の消し方(iPhone)

    タイトルに有りますようにxamarin.formsにてxamlのEntryにiPhoneだと枠が出てしまいます。 Effectを使用して、消そうとしましたが消えません。 Effec

  • 解決済

    機械学習のためのデータセット作成

    前提・実現したいこと テキストデータからtf-idf値が一定値以上の単語を抜き出し、そのデータをデータセットとして機械学習モデルに渡し、ジャンルを出力させるプログラムを作成したいと

  • 解決済

    Texture2Dをななめに切り出す方法

    Texture2Dをななめに切り出す方法を探しています。 4点を基準に画像を切り取る関数などはないでしょうか? GetPixelsの引数も一つの座標と幅、高さしかないためどう斜めに

  • 解決済

    Unity2Dでクリックしたオブジェクトの座標を取得したい

    前提・実現したいこと Unity2Dでドラッグ&ドロップではめていくパズルゲームを作成中です。 現在、パズルが出てくるスポーンが一つだけなのですが、三つに増やしたいと考えてお

  • 解決済

    WPF 複数の動画を順番に再生したい

    お世話になっております。 行いたいこと 動画を順番に再生したいと思っています。 仕様 ・再生したい動画を指定(動画1,動画2,動画3,…,動画N)→ボタンを押す→新しいウィ

  • 解決済

    C#+SeleniumでStaleElementReferenceError

    C#でSeleniumを使用して自動化処理を書いています。 (ブラウザはChromeです。) OS: Windows10 IDE: Visual Studio 2015 Sel

  • 解決済

    javaでHTMLファイルを分析

    javaでHTMLのファイルを読みだして財務分析をして流動比率というものを調べたいのですが普通に計算したほうが早いのはわかっているのですが、javaでやりたいです! これは読み

同じタグがついた質問を見る

  • C#

    7121questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。