PR

 第43話で「すごい雑誌に出会った」と『子供の科学』を紹介したところ,「私も子供の頃,読んでいた」とか「当時の科学少年少女にとってはバイブルのような本であった」というメールをいただいた(主に日経ソフトウエア編集部からであるが)。私,文学少年だったのでそんなに有名な雑誌とは存じませんでした。誠文堂新光社の皆様,失礼致しました。しかし,また子供たちが図書館で借りてきた『子供の科学』2,3月号は誰にもページをめくられていないような綺麗さを保っていた。これは,科学離れの影響なのだろうか?

 その2月号にロボカップJr世界大会という記事が出ていた。目を凝らして見るとロボットは全てMindStorms。「こうしろう,こういうのに一度参加してみたら,いいかもしれんな」,「でもそれ,オーストラリアのメルボルンだよ」,「そのうち,近くでも開催されるよ」,「なかなか,富山までは来んよ」,「金沢あたりでなら,あるかもしれんよ」中学入学を控え,何かにつけ現実的になりがちな息子に希望を持たせようとする父である。

2月17日 今日は前回作成したペットロボットのプログラムを作る予定である。



 「プログラム組む前にリモコンでテストしてみられ」と声をかけた。こうしろうがプーリーに輪ゴムを掛けて,リモコンのボタンを押すがロボットは動かない。「こうしろう,ロボットが重たすぎてプーリーでは動かんがやわ。」

 こうしろうと私でロボットを直しはじめた。なぜかこの日は二人とも必死であった。プーリーをやめてギヤで動かすように変更する。私がまごまごしていると,こうしろうが「あっ,それわかる。僕するちゃ」と横から取り上げて,ブロックのポッチの数や穴の数を読んでギヤの組み合わせを考えていく。お互いに初歩的な失敗を早くリカバリーしたいという気持ちがあったのか,テンポよく作業が進み,新型ペットロボットが完成した。



 リモコンで動作を確認すると,ヒュンヒュン走り,左右のモーターを逆回転させるとクルクル回る。犬型ペットロボットという当初の目標に近づいてきた。「安易にプーリーを使ってはいけない。駆動の基本はギヤである」ということを改めて教訓とした。

2月24日 今日こそプログラムを作ろうと,こうしろうに「このロボットはどんな動きをするのか?」とあらためて質問した。「えーっと,あちこち走り回って接近センサーで…」という明確ではない答えに「プログラムを作るには,動作を分解して簡単な言葉で表す必要があるわな,まず,どんな機能が必要か?」と問うと,こうしろうは「うーん」と考えこんでいる。なにか難しく考えているようだ。横から,かずが「走る」と口をはさむ。「そう,その通り。そんな風に単純な言葉で,機能を分解していけばいいんだよ。」かずの良いところは物事を難しく考えないことだ。

かずの教えを基にこうしろうが定義したロボットの動きが以下である。
(1) 走る
(2) 接近センサーで障害物を避ける
  (接近センサーそのものが2つの機能で成り立っているので,この機能は2つに分解される)
  (2)-1.赤外線を出力する
  (2)-2.赤外線の反射を読み取り,障害物を避ける
(3) おしりに付けたタッチセンサーが何かに触れたら,方向を変える
(4) 頭に埋め込んだタッチセンサーが押されたら,しっぽを振る

NQCの場合,これらの機能をそれぞれタスクとしてプログラミングすれば良い。

task main()
{
 SetPower(OUT_A+OUT_C,2);
 OnFwd(OUT_A+OUT_C);
 start send_signal;
 start check_signal;
 start tail_sensor;
 start head_sensor; 
}
task send_signal()
{
 while(true) 
 {
  SendMessage(0);
  Wait(10);
 }
}
int lastlevel;
task check_signal()
{
 while(true)
 {
  lastlevel = SENSOR_2;
  if(SENSOR_2 > lastlevel + 200)
   {
   if (Random(1) == 0)
    {
    OnRev(OUT_C);
    Wait(60);
    OnFwd(OUT_A+OUT_C);
    }
    else
    {
    OnRev(OUT_C);
    Wait(60);
    OnFwd(OUT_A+OUT_C);
    }
   }
 }
}
task tail_sensor()
{
 SetSensor(SENSOR_3,SENSOR_TOUCH);
 while (true)
 {
  if (SENSOR_3 == 1)
  {
   if (Random(1) == 0)
   {
   OnRev(OUT_A);
   Wait(60);
   OnFwd(OUT_A+OUT_C);
   }
   else
   {
   OnRev(OUT_C);
   Wait(60);
   OnFwd(OUT_A+OUT_C);
   }
  }
 }
}
task head_sensor()
{
 SetSensor(SENSOR_1,SENSOR_TOUCH);
 while (true)
 {
 if (SENSOR_1 == 1)
 {
  SetPower(OUT_B,1);
  OnFwd(OUT_B);
  Wait(100);
  Float(OUT_B);
  }
 }
}

 仕様をキチンとまとめてからプログラミングを開始したせいか,こうしろうは迷い無く編集を進めていった。しかし,コンパイルをするとエラーがいくつか出た。原因はタブでちゃんと字下げを行っていないため,{ と } の数が一致していないことだった。「無駄なエラーを出さないためには,タブを入れて,プログラムを見やすくすることだよ」とアドバイスした。

 明日はスキーで朝が早いので,今日はここまでとした。次回はテストである。