Skip to content

Commit 28c77d1

Browse files
committed
[Github Pages] update sample04 document.
Add paragraph about scatter plot and solving coord chain.
1 parent 748e2ea commit 28c77d1

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

docs/sample_04_DrawGraph.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ SODLは、簡単な2Dグラフのプロット機能を提供します。
2525
別々のオブジェクトを描画する事ができます。
2626
SODLは描画空間を簡単に追加する機能を提供します。
2727

28+
#### 機能:根本座標系(ワールド座標系)から見た子オブジェクト位置の取得
29+
SODLは、連鎖座標系の末端(あるいは中間)に位置するオブジェクトが、
30+
ワールド座標系原点から見た、どのような位置姿勢に存在しているかを
31+
計算して結果を返す機能を座標系オブジェクトのメソッドとして提供します。
32+
これにより、例えば関節角度を自由に変更した後のロボットハンドの手先位置を
33+
メソッド呼び出しだけで取得する事ができます。
2834

2935
### サンプルコードの解説
3036
サンプルコードは、ロボットを表示する部分については[sample_02_6AxRobot](#sample_02_6AxRobot)と同じです。
@@ -162,6 +168,120 @@ Eigen::Vector3f型の3次元空間上の点をプロットデータに追加す
162168

163169
時系列グラフの説明は以上です。
164170

171+
#### 2. 散布図グラフ
172+
```
173+
//----------------------------------------------------
174+
// 散布図グラフ(2次元)の作成と描画空間[2]への配置
175+
//----------------------------------------------------
176+
// 散布図グラフの作成
177+
auto scttrGrph = sodl::GraphObj::create(
178+
"Mouse Drag Trajectory", // オブジェクト名称 = グラフタイトル
179+
camGrph // 関連付けるカメラ(カメラ投影行列などの設定が済んでいること)
180+
);
181+
// ラベルの設定
182+
scttrGrph->xAxisLabel->text = "X [pix]";
183+
scttrGrph->yAxisLabel->text = "Y [pix]";
184+
// 描画空間[2]にグラフを追加
185+
sodl::drwMngr->AddObjTree_ToDrwSpace(scttrGrph, 2);
186+
```
187+
散布図グラフの作成手順も時系列グラフと同じです。
188+
ビューポートとカメラの追加はコードの引用も省略しています。
189+
差分は、グラフのインスタンスが`TimeSeriesGraph`であるか、`GraphObj`であるか、です。
190+
`TimeSeriesGraph`はデフォルトで古いデータが左に流れて見えなくなるようなプロット範囲をとるのに対し、
191+
散布図で用いている`GraphObj`は、デフォルトで古いデータがいつまでも流れないようなプロット範囲を維持します。だだし、古いデータ自体はやはりメモリの問題でサンプル数が`dataNumMax`を超えると削除されます。
192+
193+
以降は、プロットデータを作成している箇所を見ていきます。
194+
2つの散布図はマウスドラッグ軌跡とロボットの手先の軌跡をそれぞれブロットしています。
195+
196+
##### 2.1 マウスドラッグ軌跡のプロット
197+
```
198+
while(1)
199+
{
200+
201+
(略)
202+
203+
//-----------------------------------------------------
204+
// ドラッグ中のマウス位置X,Yを散布図グラフにプロット
205+
//-----------------------------------------------------
206+
scatterGraph_mouseDrag->addData(Eigen::Vector3f(app::mouse_x, app::mouse_y, 0));
207+
208+
//-----------------------------------------------------
209+
// 描画マネージャから描画更新を実行する
210+
//-----------------------------------------------------
211+
sodl::drwMngr->drawUpdt();
212+
213+
++count;
214+
Sleep(10);
215+
}
216+
217+
```
218+
メインループでは、単に`app::mouse_x`, `app::mouse_y` をプロットに加えているだけです。
219+
これらの変数はグローバル変数で、マウスコールバック関数で更新されています。
220+
コールバック関数を以下に示します。
221+
```
222+
namespace app {
223+
//================================================================
224+
//
225+
// <Summary> GLウィンドウ上でマウスドラッグ時のコールバック
226+
// <Description>
227+
//================================================================
228+
void onMouseDrag(int u, int v)
229+
{
230+
mouse_x = u;
231+
mouse_y = WINDOW_SIZE_Y - v;
232+
}
233+
}
234+
```
235+
いたってシンプルです。
236+
コールバックで得られる値がWindowsのウィンドウ座標系準拠なので
237+
画面左上原点の下方向が(+)の座標値となります。
238+
一方、グラフプロットの座標系は左下原点の上方向が(+)の座標系としたかったので
239+
反転してウィンドウサイズから減算した値を`mouse_y`に代入しています。
240+
241+
他に、マウスボタンを押したときのコールバック関数`onMouseBtn()`
242+
ボタンを押さずにウィンドウ上をにマウスを乗せて移動させたときのコールバック関数
243+
`onMouseHover()`が何もしない関数として実装されています。
244+
245+
##### 2.2 ロボットの手先軌跡のプロット
246+
```
247+
while(1)
248+
{
249+
(略)
250+
251+
//-----------------------------------------------------
252+
// ロボットハンド位置X,Yを散布図グラフにプロット
253+
//-----------------------------------------------------
254+
Eigen::Vector3f handPos = J6_Crd->GetTf_root2self().translation();
255+
scatterGraph_RobotHandXY->addData( handPos );
256+
257+
(略)
258+
259+
//-----------------------------------------------------
260+
// 描画マネージャから描画更新を実行する
261+
//-----------------------------------------------------
262+
sodl::drwMngr->drawUpdt();
263+
264+
++count;
265+
Sleep(10);
266+
}
267+
```
268+
ロボットハンドの手先座標の計算は、メイン関数の中で実装しています。
269+
`Eigen::Vector3f handPos = J6_Crd->GetTf_root2self().translation();`
270+
の一行です。
271+
`J6_Crd`はロボットの手先を表現している座標系オブジェクト(`CoordChainObj`のインスタンス)です。
272+
そして、座標系オブジェクトクラス`CoordChainObj`のメソッドである`GetTf_root2self()`は、
273+
座標系連鎖を親の親の・・・と辿って、
274+
根本までたどり着いた座標系オブジェクトから見た、自分自身までの座標変換
275+
(言い換えると、自分自身の位置姿勢)を表す`Eigen::Affine3f`オブジェクトを返します。
276+
`Eigen::Affine3f`から位置情報だけを取り出す`translation()`をコールして得られた
277+
`Eigen::Vector3f`がワールド座標原点から見たロボットハンドの手先位置として`handPos`
278+
に代入されます。
279+
280+
`CoordChainObj::GetTf_root2self()`は使いこなすと強力な座標変換ツールになります。
281+
また`Eigen::Affine3f`の扱いを理解することは、それ以上に座標変換の実装を楽にしてくれます。
282+
283+
sample_04_DrawGraph の説明は以上です。
284+
165285
[サンプル一覧へ戻る](FunctionExplainedWithSamples.md)
166286

167287
[トップページへ戻る](README.md)

0 commit comments

Comments
 (0)