2022年5月31日火曜日

2022年5月報

1.5月授業内容
2.5月の課題
3.4月の解答
4.今後の授業スケジュール
5.お知らせ


1. 5月授業内容


1.0 <スタートアップ(全コース)>


 割愛します。


1.1 <プライマリーコース『ロボシーソー』>


 割愛します。

1.2 <ベーシックコース『パカラー』>


 馬型ロボットです。
中には、首を長くしてキリンや、角(つの)を付けてトナカイになったものや、首なし“妖怪”もありましたが。
 横から見て、前脚(まえあし)と後ろ脚(うしろあし)がハの字に開いたり閉じたりを繰(く)り返します。
左右ではタイミングを反対(位相を180°ずらし)にしています。
単純に見えるリンク機構から、モーター1本で動物らしく4足歩行することに驚(おどろ)かされます。

 特に、前足(タイヤ)は、横から見て円形を描(えが)くように動くことで、左右どちらか一方が接地(せっち)し、他方は浮(う)き上がることが可能になり、真の歩行動作と推進力(すいしんりょく)を生み出しています。


後ろの2足(ホイール)は常(つね)に接地したまま前後運動(見せかけの歩行)をするので、摩擦(まさつ)が邪魔(じゃま)にならないようゴムを外していますが、
前の1足と合わせた3点支持(しじ)により、本体を安定させる役割も担(にな)っています。

 あとは、首を飾(かざ)り付けすぎたり、重たい電池ボックスを前方に片寄(かたよ)らせたりして前のめりにならないよう、重心(重さの中心位置)に気を配ります。

もしくは、リヤカー(サンタのソリ?)を引くことでも安定しましたね。
 授業の最後に、脚の長さを変えてスピードを競(きそ)うレースや、対戦ペアのパカラーのお尻(しり)を紐(ひも)でつないで綱(つな)引きをしました。

綱引きでは、下記のようなロボットは弱かったようです。

1) 電池が弱い(*1)

2) ベベルギアが滑(すべ)ってガリガリ言うだけで、進まない(*2)

3) 綱でお尻の高い所を引っぱられて前足が浮き、地面をうまく蹴(け)られない(*3)

4) 左右の脚を動かすタイミングが真反対(まはんたい)になっておらず、推進力が弱かったり、バランスが悪く倒れやすかったりした(*4)

5) グリップ力を高めようと重くしすぎたり、引きずる後ろ足にまでタイヤゴムをはめたりして、自身で動けなくなり、判定負けした(*5)


*1 引っぱれないどころか、動けなければ判定負けですので、勝ち目がありません。

*2 モーター側のピニオンギアとベベルギアがしっかり噛(か)み合うよう、ワッシャーを3枚入れています。
 ベベルギアが削(けず)れてしまったら、ワッシャーを4枚にしたり、ブッシュやグロメットに替(か)えたり、自分で改良します。

*3 後ろ足を支点(してん)にして、パカラーを後ろに回転させようとする力が働(はたら)くためです。
 綱をなるべく低い所に結び、さらに、頭のパーツを重くして、重心を前方に移動させます。
 運動会の綱引きで、上体を引きたい方向(後ろ)へ傾(かたむ)けるのも、つっぱった前足を支点にして体が前へ回転しないよう、重心を後ろにもっていくためです。

*4 胴体(どうたい)側面(そくめん)のロッド3アナの向きを180°ずらします。
 90°ずれの人が多かったです。そうすると、「パカ、パカ、パカ…」という等(ひと)しいリズムにならず、「パカパカッ、パカパカッ…」となってしまいます。

*5 実は、ギアで減速すると止まらず、最強の改造になりますが、ミドルコースレベルです。


1.3 <ミドルコース『ロボワン』>



 忠犬ロボットと銘打(めいう)っています。
今月はベーシックコース共に、4足歩行動物になりました。


 回転するロッド3アナ(クランク用)と連接用ロッドをペグ(回転軸)でつないだリンク機構(てこクランク機構)により、
モーター1本で4足がタイミング(位相)をずらして前後(実際は細い三日月形)運動をします。
また、このリンクの組み方次第で、ロッド末端部(足先に相当)に輪ゴム留(ど)めした鉛筆の軌跡(きせき)が細長い三日月楕円(だえん)に変わることも実験しました。




機械工学的な理論としては難しいので、テキストでも解説はありませんが、
てこクランク機構というのは、組み方を少し変えるだけで軌跡が大きく変わるので、いろいろ試して歩き方の変化を楽しんでみましょう(*1)。
 授業の最後に、コミカルな動きやデザインを競う“品評会”や、綱引きをしました。

綱引きでは、下記のようなロボットが強かったようです。

1) 電池がパワフル
 言うまでもありませんね。前提条件です。

2) ピニオンギアとベベルギアをしっかり噛(か)み合わせている
 ギアが滑(すべ)って「ガルルルッ…」と吠(ほ)えるだけの負け犬が多かったです。

 テキスト通りに作ってダメなら、自分で調整するように(*2)。

3) 4脚をバランス良くずらして動かす
 脚は付ければいいってものではありません。胴体側面のロッド3アナの向きとシャフトペグの位置をテキスト通りに合わせます。

 前脚も後ろ脚も、左右でタイミングを反対(位相を180°ずらし)にするのが基本です。
 前後では、90°ずらしています(*3)。

4) 脚が短い!
 ダックスフント型の改造例がテキストに載っています。スピードレースには不利ですが、綱引きにはとても有利です(*4)。

 同じモーターパワーで足先の動きを遅くするということは、ギアで減速するのと同じく、力を大きくします。
 その分、電池が弱くても止まりにくくなります。

5) グリップ力を増やす!
 1) ~ 4)を対策した上で、ロボットを重くしたり、足裏にタイヤゴムを履(は)かせたりして、地面との摩擦力を大きくするのは吉です(*5)。
 2018年11月には、相手に引っ張られて体勢を崩(くず)し、足を浮かせられなくても推進の邪魔にならないよう足先に転がるタイヤを付けた上で、ラチェット機構により蹴(け)り出すグリップ力を確保する改造も見られました。

 ミドルコースに相応(ふさわ)しいナイスアイデアですね!


*1 テキスト最後に掲載(けいさい)された高橋智隆(ともたか)先生のメッセージからも、試行錯誤(しこうさくご)してバランスを調整した形跡(けいせき)が見て取れますよ。

*2 実際、テキスト通りではダメでした。
 ベベルギアが滑って削(けず)れると、より滑りやすくなりますので、スペーサー(隙間を埋めて固定するもの)として、ブッシュの他にワッシャーを追加したり、グロメットやマイタギアに替えたりして強化します。

*3 そうすると、左前0°、右後ろ90°、右前180°、左後ろ270°のように、90°回転する毎に4足が次々と均等間隔(きんとうかんかく)で地面を蹴(け)るようになります。
 均等でないと、「足を着けて地面を蹴る」→「足を浮かせて前へ戻す」という一連の動作が下手(へた)になって推進効率(すいしんこうりつ)が悪くなったり、モーターの負荷(ふか)が過大(かだい)になって止まりやすくなったりします。

*4 本物のダックスフントには期待しないように…。

*5 これだけをやっても、止まりやすくなってしまいます。


1.4 <アドバンスコース『コピーロボット②』>


 《下記を参照下さい》
  http://robocobo.sakura.ne.jp/blog/robot/adv1-1805.pdf


1.5 <プロ1年目コース『オムニホイールロボット②』>


 1ヶ月目に製作したオムニホイール(Omnidirectional Wheel;全方向車輪)ロボットの動きの原理を理解し、思い通りの動きをプログラム上で指示できるようになるまでの2ヶ月目の授業です。

 1日目は、改めてオムニホイール(車輪)の仕組みを考察し、3つの車輪を任意の速さ・向きに回したときの進行方向が“力(ベクトル)の合成”によって求まることを学びました。

ここでのベクトルは、車輪の回転の向き速さを、それぞれ矢印の向き長さで(紙面上に)表したものです。

2つのベクトルの合成は、まず作用点(ベクトルの始点)を重ねて、それが平行四辺形の2辺を形成するようにもう2辺を描き足し、作用点から発した対角線(=合力)の向き長さで表します。

3つのベクトルを合成するには、任意の2つを合成した後、その合力と残りのベクトルをさらに合成します。

様々な練習問題を製図して解きつつ、プログラムの数値に反映して動きを確かめ、どんな3輪の回転の組合せでも、ロボットの進行方向を求めることができるようになりました。

 2日目に、ロボットの回転する動きを考察します。
1日目では、進行方向を割り出すことができましたが、ロボットが向きを変えずに移動(=並進運動)する場合は、これで十分でした。

しかし、実際は互いに離れた3輪による作用点(ベクトルの始点)を一点(例えば、ロボットの中心)に集めて合成するために、本体が回転しようとする力(モーメント)を扱うことができませんでした。

例えば、3輪とも同じ速さで時計回りに回転させる場合、ベクトルの合成結果は長さゼロの“点”となって、ロボットが移動しないことを言い当てますが、実際の動きは、移動こそしないものの、その場でぐるぐる回り続けます。
この回る動き(=回転運動)を予測できるようにします。

 レンチやスパナを想い起こしてください。
支点回転中心)のある物体に対し、支点から離れた場所作用点)に、(支点に向かう向きとは異なる)力を加えると、物体は支点の周りで回転します。
この物体を回そうとする作用力を“モーメント”といいます。

支点と作用点の間の距離を単に“長さ”と呼ぶと、

 [モーメント]=[長さ]×[力の大きさ]

という関係があり、長いほど回す作用が強くなるという、てこの原理を表しています。

オムニホイールは、3輪とも円周上(円形ボードの縁)に取り付けられているため、円形ボードの中心を支点としてロボットの回転を考えたとき、各ホイールまでの長さ]が全て等しいので、オムニホイールロボットの[モーメント]を推し量る上では、[力の大きさ](今回はホイールの回転スピード)だけ考慮すればよいことになります。

 難しく述べましたが、簡単には、時計回り反時計回りの回転スピードを差し引きして、ゼロなら回転せず、ゼロ以外ならその値の分だけ優勢な方向に回転する、と言えるのです。

オムニホイールロボットがカーブの軌跡を描いて移動するとき、並進運動だけで実現すれば、飛来するUFOのように向きを変えず、並進運動+回転運動を組み合わせれば、自動車のように自然に曲がることもできるのです。

3つのオムニホイールが生み出す、どんな複雑なロボットの動きも、
ベクトルの合成”で求まる並進運動と、
モーメントの合成”で求まる回転運動とに分解して説明できるのです。

 最終の3ヶ月目では、このロボットに“触覚”と“頭脳”を植え付け、ロボカップに通ずる自律型ロボットに仕上げます。


1.6 <プロ2年目コース『不思議アイテムII②』>


 外付けの電子回路をプログラミングで操る春タームの2ヶ月目です。

 前月は、タクトスイッチというデジタル(ON/OFF)入力装置をマイコンに繋いで、プログラム中 digitalRead() 関数で読み取りましたが、
我々はアナログ量に満ちた自然界に住んでいます。

光の強さ、色の濃さ、音の大きさ、痛みや匂いなど、およそ0/1だけで語られては困る事象と相互干渉しながら暮らしています。
それだけに、コンピュータやロボットに対しても、アナログ的な入力や出力を期待できないと満足がいきません(*1)。

とは言え、せっかく微量の電力だけで高速処理してくれる小さなマイコンチップに、人間の都合で味覚や温度、力加減まで、何でも分かる感覚を付け足していくのは酷で、蛇足にも思えます。
それでも、列挙した感覚をもつマシンはめいめい現存しています。専用マイコンなのでしょうか?

そうではありませんね。汎用(はんよう)の演算処理装置(CPU)に、必要なセンサーを繋いでデータを送受信する方法が一般的な解です。

 流すデータ(数値)を構成する物理量として、“電圧値”が最も多用されます。
中身が電圧型論理回路であるマイコンにとって、扱い易く、省エネにできるからです。

マイコンには、電圧のデジタル値(0/1)だけでなく、アナログ値(0~1)も入出力できるピンやモード設定が用意されています(*2)。
だから、光でも音でも熱でも力でも、その量に応じて電圧値に変えられるセンサーなら、直ぐに繋げます
繋いだら、analogRead() 関数で読み取るだけです。

 1日目に、ボリュームセンサー(可変抵抗器)を繋ぎました。
と言っても、その名の通り、ツマミを回して抵抗値を変えられる部品ですから、電圧値を読み取るマイコンの入力ピンにそのまま繋いでも、何もセンシングできません。
耳の穴に抵抗器を入れて音を聞こうとするようなものです。

抵抗値は、電流を流すことで、簡単に電圧値に変換できます(*3)。
電圧・電流・抵抗の間に、オームの法則と呼ぶ次の関係があります(*4)。
水圧・水流・蛇口の絞りの関係になぞらえると理解し易いです。


・電流(I) = 電圧(V) ÷ 抵抗(R)
・電圧(V) = 抵抗(R) × 電流(I) ←電流を流して抵抗を電圧に変換する式
・抵抗(R) = 電圧(V) ÷ 電流(I)

 ボリュームから可変電圧を作り出す原理は、抵抗分圧といって、詳細は割愛しますが、以下に簡単に説明します。

1) 10kΩタイプの3端子ボリュームの場合、両端子間にGND(0V)と5Vを繋ぐことで、I=5V÷10kΩ=0.5mAの電流がずっと流れます。

2) ツマミは、GND側から5V側まで伸びる10kΩ抵抗の任意の位置に接点をスライドさせ、接点は真ん中の端子に繋がっています。

3) 接点がGND側から20%の位置にある場合、GND⇔接点間の2kΩに0.5mA流れていることにより、真ん中の端子には2kΩ×0.5mA=1V(5Vの20%)の電圧が表れます。

4) 真ん中の端子電圧をマイコンで読み取ることで、ツマミを回した量が判定できます。

5) 両端子間の抵抗値が何でも同じですが、流し続ける電流量(ノイズ耐性)で選びます。


 ボリュームセンサーに代わり、CdS光センサーは、明るさに反応する可変抵抗器です。
例えば、暗闇で10kΩ(暗抵抗)、日光で100Ω(明抵抗)程度まで変化します。

これを固定抵抗器と直列に接続し、両端に電圧を掛ける(電流を流す)ことで、中間の接続点に明るさに応じて抵抗分圧された電圧値が表れます
つまり、マイコンで明るさを検知し、メーター表示したり、照明を自動点灯したり、画面の明るさを制御したりできるようになります(*5)。

または、圧電スピーカを繋ぎ、analogRead() 値を tone() 関数に渡すという、たった2行だけで、かざした手の距離(影の暗さ)に応じて音の高低が変わるテルミンのような楽器になりました(*6)。

 2日目は、4桁の7セグメントLEDによる表示方法を学びました(*7)。

下記の表示関数が登場しました。
・setDigit() … 指定した桁に数字およびドット(小数点)を表示
・setLed()  … 指定した桁の指定した棒またはドットを点灯/消灯
・setDec()  … 指定した数(-999~9999)を一発で表示


特に、setLed() を使えば、数字だけでなく、8(7つの棒+ドット)×4桁=32個のLEDによる任意のパターンやアニメーションを表示できるということです。
そもそも、数字の形を指示せずに表示してくれる setDigit()setDec() も、中身では setLed() 相当のプログラムで光らせる棒を1本ずつ指定しているだけです。

意味のある7セグ数字を見ていると、いかにもマイコンらしい表明手段のように感じますが、こちらの幻想に過ぎません。
マイコンにとって、数字の形や意味など知ったことではないのです(*8)。

 さて、32個のLEDを使って、誰かが用意してくれた数字の表示関数を使わずに、自分で任意のパターンやアニメーションを表示するには、それなりのデータ量をプログラムに記さなければなりません。

棒を3本光らせるのに、

int a = 4;
int b = 6;
int c = 1;
setLed(0, 0, a, HIGH);
setLed(0, 0, b, HIGH);
setLed(0, 0, c, HIGH);

よりも、

int a1 = 4;
int a2 = 6;
int a3 = 1;
setLed(0, 0, a1, HIGH);
setLed(0, 0, a2, HIGH);
setLed(0, 0, a3, HIGH);

の方が、変数の命名に悩まずに済みそうですが、配列for文による繰り返しを使って、

int a[] = {4, 6, 1};
    // a[0]=4, a[1]=6, a[2]=1 と代入される

for (int i=0; i<3; i++) {
  setLed(0, 0, a[i], HIGH);
  // a[0], a[1], a[2] に順次アクセス
}

と書く方がスマートで、データが増えても破綻(はたん)し難そうです。
for文による配列変数への順次アクセスは、プログラミングの強力な武器です。
しっかりマスターしましょう。


*1 4Kハイビジョンとか、VRとか、ニセモノ体験の質を上げ続けたくなる人間が満足する日とは…脳がそちらをホンモノと見なして生きる時でしょうか…。

*2 先月も注釈したように、マイコンには真のアナログ信号は扱えないので、
 PWM制御(1年目1月)により擬似的にアナログ出力電圧(256階調など)を生成したり、
 真のアナログ入力電圧をデジタル値(1024階調など)に変換したりするコンバータ回路が搭載されています。

*3 というより、電流をどれだけ邪魔するかの指標が抵抗なので、電流を流してみることで抵抗値が分かります。

*4 速さ・時間・距離の関係と同様、1つの式から他の2つの式を導出できます。
 語呂合わせ「はじき」と同じく、“覚える”ものではなく、感覚で捉えるべきものですが、一先ず V=RI と発音して記憶します。

*5 暗い部屋で眩(まぶ)しくないよう、LED時計やテレビ画面の明るさを落とすために、CdSセンサーを用いたディマー(減光)回路が搭載されています。

*6 明るさ[手の影] → 抵抗値[CdSセンサー] → 電圧値[抵抗分圧入力をanalogRead()] → 周波数[tone()でスピーカにPWM出力] のように物理量を変換したのです。

*7 通称「7セグ」と呼ぶ、7本の棒で数字を表現するデジタル表示器のこと。
 今やローテクの象徴のような表示手段ですが、映画『バック・トゥ・ザ・フューチャー』世代のオジサンには、未だにタイムマシンのコックピットにずらりと並ぶ先進的でロマンに溢れたデバイスにしか見えません。

*8 幻滅しましたか? 今のコンピュータなんて、パソコンもスマホもそんな無意思の集大成です。君たちの世代がそれを変貌させていくのです。


1.7 <プロ3年目コース『不思議アイテムIII-1②』>


 もっと赤外線で遊びます。

 前月、赤外線データを送受信できるようになりましたので、これを大砲の弾に見立て(*1)、戦車ロボット(オムニホイール)に搭載してサバイバル戦を繰り広げました。

戦車ゲームプログラム[IRtankFire]では、ライフ数(life)や当たり判定閾値(hit_rate)の変数が用意され、ゲーム性を簡単にカスタマイズできます。

 さて、赤外線を使って、このようなゲームが成立するのは、赤外線が照射方向に真っ直ぐ飛ぶ性質を備えているからです。
このことを「指向性が高い」と言います。

ここで波長がメートル級の電波を使ってしまうと、砲塔がどこを向いていようが、発射したビームが部屋中に拡散し、敵・見方の見境(みさかい)も無く全員を攻撃するテロリストになります。

 それならば、次のアプリケーションとして、赤外線の発信源の方向を特定し、回避したり追従したりできるでしょうか?

指向性があるとは言え、実際には、懐中電灯の光の如く、発信源(赤外線LEDやリモコン)から円錐ビーム状にある程度拡がります(*2)。
実験してみると、赤外線LEDの方向から±45°で90°(距離によっては±90°で180°も!)の範囲で受信してしまいます。
そのような赤外線の飛来方向を高精度に特定できるでしょうか?

「できない」と諦(あきら)めたら終わりです。
「入手できる複数の情報を最大限に活用して、その裏に隠された本質を抽出できるアルゴリズム(処理手順)が無いか?」を考えます。

一発の計測では無理だが、複数回の計測により受信角度の範囲が分かり、発信源はその中心の方角にあると推定できる」というアイデアですね。

オムニホイールの操舵性を活かし、その場でぐるぐる旋回させながら、受信できる角度と強度(*3)を記憶していきます。まるでレーダーのようですね。

「言うは易し」ですが、360°を10°刻みで記憶するにも36個の変数が必要です。
int range[36] のような配列に格納すれば、for文を使ってスキャンや集計が簡単になりますね(*4)。

 授業中はアルゴリズムを深堀りする時間が取れないため、ここで、赤外線ビームが飛来する方角を推定するプログラムについて考えてみます。

 赤外線受光素子を搭載したオムニホイールロボットを360°旋回させ、10°刻みで配列 int A[36] に記憶させたところ、

int A[ ] = {
  0,0,0,0,0,0,0,0,0, 
//  0~ 80°
  1,1,1,1,1,1,1,1,1, 
// 90~170°
  0,0,0,0,0,0,0,0,0, 
//180~260°
  0,0,0,0,0,0,0,0,0 };
//270~350°


で初期化した状態と同じだったとします。
ここで、配列中の各値(1/0)は、赤外線の受光有無を表します(*5)。

for( s=0; s<36; s++ ) { 
//開始位置を探す
  if( A[s]==1 )  break;
}
for( e=s+1; e<36; e++ ) { 
//終了位置を探す
  if( A[e]==0 )  break;
}


で、検出開始インデックス s=9, 検出終了インデックス e=18 が得られますから、飛来角度は (s + e)*10/2 = 135°と正しく得られます。

同じアルゴリズムで、

int B[ ] = {
  1,1,1,1,1,1,1,0,0, 
//  0~ 80°
  0,0,0,0,0,0,0,0,0, 
// 90~170°
  0,0,0,0,0,0,0,0,0, 
//180~260°
  0,0,0,0,0,0,0,1,1 };
//270~350°


の場合はどうでしょうか。
s=0, e=7 となり、飛来角度を35°と推定してしまいます。
実際は 340(-20)°~ 70°の中心値 25°と推定すべきです。

先に終了位置を探しておきましょう。

for( e=0; e<36; e++ ) { 
//終了位置を探す
  if( B[e]==0 )  break;
}
for( s=e+1; s<36; s++ ) { 
//開始位置を探す
  if( B[s]==1 )  break;
}


これで、s=34, e=7 と正しい値が得られますが、最初のデータ A[ ] に対しては s=9, e=0 となって、中心角度を 225°と誤ってしまいます。

やはり、終了位置は開始位置の後に探しましょう。

for( e=0; e<36; e++ ) { 
//先ず終了期間まで進める
  if( A[e]==0 )  break;
}

for( s=e+1; s<36; s++ ) { 
//先に開始位置を探す
  if( A[s]==1 )  break;
}
for( e=s+1; e<36; e++ ) { 
//次に終了位置を探す
  if( A[e]==0 )  break;
}


これで、A[ ] については問題ありませんが、今度は B[ ] に対して、s=34 は良いとして、e=36 で終わってしまいます。

もう一周させましょう。

for( e=0; e<36; e++ ) { 
//先ず終了期間まで進める
  if( B[e]==0 )  break;
}
for( s=e+1; s<36; s++ ) { 
//先に開始位置を探す
  if( B[s]==1 )  break;
}
for( e=s+1; e<72; e++ ) { 
//次に終了位置を探す(最長2周分)
  if( B[e%36]==0 )  break;
}


出ました! お助けヒーロー演算子“%”の登場です!
例えば、2周目で e=40 の時、B[e] は不正アクセスになりますが、B[e%36] と書いて B[4] を正しく参照できます。

これで、B[ ] でも s=34, e=43 となり、((s + e)*10/2) % 360 = 385 % 360 = 25°と正しく求められます。

int C[ ] = {
  1,1,1,1,1,1,1,1,1, 
//  0~ 80°
  0,0,0,0,0,0,0,0,0, 
// 90~170°
  0,0,0,0,0,0,0,0,0, 
//180~260°
  0,0,0,0,0,0,0,0,0 };
//270~350°


に対しても、s=36, e=45 で 45°と一応(*6)正しく機能します。

(;´▽`A`` ふぅ、安心ですかぁ?

 さらに考えるならば、自然界の計測値にはノイズ混入が付き物であり、赤外線も壁などで乱反射して届いたり、部品などに当たって瞬間的に遮蔽(しゃへい)されたりするでしょうから、所々0⇔1が入れ替わることも前提にした方が信頼性が高まります。

サンプルプログラム[IRSeekerSt2], [IRSeekerSt3]では、「同じ値が3連続以上」のような条件を位置検出に加えていますが、この仕様の是非はともかく、いい加減に作ったバグだらけのコードに見えますので(*7)、前例の配列仕様に則った改良例を記しておきます。

int D[ ] = {
  0,1,1,1,1,0,1,1,1, 
//  0~ 80°
  0,1,1,0,0,0,1,0,0, 
// 90~170°
  0,0,0,0,1,0,0,0,0, 
//180~260°
  0,0,0,0,0,0,0,1,0 };
//270~350°


のようなノイズ混入データに対して、

for( e=0; e<36; e++ ) { 
//先ず終了期間(e=12)まで進める
  if( D[e]==0 && D[(e+1)%36]==0 && D[(e+2)%36]==0 )  break;
}
for( s=e+3; s<72; s++ ) { 
//先に開始位置(s=37)を探す
  if( D[s%36]==1 && D[(s+1)%36]==1 && D[(s+2)%36]==1 )  break;
}
for( e=s+3; e<72; e++ ) { 
//次に終了位置(e=48)を探す
  if( D[e%36]==0 && D[(e+1)%36]==0 && D[(e+2)%36]==0 )  break;
}


では s=37, e=48 となり、((s + e)*10/2) % 360 = 425 % 360 = 65°と求まります。感覚的にも合いそうですね。

 どうです? この程度のことでも、突き詰めると高度でしょう?
ゲームのバグに文句を言う前に、抜け目の無いプログラムを書くことの難しさを知ってください。
そして、失敗が成功を生むように、バグをたくさん出して成長してください。

 赤外線の飛来角度が推定できたならば、姿勢センサーを搭載して(*8)、その方角に向き直る可愛らしいペット(怖い軍事ロボット?)の完成です。

プログラム中、MPU6050::getMotion6(&ax, &ay, &az, &gx, &gy, &gz) により、z軸(鉛直方向)周りでの(水平回転)角速度 gz を取り出し、これを微少単位時間毎に積算(高校数学の時間積分)して角度を算出しています(*9)。

 次回に続け、さらに赤外線の追従アルゴリズムを探求します。


*1 本当はレーザー砲と言いたいところですが、発砲のタイミングで後退りする演出(慣性の法則・作用反作用の法則)が入っていますので、重量物(物理的な弾)を発射させていると妄想すべきでしょう。

*2 レーザー光/赤外線なら、殆ど拡散せず、遠くの壁に小さなスポットを映します。
 例えば、CDのピックアップ部(読み取り装置)には、盤上の微小ピット(1μm以下)を読み取るために、赤外線レーザー(波長780nm)が使われています。

*3 実際は強度ではなく、赤外線コマンドの受信データ長(rawlen)を記録します。
 受信確度が高いほど、完全なデータ長100に近い値が得られることを利用します。

*4 例えば、a[100]のうち、最大値をmaxに記憶するには、max=a[0]; for(i=1; i<100; i++){if(max < a[i]) max=a[i];} で、
 平均値をavgに記憶するには、sum=0; for(i=0; i<100; i++) sum+=a[i]; avg=sum/100; です。

*5 実際のサンプルプログラムでは、赤外線受光強度の指標となる受信データ長が90以上か否かで判定しています。

*6 一応と言ったのは、s=36 を直接的に見つけたのではなく、一周して見つからなかったから s=36 で止まった結果であり、それでも、
どこかに必ず‘1’がある前提ならば、アルゴリズム上 s=0 を見過ごしたことになるので、ちょうど問題なく機能する特例のケースになるからです。
 このようなトリッキーなアルゴリズム仕様は、何か改変をする際にバグを生み易いので、スッキリ美しい(無駄のない)コードではあるものの、安全上は好ましくありません。

*7 思考が複雑になるので、テキストでは触れてない所ですが、バグの解析に時間を取られた身として、開発側に苦言を伝えておきます。

*8 元より、この方法論により、360°旋回スキャンや10°刻み計測ができていますので、本当は話の順番が逆なのですが。

*9 姿勢センサーについては、2年目コース2022年1月の記事を参照。
 http://higashi-fukuma-robot.blogspot.com/2022/01/


2. 5月の課題


 <スタートアップ(全コース)>
  特にありません

 <プライマリーコース>
  - オリジナル図形プリント
  http://robocobo.sakura.ne.jp/blog/HW/RobotP2205-Q.pdf

 <ベーシックコース>
  - 上記授業内容を精読する(概ね3年生以上/低学年は補助の下で)
  - オリジナル課題プリント(3面図+設問)
  http://robocobo.sakura.ne.jp/blog/HW/RobotB2205-Q.pdf

 <ミドルコース>
  - 上記授業内容を精読する
  - オリジナル課題プリント(3面図+設問)
  http://robocobo.sakura.ne.jp/blog/HW/RobotM2205-Q.pdf

 <アドバンスコース>
  - 上記授業内容を精読する
  - オリジナル課題プリント(見取図+設問)
  http://robocobo.sakura.ne.jp/blog/HW/RobotA2204-Q.pdf (4月配信済み)

 <プロ1年目コース>
  - 上記授業内容を精読する(該当テキストページを見ながら)

 <プロ2年目コース>
  - 上記授業内容を精読する(該当テキストページを見ながら)

  - CdS光センサーを使った図2-6(1日目p.17)の回路で、ボリュームインジケータ[LED5_Vol1_bar_answer]をベースに、
  様々な明るさの下で実験しながら、analogRead値 val による分岐条件を決め、
  暗闇~室内照明~日光下で0~5個のLEDが点灯する照度計(明るさメーター)に仕上げる

  - 7セグLEDを実装した形態(2日目)に、図2-6(1日目p.17)のCdS光センサー+10kΩの分圧回路を足し、
  LED8セグメント以上で高分解能表示する照度計にグレードアップする

  - 7セグ表示する2日目p.16のボリュームセンサ[_7segVol]をベースに、
  A5/GNDピンに電池(≦5V)の+/-を繋いだときの電圧[mV]を表示する電圧計に変える。

 【ヒント-照度計】
  A0入力は下図の位置です。CdS抵抗は凡そ10kΩ(暗闇)~100Ω(日光)で変化します。
  このとき、A0電位は、暗闇で 10k/(10k+10k) = 50%、日光で 100/(100+10k) = 1%
  に分圧されます。それを analogRead(A0) で1023段階に読むのです。

  <GND>---[CdS抵抗]---<A0>---[10kΩ抵抗]---<5V>

 【ヒント-照度計7セグ版】
  2日目p.10の"H"表示[_7segTest2]を参考に、7セグLEDを任意のパターンで表示するsetLed()関数を使います。

 【ヒント-電圧計】
  analogRead(A5) でA5入力電圧0~5Vを0~1023で表示するので、analogRead(A5) * 5000 / 1023 でmV表示に変換できます。
  但し、計算途中でint型整数(~32767)がオーバーフローする為、* 5 で近似するか、分かる人はlong型整数で計算します。
  電池は1~3本(4.5V)まで下図のように繋ぎます。5V以上を入力しないこと。

  <GND>---[- 電池 +][- 電池 +][- 電池 +]---<A5>


 <プロ3年目コース>
  - 上記授業内容を精読する(該当テキストページを見ながら)


3. 4月の解答


 <プライマリーコース>
  http://robocobo.sakura.ne.jp/blog/HW/RobotP2204-A.pdf
 <ベーシックコース>
  http://robocobo.sakura.ne.jp/blog/HW/RobotB2204-A.pdf
 <ミドルコース>
  http://robocobo.sakura.ne.jp/blog/HW/RobotM2204-A.pdf
 <アドバンスコース>
  翌テーマ1ヶ月目(来月)に配信します


4. 今後の授業スケジュール


◆全教室8月第1回目を一週ずつ前シフト(盆休み)します。

――――――――――【佐藤教室長】――――――――――

[東福間]第1・3土原則<学習ルームでこぼこ>
   - 13:30~ ベーシック/プライマリ
   - 15:30~ ミドル
   - 17:30~ アドバンス

 ⇒ 6/4, 18,  7/2, 16,  7/30※, 8/20

 ※8/6→7/30シフトします

[東福間プロ]第2・4日原則<学習ルームでこぼこ>
   - 10:00~ プロ1年目
   - 13:00~ プロ2年目
   - 16:00~ プロ3年目

 ⇒ 6/12, 26,  7/10, 24,  8/7※, 28

 ※8/14→8/7シフトします

[中間]第2・4土原則<なかまハーモニーホール>
   - 13:30~ ベーシック/プライマリ
   - 15:30~ ミドル
   - 17:30~ アドバンス/プロ1・2年目

 ⇒6/11 第1回 3F会議室4(和室)
  6/25 第2回 3F会議室2
  7/9, 23,  8/6※, 27

 ※8/13→8/6シフトします

[小倉北]第1・3日原則<ムーブ>
   - 10:30~ ベーシック/プライマリ
   - 13:00~ ミドル/プロ1年目
   - 14:00~ プロ2年目
   - 15:00~ アドバンス

 ⇒6/ 5 第1回 5F小セミ
  6/19 第2回 5F小セミ
  7/3, 17,  7/31※, 8/21

 ※8/7→7/31シフトします

――――――――――【中野教室長】――――――――――

[八幡東]第1・3土原則<レインボープラザ4F>
   - 13:30~ ベーシック/プライマリ
   - 15:30~ ミドル
   - 17:30~ アドバンス

 ⇒ 6/4, 18,  7/2, 16,  7/30※, 8/20

 ※8/6→7/30シフトします

[小倉南]第2・4日原則<総合農事センター2F>
   - 10:30~ ベーシック/プライマリ
   - 13:00~ ミドル
   - 15:00~ アドバンス

 ⇒ 6/12, 26,  7/10, 24,  8/7※, 28

 ※8/14→8/7シフトします


5. お知らせ

1) 第12回ロボット教室 全国大会 8/27(土) 東京大学 安田講堂

 2年ぶりに東大で開催されます。案内冊子(紙面)はありませんので、PDFをお目通し下さい。
 http://robocobo.sakura.ne.jp/blog/convention/RobotConv2022.pdf

 ◆アイデアコンテスト (全コース) :予選応募Web申込み 画像・プレゼン動画
 ◆テクニカルコンテスト(アドバンス):予選応募Web申込み 動画(2分以内)

 《全国大会 エントリー 6/13(月)12:00~7/4(月)17:00》
 《全国大会 観覧申込み 6/13(月)12:00~定員まで》
  http://kids.athuman.com/robo/event/convention/2022/


2) スペシャル地区イベント 8/12(金) 福岡市科学館サイエンスホール

 全国大会に先立ち、地区イベントも開催されます。(全国大会の予選ではありません)
 今年はベーシック/ミドルコース向けに改造レース部門が新設されます。
 発表はちょっと…という人はこちらにエントリーするのも面白いかも!?

 ◆アイデア発表会(全コース)     :抽選応募Web申込み ロボット画像
 ◆改造レース部門(ベーシック/ミドル):抽選応募Web申込み

 《地区イベント エントリー 6/13(月)12:00~7/4(月)17:00》
 《地区イベント 観覧申込み 6/13(月)12:00~定員まで》
  http://kids.athuman.com/robo/event/convention/2022/


3) 5教室合同アイデア表明会
 いきなり全国大会はハードルが高いですので、まずは地区イベントで、発表をするも聞くも、あまり気負わず親子で楽しみましょう!

 その前に、小倉北教室の昼休み時間に説明会・アイデア表明会を開催しますので、親子で是非ご参加下さい。
 先ずは宣言しちゃって、やる気になってみよう! 君だけのロボットをひねり出そう!

 ■6/5(日) 12:10-12:50 男女共同参画センター(ムーブ)5F 小セミ
 【大会説明会】過去の大会動画と、アイデアの出し方(連想・アイデアシートの使い方)紹介

 ◇必要に応じ印刷して使用下さい
 《連想シート》
  http://robocobo.sakura.ne.jp/blog/convention/ConceptSheet2022.pdf
 《アイデアシート》
  http://robocobo.sakura.ne.jp/blog/convention/IdeaSheet2022.pdf

 ■6/19(日) 12:10-12:50 男女共同参画センター(ムーブ)5F 小セミ
 【アイデア表明会】「こんな(動きの)ロボット作るつもりです」程度の意志表明
          1人2分程度、アイデアシート等で発表(設計図やロボット披露も可)


4) 5教室合同テクニカルコンテスト研究会
 エントリーマシンを開発するアドバンス生向けに、下記の教室時間を開放します。
 奮って参加下さい!
 - アドバンス授業時間外での入退室時間は自由です
 - 他教室への振替利用には事前連絡ください
 - 時間延長利用には事前連絡不要です
 - エントリー者の振替手数料は頂きません
 - エントリー者の6月分カリキュラムは割愛し、マシン開発に代えるものとします
 - アドバンス修了1年未満(6/E時点)の修了生・プロ生(15歳以下)も資格者ですので、6月教室での指導を9,900円にて承ります(家庭内開発でも可)

 ・6/ 4土 東福間    でこぼこ  17:30-21:00
 ・6/ 4土 八幡東レインボープラザ4F 17:30-21:00
 ・6/ 5日 小倉北     ムーブ5F 13:00-16:30
 ・6/11土 なかまハーモニーホール3F 17:30-21:00
 ・6/12日 小倉南  農事センター2F 13:00-16:30
 ・6/18土 東福間    でこぼこ  17:30-21:00
 ・6/18土 八幡東レインボープラザ4F 17:30-21:00
 ・6/19日 小倉北     ムーブ5F 13:00-16:30
 ・6/25土 なかまハーモニーホール3F 17:30-21:00
 ・6/26日 小倉南  農事センター2F 13:00-16:30


5) 全国大会への教室としての取り組みスタンス
 コンテストへの出品・発表は、創作力や理解力など、ロボットの総合力を一気に高めるチャンスです。
 ご家族行事として参加下さい。

 特にアドバンス生は、原則として全員テクニカル部門に応募して下さい。
 ミッション達成型の競技ですので、戦略と設計思想が肝です。皆さんの知力を思う存分発揮しましょう!
 (アイデア部門への出品に代えてもOKですので、希望者はお知らせ下さい)

 地区イベントでは、ベーシック/ミドル生向け改造レース部門も新設されます。
 「オリジナルロボは難しいけど、大会には参加してみたい!」
 そんな人は改造レース部門へエントリーしてみましょう。
 (コース詳細は非公開な為、練習コースは用意せず、必要な調整を授業時間に検討します)

 どの部門の挑戦者も、6月テキストのカリキュラムを割愛して、コンテスト作品に注力しても構いません。

 《各レースの概要》

 ◆地区イベント/改造レース部門(ベーシック)『ゴールを目指せ!ロボフィッシュ』
  6月ロボット「ロボフィッシュ」で1.5m先のゴールエリアを目指します。
  途中には障害物と凸凹床があり、進めなくなったり、コースアウトしないよう工夫します。

 ◆地区イベント/改造レース部門(ミドル)『ピタッと止まれ!ロボザウルス』
  6月ロボット「ロボザウルス」で1m先のゴールエリアに自動停止(プログラミング)します。
  途中には障害物と凸凹床があり、進めなくなったり、コースアウトしないよう工夫します。

 ◆全国大会/テクニカルコンテスト(アドバンス)『運んで立てろ!ロケット発射台』
  保管エリアに寝かせたロケット(トイレットペーパーの芯)を約1m先の発射台(パーツケースの蓋)に運んで立てる競技です。
  1分の制限時間内に立てたロケットの本数を競います。
  (トイレットペーパの芯を3,4本ご用意ください)


6) 小倉南教室 会場変更の予告
 8月~2月上旬(予定)まで農事センター2Fが耐震工事の為、利用できなくなります。
 そこで、下記の通り開催場所・施設を変更させて頂きたく、
ご不便をおかけいたしますが、何卒ご協力お願いいたします。
 時間帯に変更はありません。

  8月 7日・28日 農事センター1F A区画(エレベータホール目の前)
  9月11日・25日 山田緑地 映像室
 10月 9日・23日 山田緑地 映像室
 11月13日・27日 山田緑地 映像室
 12月以降は未定

 9,10,11月は【農事センター】→【山田緑地】へ変更になります。

 北九州市立 山田緑地 
  〒803-0865 小倉北区山田町 
   有料駐車場あり(300円/日)


7) 4月課題 高得点者  []内は教室と学年

 ◆プライマリ【6名平均 図形4.5】
   5点…亀平[八幡東1], 坂本[八幡東3], 林田[八幡東1], 山根[八幡東1]

 ◆ベーシック【20名平均 図面2.7+設問2.2=4.9】
  10点…なし
   9点…眞所[八幡東3], 古場[小倉南3]
   8点…渡辺[小倉南5]
   7点…古川[小倉北3]

 ◆ミドル【23名平均 図面2.9+設問1.8=4.7】
  10点…なし
   9点…なし
   8点…藤津[中間6]
   7点…柴田(直)[小倉北5], 柴田(大)[小倉北5]
   6点…諭[小倉北4]


東福間・中間・小倉北教室 佐藤 / 八幡東・小倉南教室 中野