■ロボットアームと6次元楕円体(その1)
「閑話休題」を書き始めてから,これまでにアップロードしたコラム数は130話を超えた.ネット検索のアクセスカウントもアップしているようであるし,結構いろいろなところで利用されているらしい.なかには,書いた本人が思いも寄らないような使われ方がされている場合もあり,昨年,東大の秦浩司先生(現・ハザマ技術研究所)の研究課題の誤差を評価するために考えだされた「n次元楕円を投影する方法」がいまひょんな所で役に立っている.
秋田大学・工学資源学研究科・ロボティクス・福祉工学講座の佐々木誠先生(makoto@control.mech.akita-u.ac.jp)から伺った話によると,ロボット工学の分野においてはアームの設計,マニピュレータの制御問題,障害物回避問題などがひとつの重要な研究対象になっているのだが,ロボットアームの機能を評価したり,動作を最適に制御するためにはx方向・y方向・z方向の速度,x軸まわり・y軸まわり・z軸まわりの角速度を同時にコントロールしなければならない.
これを「6軸制御」というのだそうだが,その際,6次元楕円が必要になり,コラムに掲げた方法が有用とのことであった.いろいろな使い道があるものだと感心したが,予期せぬ効用の好例といえるだろう.
===================================
【1】予期せぬ効用の発端
さて,事の起こりは,以下のようなメールが届いたことから始まりました.
超楕円体についてネット検索していたところ,『n次元楕円の陰と影』というコラムに行き着きました.実は,現在6次元楕円を描写したいと考えております.A(6×6)の行列をUΣV’に特異値分解すると,Uの要素を主軸方向,Σの要素つまり特異値が半径とする楕円体が描写できるはずです(中略).
なぜ6次元楕円体が必要か? ロボット工学の分野には,ロボットアームの評価法として,可操作性楕円体という概念があります.内容は,qを関節角速度とすると,ユークリッドノルム‖q‖=(q1^2+q2^2+・・・+q6^2)^(1/2)が1以下を満足するようなアーム(7関節)の関節角速度を用いて実現しうる手先速度vの集合がm次元ユークリッドノルム空間内になり,3次元空間における手先の位置と姿勢を考えるとm=6となります.大抵は,アームの関節を減らし,3次元ユークリッドノルム空間にして考えられています.
また,v=Jqという関係式も成り立ち,Jは6×7のヤコビ行列を表します.ヤコビアンに関しては,2次元で扱う場合,手先位置座標を関節角度変数で1階微分したものとなります.3次元(作業空間)で扱う場合,つまり今回の場合は,関節回転軸×(関節点から手先位置への位置ベクトル)および関節回転軸で構成されます.さらに,楕円体はv’J~’J~vが1以下,かつ,vはJの値域に含まれます(’は転置を示す)・・・というようなものです.
ここで,今回の6次元楕円体とは手先の並進と回転の速度vを示します.v1〜v3までは速度(単位m/s),v4〜v6までは角速度(rad/s)となります.よって2次元平面の切り口でみたいというのは,手先の発生しうる速度が手先位置によってどのように変化するか? ある位置で,xyz方向にどの程度の速度を出せるか? というものを表したいのです.
ロボット工学ではこれまで6次元楕円体の描写に関する議論がなされていないこと,それによってロボットアームの手先の自由度が6となるような運動が評価できていなかったのですが,v=JqのJがいまわかっているので,Jを特異値分解してみるという流れで行ってみました.ところが,実際問題,6次元という大きな壁にぶつかり,ご相談している次第であります.ご助言いただければ幸いであります.
===================================
【2】可操作性楕円体と操作力楕円体
次元というのは,独立なパラメータの個数と考えられるので,問題が何次元になろうが驚く必要はありません.
ところで,参考文献:吉川恒夫先生のロボット制御基礎論(コロナ社)によると,いま問題にしているのは「可操作性楕円体」といい,長軸ほど早い速度で動ける方向を表しているとのことでした.
もうひとつ「操作力楕円体」というものがあり,その関係式はτ=J~fで,fは力とモーメントの要素,τは関節に働くトルクを示します.操作力楕円体はf’J~’J~f≦1の楕円体となり,一般に可操作性楕円体と直交するような楕円体になることが知られています.
どちらも数学的な構造は同じものですから,可操作性楕円体,すなわち,v=Jq(q=J~v)のとき,超楕円体
q’q=v’J~’J~v≦1
が描ければよいことになります.
ここで,J~はJのムーア・ペンローズ型一般逆行列(擬似逆行列)ですが,
J~’J~=(JJ’)~
JJ’は正方行列なので,普通の逆行列として扱うことができます.
また,メールには「2次元平面の切り口でみたい」とありますが,どうやらそれは「2次元平面への正射影をみたい」の誤解のようでした.正射影と切り口にそれぞれ統計学上の用語を対応させると,正射影は「相関」に相当するものですが,切り口は「偏相関」すなわち,他の変数の影響を除いた相関の強さを意味しています.それに対して,通常の相関はみかけ上の相関を含んだ全相関を意味しています.
ともあれ,3次元世界で人の顔を映すならば三面鏡で十分なのですが,6次元世界に住む人間では15面鏡(v1-v2,v1-v3,v2-v3などそれぞれのv1〜v6の各組み合わせの2次元平面への正射影)を用いなければ全体像を映し出すことはできません.
また,v1〜v3は速度,v4〜v6は角速度とありますから,ロボットアームの場合,3次元速度空間(v1,v2,v3)あるいは角速度空間(v4,v5,v6)への正射影,さらには3次元空間での切り口を求めることも必要になるものと思われました.
===================================
【3】6次元楕円の赤道面・切り口・正射影を求めるプロシージャ
[1]赤道面
さて,6次元楕円であっても,楕円の赤道面の(vi,vj)平面への正射影を描くことは,単なる座標変換で済みますから,簡単に解決できる問題です.その際の座標変換式は,以下の手順で求めることができます.
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの固有値・固有ベクトルを求める
(4)軸の長さを1/√λとする
ただし,文献にある解説では2次元楕円を2次元平面に描く場合であっても,かなり面倒な方法を使って楕円を求めています.数学的にいえば,簡単なユニタリ変換で済むところをわざわざ難しくしているという感さえあります.そのため,文献の方法はお勧めしませんし,とても6次元楕円の正射影を求められそうにもありません.
[2]切断面
次に,楕円の(vi,vj)平面での切り口の形を描くためには,vi,vj成分以外はすべて0ですから,ヘシアンの固有値・固有ベクトルを求めずとも標準形に直すことができ,簡単に切り口の形を計算できます.
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの小行列(Hij)の固有値・固有ベクトルを求める
(4)軸の長さを1/√λとする
ここで,Hijとは,行列Hに対して添字i,jで指定した行・列を取り出して得られる小行列という意味であって,i行とj列を取り除いたものでないことに注意して下さい.
[3]正射影(輪郭)
それに対して,6次元楕円の(vi,vj)平面への正射影の形を求めることはそれほど易しい問題ではありません.
われわれが3次元空間内の曲面をみるときは,ちょうど写真を撮るように2次元の面に射影していると考えられます.山を眺めると稜線がみえます.それは接平面が視点を通るような曲面上の点の軌跡を視平面に射影した輪郭なのです.6次元楕円でも本質的な考え方は同じなのですが,法線方向が1つではないので,高次元空間に馴れていないわれわれにとっては計算が複雑になり,簡単にはいかないのです.
しかし,輪郭を求める考え方自体は切り口の求め方によく似ていて,いわば局所的な固有値(?)を2次方程式を解くことによって求めるだけで正射影の計算ができるのです.詳細についてはコラム『n次元楕円の陰と影』をご覧頂きたいのですが,ここで,正射影を求めるプロシージャをまとめておきます.
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの逆行列(V=H~)を求める
(4)逆行列の小行列(Vij)の固有値・固有ベクトルを求める
(5)軸の長さを√λとする
すなわち,正射影を求めるにはヘシアンの固有値・固有ベクトルの計算は不要ですが,逆行列の計算が不可避と考えられました.また,長軸,短軸を固有値の大きさを用いて定めることによって描くことができるのですが,切り口が軸の長さを√λで割ってやるのに対して,正射影では√λを掛けなければなりません.
切り口:順行列の小行列の固有値を求める → 軸の長さを√λで割る
正射影:逆行列の小行列の固有値を求める → 軸の長さに√λを掛ける
以上により,切り口を求めることと正射影を求めることは「表と裏の関係」にあることが理解されます.
===================================
[注]逆行列の固有値
6次元楕円の極や赤道はヘシアンから直接的に固有値と固有ベクトルを計算することによって得られますし,その方が一般的でしょう.しかし,逆行列の固有値は元の行列の逆数となりますし,また,固有ベクトルは変わりませんから,ヘシアンの逆行列を用いても赤道面の正射影を描くことができます.ただし,その手順は長くなってしまいます.
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの逆行列(V=H~)を求める
(4)ヘシアンの逆行列(V=H~)の固有値・固有ベクトルを求める
(5)軸の長さを√λとする
一方,輪郭の計算では,ヘシアンの逆行列の小行列の逆行列を求める必要があり,
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの逆行列(V=H~)を求める
(4)逆行列の小行列(Vij)の逆行列(Vij~)を求める
(5)逆行列(Vij~)の固有値・固有ベクトルを求める
(6)軸の長さを1/√λとする
の手順で描くことができます.これまでの議論からこの方が正攻法の描き方であることがおわかり頂けるでしょう.しかし,正射影を描く場合,
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの逆行列(V=H~)を求める
(4)逆行列の小行列(Vij)の固有値・固有ベクトルを求める
(5)軸の長さを√λとする
とすると手順を1回省くことができるという利点があり,また,切り口と「表と裏の関係」にあることがわかりやすくなるのです.
===================================
[注]統計の立場から
固有値を求め,標準形にするところは簡単にわかると思われますが,それではなぜ正射影の場合,逆行列をとる必要があるのでしょうか?
輪郭の計算は,接平面(法線ベクトル)を求めるという微分幾何学の基本的な知識と線形代数学の方法(ヤコビの公式,シルベスターの定理など)によって説明できるのですが,長くなりますし,証明に興味をお持ちの方も少ないでしょうから,ここではその証明を割愛します.
統計学的にみると,これは「誤差伝播の法則」に基づいているのですが,統計の世界では昔から使われている考え方であって,次のように説明されます.
上記のヘシアンは,フィッシャーの情報行列(Fisher's information matrix)と呼ばれるものに対応していて,この行列の逆行列は,いわゆる分散共分散行列であって,その対角要素はパラメータの精度を与える重要な性質をもっています.
パラメータθiの最尤推定量の分散は
Var[θi]=[I(θ)^(-1)]ii=(Δθi)^2
と表されるのですが,分散共分散行列はすべてのパラメータが独立と考えられる場合は対角行列,また,パラメータ間に強い相関がある場合には非対角要素は無視できなくなり対称行列となります.
すなわちvi方向の拡がりを決定するものが,分散共分散行列なのですが,これによって,たとえば,v1方向の拡がりは主としてv1の誤差に基づくのですが,他の要素v2〜v6の誤差の影響も受ける形に変換されるのです.参考文献として吉沢康和「新しい誤差論」共立出版を掲げておきます.
===================================
【4】プログラム
以下に,6次元楕円の正射影を2次元平面に投影するプログラムを掲げます.このプログラムを実行すると,2次元平面vi-vjへの正射影15画面分の楕円が1枚ずつ次々に表示されますが,15枚まとめて画面に描写するようにした方がいいかもしれません.
1000 '
1010 ' **** robot-arm control ****
1020 ' 2002/01/18 (C) サトウ イクロウ
1030 SCREEN 3,0:CONSOLE ,,0,1
1040 CLS 3:WIDTH 80,25:COLOR 6
1050 GOSUB *INITIALIZE
1060 GOSUB *JACOBIAN
1070 GOSUB *HESSIAN
1080 'GOSUB *ELLIPSOID
1090 '
1100 STAGE$="1":' [contour]
1110 'GOSUB *ELLIPSOID.WF
1120 GOSUB *ELLIPSOID3
1130 '
1140 STAGE$="2":' [section]
1150 'GOSUB *ELLIPSOID.WF
1160 'GOSUB *ELLIPSOID3
1170 '
1180 CLS 3
1190 END
1200 '
1210 ' *** 初期設定 ***
1220 '
1230 *INITIALIZE:
1240 RX=.7:RY=.8:BOX=1:KIND=1:POWER=0
1250 IX=.7:IY=.8:MARK=1:CLR=2:DRAW.COLOR=4
1260 TXT.COLOR=6:GRP.COLOR=5:REF.COLOR=6
1270 SCALE.KIND=1:PLOT=1
1280 PI=3.14159
1290 JX=.709:JY=1
1300 RX=IX*JX:RY=IY*JY
1310 '
1320 M=6
1330 N1=7
1340 '
1350 MMAX=10:NMAX=10
1360 DIM V(MMAX)
1370 DIM JACOBI(MMAX,NMAX)
1380 DIM AZ(MMAX,MMAX),BZ(MMAX,MMAX)
1390 DIM HESSE(MMAX,MMAX)
1400 DIM COV(MMAX,MMAX)
1410 DIM VO(MMAX),VL(MMAX)
1420 DIM VD(MMAX),VS(MMAX)
1430 DIM UNIT$(MMAX)
1440 '
1450 FOR I=1 TO 3
1460 VO(I)=0:VL(I)=.5
1470 VD(I)=5:VS(I)=1
1480 UNIT$(I)="m/s"
1490 NEXT I
1500 FOR I=4 TO 6
1510 VO(I)=0:VL(I)=2
1520 VD(I)=4:VS(I)=1
1530 UNIT$(I)="rad/s"
1540 NEXT I
1550 RETURN
1560 '
1570 ' *** ヤコビアンの読み込み ***
1580 '
1590 *JACOBIAN:
1600 RESTORE *J
1610 FOR J=1 TO M
1620 FOR I=1 TO N1
1630 READ JACOBI(J,I)
1640 NEXT I
1650 NEXT J
1660 '
1670 RESTORE *V
1680 FOR J=1 TO M
1690 READ V(J)
1700 NEXT J
1710 RETURN
1720 '
1730 *J:'[1]
1740 DATA .2084, .0320, .0409,-.0413,-.0032,-.0086, .0033
1750 DATA 0,-.3443, .1829,-.1264,-.0153,-.0227,-.0493
1760 DATA -.3425, .0606,-.1273,-.1929, .0157, .0446,-.0244
1770 DATA 0, .8841, .4161, .1965, .9440,-.3250, .1699
1780 DATA 1, 0, .4550, .8003,-.3106,-.8159, .4470
1790 DATA 0,-.4673, .7873,-.5664,-.1115,-.4782,-.8782
1800 '
1810 *V:'[1]
1820 DATA -.0013
1830 DATA -.0020
1840 DATA -.0005
1850 DATA .0007
1860 DATA -.0506
1870 DATA -.0119
1880 '
1890 '*J:'[20]
1900 DATA .3063,-.1201, .1035, .1037,-.0128,-.0019, .0373
1910 DATA 0,-.1692, .2014,-.2040,-.0076,-.0405,-.0248
1920 DATA -.1289, .1619,-.1761,-.1737, .0217, .0301,-.0311
1930 DATA 0, .8031,-.4195, .3965, .8705, .3581, .0393
1940 DATA 1, 0, .7101, .7037,-.0844,-.5671, .8029
1950 DATA 0, .5958, .5655,-.5896, .4848,-.7418,-.5948
1960 '
1970 '*V:'[20]
1980 DATA -.6581
1990 DATA .0862
2000 DATA .1687
2010 DATA .5254
2020 DATA -1.1528
2030 DATA .7858
2040 '
2050 ' *** ヘシアンと共分散行列 ***
2060 '
2070 *HESSIAN:
2080 FOR M1=1 TO M
2090 FOR M2=M1 TO M
2100 S=0
2110 FOR I=1 TO N1
2120 S=S+JACOBI(M1,I)*JACOBI(M2,I)
2130 NEXT I
2140 AZ(M1,M2)=S:AZ(M2,M1)=S
2150 COV(M1,M2)=S:COV(M2,M1)=S
2160 NEXT M2
2170 NEXT M1
2180 NZ=M
2190 '
2200 GOSUB *INVERSE
2210 '
2220 FOR I=1 TO M
2230 FOR J=1 TO M:HESSE(I,J)=BZ(I,J):NEXT J
2240 NEXT I
2250 RETURN
2260 '
2270 ' ** 逆行列 ( AZ==>BZ ) **
2280 '
2290 *INVERSE:' [GAUSS-JORDAN]
2300 FOR I=1 TO NZ
2310 FOR J=1 TO NZ:BZ(I,J)=0:NEXT J
2320 BZ(I,I)=1
2330 NEXT I
2340 FOR I=1 TO NZ
2350 IZ=I
2360 IF AZ(I,I)=0 THEN 2370 ELSE 2430
2370 IZ=IZ+1:IF IZ>NZ THEN RZ=1:RETURN
2380 IF AZ(IZ,I)=0 THEN 2370
2390 FOR J=1 TO NZ
2400 SWAP AZ(I,J),AZ(IZ,J)
2410 SWAP BZ(I,J),BZ(IZ,J)
2420 NEXT J
2430 AII=AZ(I,I)
2440 FOR J=1 TO NZ
2450 AZ(I,J)=AZ(I,J)/AII
2460 BZ(I,J)=BZ(I,J)/AII
2470 NEXT J
2480 FOR K=1 TO NZ
2490 AKI=AZ(K,I):IF K=I THEN 2540
2500 FOR J=1 TO NZ
2510 AZ(K,J)=AZ(K,J)-AKI*AZ(I,J)
2520 BZ(K,J)=BZ(K,J)-AKI*BZ(I,J)
2530 NEXT J
2540 NEXT K
2550 NEXT I
2560 RZ=0
2570 RETURN
2580 '
2590 ' *** 楕円体 ***
2600 '
2610 *ELLIPSOID:
2620 IF M=1 THEN RETURN
2630 '
2640 FOR I=1 TO M
2650 FOR J=1 TO M:AZ(I,J)=COV(I,J):NEXT J
2660 NEXT I
2670 NZ=M:GOSUB *JACOBI
2680 '
2690 FOR I=1 TO M-1
2700 FOR J=I+1 TO M
2710 UO=VO(I):UL=VL(I)
2720 VO=VO(J):VL=VL(J)
2730 DU=VD(I):SU=VS(I)
2740 DV=VD(J):SV=VS(J)
2750 '
2760 GOSUB *DRAW.AXIS
2770 GOSUB *DRAW.ELLIPSE
2780 GOSUB *TEMP
2790 NEXT J
2800 NEXT I
2810 RETURN
2820 '
2830 ' ** 固有値 ( AZ==>BZ ) **
2840 '
2850 *JACOBI:' [ EIGEN-VECTOR: BZ(J,I) ]
2860 EPSL=.00001
2870 FOR I=1 TO NZ
2880 FOR J=1 TO NZ:BZ(I,J)=0:NEXT J
2890 BZ(I,I)=1
2900 NEXT I
2910 '
2920 CMAX=0
2930 FOR I=1 TO NZ
2940 FOR J=1 TO NZ
2950 IF CMAX<ABS(AZ(I,J)) THEN CMAX=ABS(AZ(I,J))
2960 NEXT J
2970 NEXT I
2980 EPS=CMAX*EPSL
2990 '
3000 LMAX=100
3010 LOOP=0
3020 SW=0
3030 WHILE LOOP<LMAX AND SW=0
3040 '
3050 FOR L=1 TO NZ-1
3060 FOR I=1 TO NZ-1
3070 J=I+L:IF J>NZ THEN 3260
3080 IF ABS(AZ(I,J))<EPS THEN 3250
3090 DIF=AZ(I,I)-AZ(J,J)
3100 IF DIF=0 THEN T=PI/4 ELSE T=1/2*ATN(2*AZ(I,J)/DIF)
3110 C=COS(T):S=SIN(T)
3120 FOR K=1 TO NZ
3130 A1=AZ(I,K):A2=AZ(J,K)
3140 AZ(I,K)= C*A1+S*A2
3150 AZ(J,K)=-S*A1+C*A2
3160 NEXT K
3170 FOR K=1 TO NZ
3180 A1=AZ(K,I):A2=AZ(K,J)
3190 AZ(K,I)= C*A1+S*A2
3200 AZ(K,J)=-S*A1+C*A2
3210 B1=BZ(K,I):B2=BZ(K,J)
3220 BZ(K,I)= C*B1+S*B2
3230 BZ(K,J)=-S*B1+C*B2
3240 NEXT K
3250 NEXT I
3260 NEXT L
3270 '
3280 SW=1
3290 FOR I=1 TO NZ-1
3300 FOR J=I+1 TO NZ
3310 IF ABS(AZ(I,J))>EPS THEN SW=0
3320 NEXT J
3330 NEXT I
3340 LOOP=LOOP+1
3350 '
3360 WEND
3370 RZ=0
3380 RETURN
3390 '
3400 ' *** 正射影 ***
3410 '
3420 *DRAW.ELLIPSE:
3430 'DRAW.COLOR=4
3440 WUO=UO-UL:WUL=UO+UL
3450 WVO=VO-VL:WVL=VO+VL
3460 WINDOW(WUO,-WVL)-(WUL,-WVO)
3470 VIEW(SX1,SY1)-(SX2,SY2)
3480 '
3490 GOSUB *POLAR
3500 'GOSUB *EQUATOR
3510 'GOSUB *SECTION
3520 GOSUB *CONTOUR
3530 '
3540 WINDOW(0,0)-(639,399)
3550 VIEW(0,0)-(639,399)
3560 RETURN
3570 '
3580 ' *** 輪郭 ***
3590 '
3600 *CONTOUR:
3610 GOTO 3830
3620 '
3630 S1=COV(I,I)
3640 S2=COV(J,J)
3650 S3=COV(I,J)
3660 LAMBDA1=(S1+S2+SQR((S1-S2)*(S1-S2)+4*S3*S3))/2
3670 LAMBDA2=(S1+S2-SQR((S1-S2)*(S1-S2)+4*S3*S3))/2
3680 'LAMBDA2=(S1*S2-S3*S3)/LAMBDA1
3690 T=1:' [non-stochastic]
3700 AAA=SQR(T*LAMBDA1)
3710 BBB=SQR(T*LAMBDA2)
3720 IF S3=0 THEN CCC=PI/2 ELSE B3=(S2-S1+SQR((S1-S2)*(S1-S2)+4*S3*S3))/2/S3:CCC=ATN(B3)
3730 'IF S3=0 THEN CCC=PI/2 ELSE B3=(LAMBDA1-S2)/S3:CCC=ATN(B3)
3740 '
3750 G=0
3760 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
3770 GX=AAA*COS(ANGLE)*COS(CCC)-BBB*SIN(ANGLE)*SIN(CCC)+VO(I)
3780 GY=AAA*COS(ANGLE)*SIN(CCC)+BBB*SIN(ANGLE)*COS(CCC)+VO(J)
3790 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
3800 LINE-(GX,-GY),DRAW.COLOR
3810 NEXT ANGLE
3820 RETURN
3830 '
3840 DIF=COV(I,I)-COV(J,J)
3850 IF DIF=0 THEN TH=PI/4 ELSE TH=1/2*ATN(2*COV(I,J)/DIF)
3860 C=COS(TH):S=SIN(TH)
3870 '
3880 LAMBDA1=COV(I,I)*C*C+2*COV(I,J)*C*S+COV(J,J)*S*S
3890 LAMBDA2=COV(I,I)*S*S-2*COV(I,J)*C*S+COV(J,J)*C*C
3900 T=1:' [non-stochastic]
3910 AAA=SQR(T*LAMBDA1)
3920 BBB=SQR(T*LAMBDA2)
3930 '
3940 G=0
3950 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
3960 GX=AAA*COS(ANGLE)*C-BBB*SIN(ANGLE)*S+VO(I)
3970 GY=AAA*COS(ANGLE)*S+BBB*SIN(ANGLE)*C+VO(J)
3980 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
3990 LINE-(GX,-GY),DRAW.COLOR
4000 NEXT ANGLE
4010 RETURN
4020 '
4030 ' *** 極線 ***
4040 '
4050 *POLAR:
4060 FOR K=1 TO M
4070 T=1:' [non-stochastic]
4080 RRR=SQR(T*AZ(K,K))
4090 GX=BZ(I,K)*RRR
4100 GY=BZ(J,K)*RRR
4110 GX1= GX+VO(I):GY1= GY+VO(J)
4120 GX2=-GX+VO(I):GY2=-GY+VO(J)
4130 LINE(GX1,-GY1)-(GX2,-GY2),7
4140 IF K=I OR K=J THEN LINE(GX1,-GY1)-(GX2,-GY2),CLR
4150 NEXT K
4160 RETURN
4170 '
4180 ' *** 赤道 ***
4190 '
4200 *EQUATOR:
4210 T=1:' [non-stochastic]
4220 AAA=SQR(T*AZ(I,I))
4230 BBB=SQR(T*AZ(J,J))
4240 '
4250 G=0
4260 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
4270 GX=AAA*COS(ANGLE)*BZ(I,I)+BBB*SIN(ANGLE)*BZ(I,J)+VO(I)
4280 GY=AAA*COS(ANGLE)*BZ(J,I)+BBB*SIN(ANGLE)*BZ(J,J)+VO(J)
4290 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
4300 LINE-(GX,-GY),DRAW.COLOR
4310 NEXT ANGLE
4320 RETURN
4330 '
4340 ' *** 断面 ***
4350 '
4360 *SECTION:
4370 DIF=HESSE(I,I)-HESSE(J,J)
4380 IF DIF=0 THEN TH=PI/4 ELSE TH=1/2*ATN(2*HESSE(I,J)/DIF)
4390 C=COS(TH):S=SIN(TH)
4400 '
4410 LAMBDA1=HESSE(I,I)*C*C+2*HESSE(I,J)*C*S+HESSE(J,J)*S*S
4420 LAMBDA2=HESSE(I,I)*S*S-2*HESSE(I,J)*C*S+HESSE(J,J)*C*C
4430 T=1:' [non-stochastic]
4440 AAA=SQR(T/LAMBDA1)
4450 BBB=SQR(T/LAMBDA2)
4460 '
4470 G=0
4480 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
4490 GX=AAA*COS(ANGLE)*C-BBB*SIN(ANGLE)*S+VO(I)
4500 GY=AAA*COS(ANGLE)*S+BBB*SIN(ANGLE)*C+VO(J)
4510 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
4520 LINE-(GX,-GY),DRAW.COLOR
4530 NEXT ANGLE
4540 RETURN
4550 '
4560 ' *** 座標軸 ***
4570 '
4580 *DRAW.AXIS:
4590 CLS 3
4600 SX1=59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360
4610 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
4620 RR=3:GOSUB *X.SCALE2:GOSUB *X.REF2
4630 RR=3:GOSUB *Y.SCALE2:GOSUB *Y.REF2
4640 RR=3:GOSUB *DOT.PLOT
4650 GOSUB *TITLE.BACK2
4660 RETURN
4670 '
4680 ' *** 等分目盛り (X) ***
4690 '
4700 *X.SCALE2:
4710 CU=(SX2-SX1)/DU/2
4720 IF KIND=0 THEN KARA=-RR:MADE=0
4730 IF KIND=1 THEN KARA=0 :MADE=RR
4740 IF KIND=2 THEN KARA=-RR:MADE=RR
4750 FOR K=0 TO DU*2
4760 LINE(CU*K+SX1,SY2+KARA)-(CU*K+SX1,SY2+MADE),GRP.COLOR
4770 LINE(CU*K+SX1,SY1-KARA)-(CU*K+SX1,SY1-MADE),GRP.COLOR
4780 NEXT K
4790 'GOSUB *X.REF2
4800 RETURN
4810 '
4820 ' *** 参照値の記入 (X) ***
4830 '
4840 *X.REF2:
4850 REF.COLOR=6
4860 UW=UL-UO
4870 FOR K=0 TO DU*2 STEP SU
4880 F=UW*(K/DU-1):F$=STR$(F)
4890 IF F>=0 THEN F$=MID$(F$,2)
4900 FL=LEN(F$)
4910 FOR L=1 TO FL
4920 GX=CU*K+59-FL*8/2+(L-1)*8:GY=23*16
4930 PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
4940 NEXT L
4950 NEXT K
4960 RETURN
4970 '
4980 ' *** 等分目盛り (Y) ***
4990 '
5000 *Y.SCALE2:
5010 CV=(SY2-SY1)/DV/2
5020 IF KIND=0 THEN KARA=0 :MADE=RR
5030 IF KIND=1 THEN KARA=-RR:MADE=0
5040 IF KIND=2 THEN KARA=-RR:MADE=RR
5050 FOR K=0 TO DV*2
5060 LINE(SX1+KARA,SY2-CV*K)-(SX1+MADE,SY2-CV*K),GRP.COLOR
5070 LINE(SX2-KARA,SY2-CV*K)-(SX2-MADE,SY2-CV*K),GRP.COLOR
5080 NEXT K
5090 'GOSUB *Y.REF2
5100 RETURN
5110 '
5120 ' *** 参照値の記入 (Y) ***
5130 '
5140 *Y.REF2:
5150 REF.COLOR=6
5160 VW=VL-VO
5170 FOR K=0 TO DV*2 STEP SV
5180 F=VW*(K/DV-1):F$=STR$(F)
5190 IF F>=0 THEN F$=MID$(F$,2)
5200 FL=LEN(F$)
5210 FOR L=1 TO FL
5220 GX=48-FL*8+(L-1)*8:GY=360-CV*K-8
5230 PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
5240 NEXT L
5250 NEXT K
5260 RETURN
5270 '
5280 ' *** プロット ***
5290 '
5300 *DOT.PLOT:
5310 WUO=UO-UL:WUL=UO+UL
5320 WVO=VO-VL:WVL=VO+VL
5330 WX=WUL-WUO
5340 BX=(WUL*SX1-WUO*SX2)/WX
5350 AX=(SX2-SX1)/WX
5360 WY=WVL-WVO
5370 BY=(WVL*SY2-WVO*SY1)/WY
5380 AY=(SY1-SY2)/WY
5390 '
5400 XX=AX*V(I)+BX
5410 YY=AY*V(J)+BY
5420 CIRCLE(XX,YY),RR,1
5430 PAINT(XX,YY),CLR,1
5440 CIRCLE(XX,YY),RR,CLR
5450 RETURN
5460 '
5470 ' *** タイトル ***
5480 '
5490 *TITLE.BACK2:
5500 LX=INT((580*RX+59)/8)
5510 LY=INT(360*(1-RY)/16)
5520 LZ=INT((290*RX+59)/8)
5530 L1$="ellipsoid projection of "
5540 L2$="v"+MID$(STR$(I),2)+"-"
5550 L3$="v"+MID$(STR$(J),2)+" plane"
5560 L$=L1$+L2$+L3$
5570 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
5580 L$=UNIT$(J)
5590 IF LEN(L$)=0 THEN 5610
5600 LOCATE 7,LY-1:PRINT "("+L$+")"
5610 L$=UNIT$(I)
5620 IF LEN(L$)=0 THEN 5640
5630 LOCATE LX+3,21:PRINT "("+L$+")"
5640 '
5650 LOCATE LX+3,LY:PRINT "v components: "
5660 FOR K=1 TO M
5670 V$="v"+MID$(STR$(K),2)+"="
5680 LOCATE LX+3,LY+K+1:PRINT V$;:PRINT V(K)
5690 NEXT K
5700 RETURN
5710 '
5720 *TEMP:
5730 LOCATE 0,24:PRINT "何かキーを押してください";:WHILE INKEY$="":WEND
5740 RETURN
3630行〜3730行では,ヘシアンの逆行列
V=[σx2,σxy]
[σxy,σy2]
の固有方程式(この場合は2次方程式)を解いて,固有値
λ=(σx^2+σy^2±√(σx^2−σy^2)^2+4σxy^2)/2
を求めています.
そのうち,大きいほうの固有値をλ1,小さいほうの固有値をλ2とすると,
λ2=(σx^2σy^2−σxy^2)/ λ1
ですが,主軸a(x−x0)+b(y−y0)=0のaおよびbは,
a=σxy/√{σxy^2 +(λ2 −σx^2)^2}
b=(λ2 −σx^2)/√{σxy^2 +(λ2 −σx^2)^2}
により定めることができます.
しかし,この方法では軸の対応がずれてしまうことが起こり得ます.そのため,3840行〜3920行では,2次方程式を解く代わりに,回転行列
R=[cosθ,−sinθ]
[sinθ, cosθ]
を用いて楕円半径と楕円の配向を定めています.
その際,
R^(-1)VR=R’VR
が対角行列になるようにθを決定するのですが,非対角要素
(σy2−σx2)cosθsinθ+σxy(cos^2θ−sin^2θ)=0
より,
tan2θ=2σxy/(σx2−σy2)
したがって,
θ=1/2arctan(2σxy/(σx2−σy2))
にとればよいことがわかります.
一方,切り口を求める場合は,ヘシアンそのものを用いて同じ計算をしますが,正射影では,*行で軸の長さに√λを掛けているのに対して,切り口では軸の長さを√λで割らなければなりません(4450〜4460行).
===================================
【5】このプログラムの問題点
6次元楕円では実対称行列を扱いますから,固有値はヤコビ法で計算しています.ヤコビ法はすべての固有値・固有ベクトルが同時に求められる,最も実用に適した優れた計算法です.ほかにもいろいろな方法がありますが,理論が難解なもの,計算手順が複雑なもの,プログラム作成が難しいもの,計算時間がかかるもの,収束が確実ではないもの,などが多いのです.
固有値は大きい順に並べ替えて使われることが多いのですが,それでは座標軸との関係が一致しなくなりますから,ロボットアームの問題では軸との対応関係が保たれなければなりません.そこで気がかりなのは固有値計算における対応関係の保持です.
固有値問題の性質として,逆行列の固有値は元の行列の逆数となり,また,固有ベクトルは変わりません.しかし,ここに掲げたプログラムでは,直接ヘシアンから固有値・固有ベクトルを求めた場合(λ1,・・・,λ6)とヘシアンの逆行列経由で固有値・固有ベクトルを求めた場合(δ1,・・・,δ6)とで,その対応関係がくずれてしまう(δi≠1/λi)という困った現象が見つかっています.
そのため,計算上の対策を施さなければいけないということがわかりました.もしR’VRが対角行列ではなく,上半角行列でいいのであれば,QR法,LU分解などの行列分解のスキームが適用できます.そこで,まず最初にLU法やQR法を用いて固有値を計算する手も考えたのですが,固有値だけでなく,固有ベクトルも欲しいので,QR法,LU分解はNG.それよりは6次元楕円の正射影と極を同時に描くことによって,軸との対応関係の不整をチェックする方法をとることにしました.
正射影を求めるサブルーチンは3830〜4010行なのですが,いわば局所的な条件のみに基づいて,回転行列を用いて楕円半径と楕円の配向を定めていますから,6次元楕円の固有値・固有ベクトルには依存しません.
それに対して,極や赤道面は固有値・固有ベクトルに依存するのですが,正射影は局所的な条件によって定まるので,整合の良し悪しはある程度この方法で確認することが可能になります.とはいっても,完全とはいえないのですが,正しく描かれると,2次元平面への正射影のなかにすべての極や赤道面が含まれることになります.
===================================