■ロボットアームと6次元楕円体(その2)
ロボットアームの操作性の解析において,v1〜v3は速度,v4〜v6は角速度を表しますから,速度だけあるいは角速度だけを分離して解析したいという要求ができるの当然の成りゆきでしょう.
そこで,今回のコラムでは6次元楕円の3次元速度空間(v1,v2,v3)あるいは3次元角速度空間(v4,v5,v6)への投影を試みます.
===================================
【1】6次元楕円を3次元空間に投影するプロシージャ
6次元楕円の楕円半径と楕円の配向を決定する6×6行列の右上,左下の3×3部分行列は,零行列ではないので,この6次元楕円は2つの3次元楕円には退化しません.そこで,6次元楕円を3次元空間に投影する必要がでてきます.
3次元空間に投影するといっても,特別なことをしているわけではなく,その手順は
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの逆行列(V=H~)を求める
(4)逆行列の小行列(Vijk)の固有値・固有ベクトルを求める
(5)軸の長さを√λとする
すなわち,2次元平面のときの小行列VijがVijkに変わっただけのことですが,3次元空間への正射影を計算するためには,3次方程式を解かなければなりません(証明略).
また,切り口の形を3次元空間に投影する際も,同様の手順
(1)ヤコビアン(J)の入力
(2)ヘシアン(H=(JJ’)~)の計算
(3)ヘシアンの小行列(Hijk)の固有値・固有ベクトルを求める
(4)軸の長さを1/√λとする
で計算できます.
その際,3次元空間への正射影のみならず,6次元楕円の3次元空間での切り口を求める必要がでてきます.その理由を述べるためには,統計用語の説明をしなければならないのですが,「偏相関係数」とは2つの変数間の,他の変数の影響を除いた相関の強さを意味する相関係数のことです.
単相関は,直接的な相関関係の部分と他の変数を通して現れる間接的相関の部分を含んでいます(見かけ上の相関).それに対して,偏相関は全体の相関の中から,他の変数の影響による間接的部分を排除して,直接的部分のみを取り出して評価しようとするものです.すなわち,単相関係数がすべての説明変量を全体として考慮した場合の関係(全相関)であるのに対し,偏相関係数は1つの説明変量を取り上げ,他の説明変量を一定にした場合の両者の相互関係を示しています.
正射影は「相関」に相当するものですが,切り口は「偏相関」すなわち,他の変数の影響を除いた相関の強さを意味しています.しかし,偏相関(切り口)はもし〜〜したらとか,もし〜〜であればという仮定の下に成り立つものです.切り口の場合は,v1=v2=v3=0,あるいは,v4=v5=v6=0が成り立つ空間における切り口ということになります.それに対して,通常の相関(正射影)は,みかけ上の相関を含んだ全相関を意味していて,実際の可動域を反映しています.
角度楕円・角速度楕円として正射影と切り口のどちらが適当か,私にはその優劣はつけられそうにありません.私自身はこの種の問題に対して門外漢であり,批評したところでそれは机上の空論になりかねません.こうした問題に詳しい人に委ねざるをえないのですが,適材適所を考えて,両者を使い分ける必要もでてくるかと思われます.
===================================
【2】ワイヤーフレームモデル
以下に,6次元楕円の3次元空間への正射影と,3次元空間での切り口を描くプログラムを掲げます.
6次元楕円を3次元空間に投影すると,どの方向に投影しても3次元楕円になります.これは3次元楕円の平面による切り口が常に楕円となる曲面であることと対応するものです.
3次元楕円は,いわば地球の形であり,その表示法としてワイヤーフレームモデルが多く用いられています.楕円体を概する多面体(ワイヤーフレームモデル)は図形を網目として素通しで見るものですから,ややリアリティーに欠けるものの,複雑な手順を必要としない最も簡単な表示法です.
ただし,この方法ではすべての経線・緯線をそのまま表示すると,図形がわかりにくくなるという欠点があります.そこで視点から見えない部分の経線・緯線を表示しないようにすれば,理解しやすい図形となります.
このプログラムの隠線処理では,各点での法線ベクトルを求めます.法線ベクトルが正のときは見える部分ですから実線で,負のときには見えない部分ですからその部分を破線で表示するようにしました.
ここで,標準形と助変数表示式をまとめておきますが,2次元楕円
x1^2/a^2+x2^2/b^2=1
では
x1=acosθ
x2=bsinθ
であったのに対し,3次元楕円
x1^2/a^2+x2^2/b^2+x3^2/c^2=1
では
x1=acosθ
x2=bsinθcosφ
x3=csinθsinφ
とパラメトライズすることができます.x1が緯度線を,x2,x3が経度線を与えますが,ただし,この場合の極は元の6次元楕円の極とは無関係です.
3次元楕円の極は3組あるわけですが,どれを極にするかは作図パラメータIJK(=1,2,3)で指定します.デフォルトはIJK=3になっています.また,作図パラメータIJKを0とすると,ワイヤーフレームモードが解除され,2次元に正射影した楕円の輪郭だけが描かれます.
===================================
【3】プログラム
5750 '
5760 ' *** ワイヤーフレーム楕円体 ***
5770 '
5780 *ELLIPSOID.WF:
5790 IB=1:JB=2:KB=3:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5800 IB=1:JB=3:KB=2:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5810 IB=2:JB=3:KB=1:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5820 IB=4:JB=5:KB=6:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5830 IB=4:JB=6:KB=5:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5840 IB=5:JB=6:KB=4:IJK=3:GOSUB *ELLIPSOID.WF.SUB
5850 RETURN
5860 '
5870 *ELLIPSOID.WF.SUB:
5880 UO=VO(IB):UL=VL(IB)
5890 VO=VO(JB):VL=VL(JB)
5900 DU=VD(IB):SU=VS(IB)
5910 DV=VD(JB):SV=VS(JB)
5920 '
5930 GOSUB *DRAW.AXIS.WF
5940 GOSUB *DRAW.ELLIPSE.WF
5950 GOSUB *TEMP
5960 RETURN
5970 '
5980 ' *** 正射影 ***
5990 '
6000 *DRAW.ELLIPSE.WF:
6010 'DRAW.COLOR=4
6020 WUO=UO-UL:WUL=UO+UL
6030 WVO=VO-VL:WVL=VO+VL
6040 WINDOW(WUO,-WVL)-(WUL,-WVO)
6050 VIEW(SX1,SY1)-(SX2,SY2)
6060 '
6070 IF IJK<>0 THEN GOSUB *EIGEN.WF:GOSUB *COMMON.WF
6080 IF IJK=0 AND STAGE$="1" THEN I=IB:J=JB:GOSUB *CONTOUR
6090 IF IJK=0 AND STAGE$="2" THEN I=IB:J=JB:GOSUB *SECTION
6100 'GOSUB *COMMON.WF
6110 'I=IB:J=JB:GOSUB *CONTOUR
6120 'I=IB:J=JB:GOSUB *SECTION
6130 '
6140 WINDOW(0,0)-(639,399)
6150 VIEW(0,0)-(639,399)
6160 RETURN
6170 '
6180 *EIGEN.WF:
6190 IF STAGE$="2" THEN 6380
6200 '
6210 AZ(1,1)=COV(IB,IB)
6220 AZ(1,2)=COV(IB,JB)
6230 AZ(1,3)=COV(IB,KB)
6240 AZ(2,1)=AZ(1,2)
6250 AZ(2,2)=COV(JB,JB)
6260 AZ(2,3)=COV(JB,KB)
6270 AZ(3,1)=AZ(1,3)
6280 AZ(3,2)=AZ(2,3)
6290 AZ(3,3)=COV(KB,KB)
6300 NZ=3:GOSUB *JACOBI
6310 '
6320 T=1:' [non-stochastic]
6330 AAA=SQR(T*AZ(1,1))
6340 BBB=SQR(T*AZ(2,2))
6350 CCC=SQR(T*AZ(3,3))
6360 KS=PI/12
6370 GOTO 6550
6380 '
6390 AZ(1,1)=HESSE(IB,IB)
6400 AZ(1,2)=HESSE(IB,JB)
6410 AZ(1,3)=HESSE(IB,KB)
6420 AZ(2,1)=AZ(1,2)
6430 AZ(2,2)=HESSE(JB,JB)
6440 AZ(2,3)=HESSE(JB,KB)
6450 AZ(3,1)=AZ(1,3)
6460 AZ(3,2)=AZ(2,3)
6470 AZ(3,3)=HESSE(KB,KB)
6480 NZ=3:GOSUB *JACOBI
6490 '
6500 T=1:' [non-stochastic]
6510 AAA=SQR(T/AZ(1,1))
6520 BBB=SQR(T/AZ(2,2))
6530 CCC=SQR(T/AZ(3,3))
6540 KS=PI/12
6550 RETURN
6560 '
6570 ' *** 経線・緯線 ***
6580 '
6590 *COMMON.WF:
6600 FOR V=PI/2-KS TO -PI/2+KS-.01 STEP -KS
6610 G=0
6620 FOR U=0 TO 2*PI+.01 STEP KS
6630 GOSUB *WIRE.FRAME
6640 NEXT U
6650 NEXT V
6660 '
6670 FOR U=0 TO 2*PI+.01 STEP KS
6680 G=0
6690 'FOR V=PI/2-KS TO -PI/2+KS-.01 STEP -KS
6700 FOR V=PI/2 TO -PI/2-.01 STEP -KS
6710 GOSUB *WIRE.FRAME
6720 NEXT V
6730 NEXT U
6740 RETURN
6750 '
6760 *WIRE.FRAME:
6770 ON IJK GOTO 6900,6840,6780
6780 '
6790 '[k-pole]
6800 GX=AAA*COS(U)*COS(V)*BZ(1,1)+BBB*SIN(U)*COS(V)*BZ(1,2)+CCC*SIN(V)*BZ(1,3)
6810 GY=AAA*COS(U)*COS(V)*BZ(2,1)+BBB*SIN(U)*COS(V)*BZ(2,2)+CCC*SIN(V)*BZ(2,3)
6820 GZ=AAA*COS(U)*COS(V)*BZ(3,1)+BBB*SIN(U)*COS(V)*BZ(3,2)+CCC*SIN(V)*BZ(3,3)
6830 GOTO 6950
6840 '
6850 '[j-pole]
6860 GX=AAA*SIN(U)*COS(V)*BZ(1,1)+BBB*SIN(V)*BZ(1,2)+CCC*COS(U)*COS(V)*BZ(1,3)
6870 GY=AAA*SIN(U)*COS(V)*BZ(2,1)+BBB*SIN(V)*BZ(2,2)+CCC*COS(U)*COS(V)*BZ(2,3)
6880 GZ=AAA*SIN(U)*COS(V)*BZ(3,1)+BBB*SIN(V)*BZ(3,2)+CCC*COS(U)*COS(V)*BZ(3,3)
6890 GOTO 6950
6900 '
6910 '[i-pole]
6920 GX=AAA*SIN(V)*BZ(1,1)+BBB*COS(U)*COS(V)*BZ(1,2)+CCC*SIN(U)*COS(V)*BZ(1,3)
6930 GY=AAA*SIN(V)*BZ(2,1)+BBB*COS(U)*COS(V)*BZ(2,2)+CCC*SIN(U)*COS(V)*BZ(2,3)
6940 GZ=AAA*SIN(V)*BZ(3,1)+BBB*COS(U)*COS(V)*BZ(3,2)+CCC*SIN(U)*COS(V)*BZ(3,3)
6950 '
6960 GX=GX+VO(IB)
6970 GY=GY+VO(JB)
6980 GZ=GZ+VO(KB)
6990 '
7000 ON VHP+1 GOSUB *VERTICAL,*VERTICAL,*HORIZONTAL,*PROFILE
7010 RETURN
7020 '
7030 *VERTICAL:
7040 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
7050 GOSUB *NORMAL.VECTOR
7060 IF DZ<=0 THEN LINE-(GX,-GY),DRAW.COLOR
7070 IF DZ> 0 THEN LINE-(GX,-GY),DRAW.COLOR,,&H1111
7080 RETURN
7090 '
7100 *HORIZONTAL:
7110 IF G=0 THEN PSET(GX,-GZ),DRAW.COLOR:G=1
7120 GOSUB *NORMAL.VECTOR:DY=-DY
7130 IF DY<=0 THEN LINE-(GX,-GZ),DRAW.COLOR
7140 IF DY> 0 THEN LINE-(GX,-GZ),DRAW.COLOR,,&H1111
7150 RETURN
7160 '
7170 *PROFILE:
7180 IF G=0 THEN PSET(GZ,-GY),DRAW.COLOR:G=1
7190 GOSUB *NORMAL.VECTOR:DX=-DX
7200 IF DX<=0 THEN LINE-(GZ,-GY),DRAW.COLOR
7210 IF DX> 0 THEN LINE-(GZ,-GY),DRAW.COLOR,,&H1111
7220 RETURN
7230 '
7240 ' *** 法線ベクトル ***
7250 '
7260 *NORMAL.VECTOR:
7270 ON IJK GOTO 7460,7370,7280
7280 '
7290 '[k-pole]
7300 DXDU=-AAA*SIN(U)*COS(V)*BZ(1,1)+BBB*COS(U)*COS(V)*BZ(1,2)
7310 DYDU=-AAA*SIN(U)*COS(V)*BZ(2,1)+BBB*COS(U)*COS(V)*BZ(2,2)
7320 DZDU=-AAA*SIN(U)*COS(V)*BZ(3,1)+BBB*COS(U)*COS(V)*BZ(3,2)
7330 DXDV=-AAA*COS(U)*SIN(V)*BZ(1,1)-BBB*SIN(U)*SIN(V)*BZ(1,2)+CCC*COS(V)*BZ(1,3)
7340 DYDV=-AAA*COS(U)*SIN(V)*BZ(2,1)-BBB*SIN(U)*SIN(V)*BZ(2,2)+CCC*COS(V)*BZ(2,3)
7350 DZDV=-AAA*COS(U)*SIN(V)*BZ(3,1)-BBB*SIN(U)*SIN(V)*BZ(3,2)+CCC*COS(V)*BZ(3,3)
7360 GOTO 7540
7370 '
7380 '[j-pole]
7390 DXDU=AAA*COS(U)*COS(V)*BZ(1,1)-CCC*SIN(U)*COS(V)*BZ(1,3)
7400 DYDU=AAA*COS(U)*COS(V)*BZ(2,1)-CCC*SIN(U)*COS(V)*BZ(2,3)
7410 DZDU=AAA*COS(U)*COS(V)*BZ(3,1)-CCC*SIN(U)*COS(V)*BZ(3,3)
7420 DXDV=-AAA*SIN(U)*SIN(V)*BZ(1,1)+BBB*COS(V)*BZ(1,2)-CCC*COS(U)*SIN(V)*BZ(1,3)
7430 DYDV=-AAA*SIN(U)*SIN(V)*BZ(2,1)+BBB*COS(V)*BZ(2,2)-CCC*COS(U)*SIN(V)*BZ(2,3)
7440 DZDV=-AAA*SIN(U)*SIN(V)*BZ(3,1)+BBB*COS(V)*BZ(3,2)-CCC*COS(U)*SIN(V)*BZ(3,3)
7450 GOTO 7540
7460 '
7470 '[i-pole]
7480 DXDU=-BBB*SIN(U)*COS(V)*BZ(1,2)+CCC*COS(U)*COS(V)*BZ(1,3)
7490 DYDU=-BBB*SIN(U)*COS(V)*BZ(2,2)+CCC*COS(U)*COS(V)*BZ(2,3)
7500 DZDU=-BBB*SIN(U)*COS(V)*BZ(3,2)+CCC*COS(U)*COS(V)*BZ(3,3)
7510 DXDV=AAA*COS(V)*BZ(1,1)-BBB*COS(U)*SIN(V)*BZ(1,2)-CCC*SIN(U)*SIN(V)*BZ(1,3)
7520 DYDV=AAA*COS(V)*BZ(2,1)-BBB*COS(U)*SIN(V)*BZ(2,2)-CCC*SIN(U)*SIN(V)*BZ(2,3)
7530 DZDV=AAA*COS(V)*BZ(3,1)-BBB*COS(U)*SIN(V)*BZ(3,2)-CCC*SIN(U)*SIN(V)*BZ(3,3)
7540 '
7550 DX=DYDU*DZDV-DYDV*DZDU
7560 DY=DZDU*DXDV-DZDV*DXDU
7570 DZ=DXDU*DYDV-DXDV*DYDU
7580 RETURN
7590 '
7600 ' *** 座標軸 ***
7610 '
7620 *DRAW.AXIS.WF:
7630 CLS 3
7640 SX1=59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360
7650 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
7660 RR=3:GOSUB *X.SCALE2:GOSUB *X.REF2
7670 RR=3:GOSUB *Y.SCALE2:GOSUB *Y.REF2
7680 I=IB:J=JB:RR=3:GOSUB *DOT.PLOT
7690 GOSUB *TITLE.BACK2.WF
7700 RETURN
7710 '
7720 ' *** タイトル ***
7730 '
7740 *TITLE.BACK2.WF:
7750 LX=INT((580*RX+59)/8)
7760 LY=INT(360*(1-RY)/16)
7770 LZ=INT((290*RX+59)/8)
7780 L1$="ellipsoid projection of "
7790 L2$="v"+MID$(STR$(IB),2)+"-"
7800 L3$="v"+MID$(STR$(JB),2)+"-"
7810 L4$="v"+MID$(STR$(KB),2)+" space"
7820 L$=L1$+L2$+L3$+L4$
7830 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
7840 L$=UNIT$(JB)
7850 IF LEN(L$)=0 THEN 5610
7860 LOCATE 7,LY-1:PRINT "("+L$+")"
7870 L$=UNIT$(IB)
7880 IF LEN(L$)=0 THEN 5640
7890 LOCATE LX+3,21:PRINT "("+L$+")"
7900 '
7910 LOCATE LX+3,LY:PRINT "v components: "
7920 FOR K=1 TO M
7930 V$="v"+MID$(STR$(K),2)+"="
7940 LOCATE LX+3,LY+K+1:PRINT V$;:PRINT V(K)
7950 NEXT K
7960 RETURN
===================================
【4】このプログラムの問題点
前回のコラムでは,対称行列を対角行列に直して,固有値を求めるアルゴリズムに,行列の数値計算の本に載っていない欠陥があることを指摘しました.固有値・固有ベクトルを求める際,既存のプログラムでは軸と固有値・固有ベクトルの対応関係が崩れてしまう恐れがあるのです.
そのため,実際は横長の楕円となるべきところが縦長になったりしてしまったりするのですが,この状況は6次元楕円ではますます顕著になってきます.このことは本には書かれていないので,はじめてこの現象に気づいたときは愕然としました.
たとえば,2次元平面に投影する際,2次方程式を解いて,固有値λ1,λ2を求めるところまではいいのですが,λ1がx軸に対応するのか,それともy軸なのかで,まったく話が違ってしまいます.そこで,軸との対応関係を保持させるために,回転行列を用いて解析的に求めることにしました.
2次元の回転行列
R=[cosθ,−sinθ]
[sinθ, cosθ]
のθは,
R^(-1)VR=R’VR
の行列Vの成分を用いて
θ=1/2arctan(2σxy/(σx2−σy2))
と表すことができますから,6次元楕円の正射影や切り口の2次元平面への投影に関してはまったく問題はありません.
それに対して,3次元空間への投影では,固有値を求めるアルゴリズムを用いる限り対応関係に狂いを生ずる可能性がありますから,なにか対策を施さなければなりません.
やりたいことは,任意の対称行列Hに対して,Rをユニタリ行列とし,
R’HR=diag(λ1,λ2,λ3)
すなわち,対角行列となるような直交行列Rを見つけたいということです.とはいっても,固有方程式(3次方程式)をカルダノの方法を使って直接解く方法では実用性に乏しいと思われるので,2次元の場合と同様,
(1)回転行列をみつける
(2)非対角要素を0にする回転角を定める
ことによって,解析的に解を求めたいと考えました.
最初に考えついた方法は,3次元の直交行列
[sinθcosφ,cosθcosφ,-sinφ]
[sinθsinφ,cosθsinφ,cosφ ]
[cosθ ,-sinθ ,0 ]
を使って直交変換することでした.このあと,R’HR=Gにおいて,
H=[h11,h12,h13] G=[g11,g12,g13]
[h12,h22,h23] [g12,g22,g23]
[h13,h23,h33] [g13,g23,g33]
として,非対角要素g12=0,g13=0,g23=0から,θとφをhijで表そうとしたのですが,条件より
(1)1/2*sin2θ{h11(cosφ)^2+h22(sinφ)^2-h33+2*h12sinφcosφ}+cos2θ(h13cosφ+h23sinφ)=0
(2)1/2*sinθ{(h22-h11)sin2φ+2*h12cos2φ}+cosθ(h23cosφ-h13sinφ)=0
(3)1/2*cosθ{(h22-h11)sin2φ+2*h12cos2φ}-sinθ(h23cosφ-h13sinφ)=0
の3つの式からθ,φをhijを用いて表す問題となりました.
ここで,
1/2*{(h22-h11)sin2φ+2*h12cos2φ}:=a
(h23cosφ-h13sinφ):=b
(a^2+b^2)=c,a/c=cosα,b/c=sinαとすると,
(2)はsinθcosα+cosθsinα=sin(θ+α)=0
(3)はcosθcosα-sinθsinα=cos(θ+α)=0
となって,あり得ないことが起こり,矛盾を生じます.
ここで計算が行き詰まったのですが,これは当該の直交行列が回転行列ではないことを意味しています.二次元の場合,直交行列は必ず原点の周りの回転
R=[cosθ,-sinθ]
[sinθ, cosθ]
で表現可能であるので,平面の回転では回転行列Rをかけてやればよいのですが,ところが,空間の回転では直交行列は回転行列とは限らないのです.たとえば,
[1 0 0]
[0 1 0]
[0 0 -1]
はユニタリではあるが,軸の周りの「回転」ではありません.(教訓):2次元の直交変換はそのまま平面の回転なのですが,3次元の直交変換は一般に空間の回転になりません.
そこで,空間を回転させる行列で直交変換となっているものを探してみたところ,パラメータ数が3つの「回転」かつ「直交」行列として
(1)オイラー角に基づくもの
(2)ロール・ピッチ・ヨーに基づくもの
が見つかりました.
(1)はz軸まわりの回転α→新しいy軸まわりの回転β→新しいz軸まわりの回転γ,(2)はz軸まわりの回転φ→新しいy軸まわりの回転θ→新しいx軸まわりの回転ψの3段階によって表すもので,両者に本質的な違いはありません.
ロボット工学の基礎としては(2)が良く扱われるとのことですから,(2)を示しますが,
R(1,1)=cosφcosθ
R(2,1)=sinφcosθ
R(3,1)=-sinθ
R(1,2)=cosφsinθsinψ-sinφcosψ
R(2,2)=sinφsinθsinψ+cosφcosψ
R(3,2)=cosθsinψ
R(1,3)=cosφsinθcosψ+sinφsinψ
R(2,3)=sinφsinθcosψ-cosφsinψ
R(3,3)=cosθcosψ
回転行列を与えられた場合のφ,θ,ψの解法は知られている(ただし,一意ではなく,象限判別が必要となる)のですが,非対角要素を0とする3つのパラメータθ,φ,ψを決定することは,複雑すぎてできそうにありませんでした.
また,単位ベクトル
n↑=(α,β,γ) α,β,γは方向余弦で,α^2+β^2+γ^2=1を満たすものとする
を回転軸とし,その周りに正の回転方向にθだけ回転する回転行列
R(1,1)=α^2(1-cosθ)+cosθ
R(2,2)=β^2(1-cosθ)+cosθ
R(3,3)=γ^2(1-cosθ)+cosθ
R(1,2)=αβ(1-cosθ)+γsinθ
R(2,1)=αβ(1-cosθ)-γsinθ
R(1,3)=αγ(1-cosθ)-βsinθ
R(3,1)=αγ(1-cosθ)+βsinθ
R(2,3)=βγ(1-cosθ)+αsinθ
R(3,2)=βγ(1-cosθ)-αsinθ
についても同様でした.結局,どの回転行列を使ったとしても,固有値・固有ベクトルを解析的に求めることは簡単ではないようです.
このプログラムの正射影や切り口の3次元空間への投影に関しては,まだ問題が払拭できずにいるのですが,解決策(次善策)については次回のコラムで述べることにします.
===================================