目次
前
次
計算
正3角形の頂点に、モータを配置して、モータの回転で
できるボールの移動Vectorを計算します。
各頂点をTop、Left、Rightと命名します。
(実際は、A、B、Cでも構わないのですが、
わかりやすくするために、こうします。)
Topの方向を基準にすると、Left、Rightは各々-60°、
+60°の傾きをもちます。(正3角形なので)
垂直(Y方向)と水平(X方向)の正方向を決めてTop、
Left、Rightの回転数を-100〜+100に規格化。
(規格化で、PWMと回転数の対応が、わかりやすくなります。)
この条件を元に、水平と垂直に分け、Vectorの成分を求めます。
水平方向成分
Topは、水平方向成分を持たないので、LeftとRightの
回転数をleftPWM、rightPWMとして、合成した水平方向
成分を求めます。
頂点Leftの水平方向成分は leftPWM x cos( 60)
頂点Righttの水平方向成分は rightPWM x cos(120)
合成すると ($leftPWM - $rightPWM) / 2
垂直方向成分
Topは、垂直方向の回転成分だけを持つので、topPWMとします。
また、LeftとRightの回転数をleftPWM、rightPWMに。
頂点Leftの垂直方向成分は leftPWM x sin( 60)
頂点Righttの垂直方向成分は rightPWM x sin(120)
合成すると $topPWM + sqrt(3) x ($leftPWM - $rightPWM) / 2
計算シーケンス
Top、Left、Rightの回転数を入力後、移動Vectorを
算出するシーケンスを考えます。
- 3頂点の成分が、-100〜+100の範囲内であることを確認します
- 1つでも範囲外であれば、エラーメッセージ表示後終了
- 水平方向成分を求めます
- 垂直方向成分を求めます
- 進行方向に対する傾きを求めます
シーケンスを決めたので、各処理に分解
して内容を記述。
成分範囲チェックプロシージャ
パラメータを入力し、範囲内で1を、範囲外で0を返す
プロシージャを定義します。
1と0の論理値なので、Yes、Noだけでもよいのですが、
論理積を数値の積に置換して求めると、判定処理が楽に
なるので、数値を返します。
Tcl/Tkは、procで定義。
proc judge {x} {
set result 0
if { -100 <= $x && $x <= 100 } {
incr result
}
return $result
}
入力パラメータをXとして、-100〜+100であるかを判定します。
結果の初期値を0としておき、範囲内であれば結果に1を
加え、returnを使い返値。
3頂点の回転数の範囲をチェックし、積を変数checkに設定。
変数checkが0ならば、エラーメッセージで終了。1ならば
次の動作を考えるように記述。
set check [expr [judge $topPWM] * [judge $leftPWM] * [judge $rightPWM]]
if { $check == 0 } {
tk_messageBox -type ok -message "Range error!"
} else {
; #
}
水平垂直成分計算
移動VectorのX成分(水平)、Y成分(垂直)を求めます。
計算式は導出してありますが、X成分、Y成分を求めるときに
必要な係数は固定値です。
最初に定数を変数に格納しておきます。
set deltaX 0.5
set deltaY [expr sqrt(3) / 2.0]
2定数deltaX、deltaYを利用し、X成分、Y成分を求めます。
set xcmp [expr $deltaX * ($leftPWM - $rightPWM)]
set ycmp [expr $topPWM + $deltaY * ($leftPWM + $rightPWM)]
角度計算
移動VectorのX成分(水平)、Y成分(垂直)を求めた後
X成分が0でなければ、左右に傾いて進みます。
左右どちらに傾いているかと、角度を求めます。
角度は、逆正接で求められます。
atan($ycmp/$xcmp)
3角関数に関係する関数を使う場合、注意が必要。
Tcl/Tkの組込み関数では、角度の単位はラジアン。
変換しなければなりません。
ラジアンから度への変換には、円周率πが必要になりますが
直接πを生成する関数はないので工夫します。
1の逆正接がπ/4なので、ラジアンから度の変換は
次式で計算できます。
set ang [expr 45 * atan($ycmp/$xcmp) / atan(1)]
左右どちらに傾いているかは、変数angの正負で判定できます。
正であれば、右に傾いています。
負であれば、左に傾いています。
正負という情報があるので、傾きは0〜90度に限定します。
負になる場合は、90を加えて、正にします。
if { $ang < 0 } {
set ang [expr 90 + $ang]
set dir "LEFT"
} else {
if { $ang > 0 } {
set dir "RIGHT"
}
}
傾いている方向と角度を求めるには、以下のコードにします。
set ang 0
set dir ""
if { $xcmp != 0 } {
set ang [expr 45 * atan($ycmp/$xcmp) / atan(1)]
if { $ang < 0 } {
set ang [expr 90 + $ang]
set dir "LEFT"
} else {
if { $ang > 0 } {
set dir "RIGHT"
}
}
}
全プロシージャ
3頂点の回転数を利用して、移動Vectorを求める
プロシージャは、以下となります。
proc calSet {x} {
global topPWM leftPWM rightPWM xcmp ycmp
global deltaX deltaY ang dir
set check [expr [judge $topPWM] * [judge $leftPWM] * [judge $rightPWM]]
if { $check == 0 } {
tk_messageBox -type ok -message "Range error!"
} else {
# get components
set xcmp [expr $deltaX * ($leftPWM - $rightPWM)]
set ycmp [expr $topPWM + $deltaY * ($leftPWM + $rightPWM)]
# calculate angle
set ang 0
set dir ""
if { $xcmp != 0 } {
set ang [expr 45 * atan($ycmp/$xcmp) / atan(1)]
if { $ang < 0 } {
set ang [expr 90 + $ang]
set dir "LEFT"
} else {
if { $ang > 0 } {
set dir "RIGHT"
}
}
}
}
# draw graph
}
プロシージャ内変数は、プロシージャ内部だけで有効です。
プロシージャ外部で定義している変数を利用する場合には、
global指定で、明らかにしておきます。
移動Vectorを図示するプロシージャは、別途定義。
目次
前
次