OGIMOノート~家族のためのモノづくり~

OGIMOテックノート ~家族のためのモノづくり~

重度障害の息子を持つ父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具/ロボット関係の製作記録、思った事を残していきます

【かんたん工作】 おもちゃ改造してワンワンぬいぐるみを暴走させてみた

本記事で伝えたいこと:大事なのは技術力じゃなくて「解決したい課題」に対する着眼力・アイディア力
f:id:motokiinfinity8:20191002194703j:plain

製作動機

f:id:motokiinfinity8:20190916094422j:plain

知的にも遅れのある息子氏。4歳を過ぎても周囲に対して鈍感で、何もせずぼーっとしている様な印象でした。

子供にとって好奇心こそ重要!
好奇心があってこそ、子供の成長は一気に加速する!

そう考えた我々両親は息子の好奇心をこじ開けるため、お気に入りのオモチャを探しまくってました。
そんな中、ようやく好みのおもちゃが見つかってきたのですが…
特に触りにいく事もなく、ただ見ているだけ…

息子に限らず重度障碍を抱えた子供は、ハンデがあり自分で体をうまく動かせないが故に人に介助してもらう機会が多いため、どうしても受け身がちになってしまう
やはり、そこから次の世界へ進み、
自分の意志を出していくきっかけを親として作っていきたい!

そんな試行錯誤の中で、
「息子が手を出すきっかけを作ってみよう!」
という取り組みで、息子のお気に入りの「ワンワン鳴くぬいぐるみおもちゃ」を改造してみました。

ベースはこのおもちゃシリーズ

あかちゃんシリーズ ビーグル ぬいぐるみ

あかちゃんシリーズ ビーグル ぬいぐるみ

  • メディア: おもちゃ&ホビー



[改造ポイント]
・ボタンを押した時だけワンワン鳴く
→ 「ボタンを押す」という自分のアクションで、動きが変わるという体験を楽しんで学んでもらう
・ただ動くのではなく激しく動く
→ 子供は「静」と「動」の変化が激しいほどウケる傾向があるので、これをもっと明確にしたら鈍感な息子でも反応するかも


物理スイッチを通して、本人のやる気スイッチを引き出す!

これを目指して取り組みました!



完成品

ボタンを押すと高速で動きだすワンワンおもちゃが出来ました!
普段の150%~200%の元気さで叫びます!


ちなみに、ワンワンぬいぐるみだけでなく、ニャンニャンぬいぐるみ等への応用も可能です。


息子の反応もものすごく良好で、1年経った今でも一番のお気に入りオモチャとしてずっと使ってくれています。
また、気軽に持っていけるので、療育園でお友達と一緒に遊んだりもあるし、展示会で出展しても非常に人気な改造おもちゃになりました。

製作方法

まず、「どうやってワンワンを激しく動かしたか?」と疑問に思う方も多いですが、仕組みは簡単です!

単三電池2個で動くおもちゃを
単三電池4個に増やしただけ
です


この発想は、一度ワンワンぬいぐるみを分解した時にひらめきました。

まさかのマイコンなしで、モーター1つで3つのアクションを切り替えるという神設計でした。
そこで分解して気付いたのは
「ん?モーター一つだけという事は……電圧を上げるだけで簡単に速度上がるやん」
という事でした。

※注意
今回は分解の結果、該当おもちゃがマイコンICを使わず、モーターのみを使用していた事が判明したため、上記の様に電池を増やすアイデアが適用できました。
万が一マイコンICが付いているおもちゃの電池を増やしてしまうと、最悪の場合 マイコンICが壊れてしまいますので、ご注意ください。

製作詳細

改造前後の製作図は以下です。

f:id:motokiinfinity8:20191002011222j:plain

部品名 個数 購入先
あかちゃんシリーズ ワンワンぬいぐるみ 1 Amazon
押しボタンスイッチ(モーメンタリ)赤 1 Marutsu
ケース(プラスチック製タッパ) 1 ダイソー
ELPA スイッチ&カバー付電池ボックス単3形*2本 UM-SC32NH 2 Amazon


以下は各部分の加工写真です。


・スイッチ端子に半田付けで配線を接着します
f:id:motokiinfinity8:20191002014334j:plain

・ボックスの構成。灰色線の中に2本配線が入っており、
 片側(線A)をスイッチへ、片側(線B)を電池ボックスの黒線に繋げています。
f:id:motokiinfinity8:20191002014428j:plain

・半田付けした場所は、絶縁テープなどでグルグル巻きします。
f:id:motokiinfinity8:20191002014530j:plain

・ぬいぐるみは、電池用のフタを開けて、おしりの方の単三電池プラス端子を線A、単三電池マイナス端子を線Bで半田付けします。
f:id:motokiinfinity8:20191002014820j:plain

・端子は面積が大きくて半田が溶けにくいので、はんだごてでじっくり熱を与えて、先に端子上にはんだの山を作るとやりやすいです!
f:id:motokiinfinity8:20191002015009j:plain



終わりに

本記事で書いた内容は、電気技術者にとってはすごく簡単な内容ですし、技術的にはなんら難しくはありません。だからこそ、初心者の方でも
「これなら、自分でも作れるかも」
「自分の子供にも作ってあげよう!」

と思えて、モノづくりの最初の一歩に繋がればいいなぁ、
と実験的に書いてみました。

…とはいえ、半田ごてを使ってる時点で初心者にはハードル高いかもしれないなぁ、と気付いてしまい、
そこは反省です。。。

技術者って、ついつい『高度な技術を使ってる方が価値がある』と手段前提の発想
になりがちなんですよね。
私自身もその発想に陥る事もありますし、実際にそれが勉強や研修目的であるならば非常に有効だと思います。


しかし、実際に誰かのためのモノを作る事を考えた時には
高度な技術が不要な事も多いし、
何より短期間で価値(本当に喜んでもらえるか)を確認する事が大事!

なので、
解決したい課題にダイレクトにつながりつつ
技術難度が低く、シンプルに、誰でも簡単に作れるモノ

もまた、非常に価値になると思います!

それに気付かせてくれた「暴走ワンワンおもちゃ」

是非とも一度作ってみてください!(^^)!

単身赴任の寂しさ解消!? 分身ロボットによる遠隔家族団らんチャレンジ

f:id:motokiinfinity8:20190915193059j:plain

私自身の活動テーマである「家族のためのモノづくり」

その一環として、昨年11月より使用させて頂いております
分身ロボットOriHimeの活用事例
について、OriHimeの製作元である
オリィ研究所 | オリィ研究所。株式会社オリィ研究所はOriHime-分身ロボットを開発・提供しています。様の公式ブログに執筆させて頂きましたので、
本ブログでも紹介!

・私の簡単な自己紹介 (「家族のためのモノづくり」に至った経緯)
・分身ロボットを使う事になったきっかけ
・活用事例①
 単身赴任生活において分身ロボットを活用した遠隔団欒は成立するか?

について、昨年11月での取り組みを記載しました。
今後、分身ロボットの我が家での活用事例について公式ブログ様で紹介させて頂ければ、と思います。


avatarworld.info


Twitter等で「家族のためのモノづくり」としての活動を発信し続けていった中で繋がった分身ロボットとのご縁、
大変ありがたいです!

車椅子を「ワクワク新幹線」に変える M5Stack×スピーカ×イルミモジュール製作

f:id:motokiinfinity8:20190831220648p:plain

はじめに

私は、障害を持った息子や家族が、日々楽しく過ごしていくためのサポートとして電子機器やおもちゃ等の「家族のためのモノづくり」として活動しています。そんな自分が製作していたものをtwitter等のSNSに発信し続けていたところ、
世界ゆるスポーツ協会 澤田 智洋さんより
「特別支援学校をもっと面白くするプロジェクトを一緒にやりませんか?」
とお声がけ頂き、
『特別支援学校の特別おもしろ祭り』
にスタッフ側として参加させて頂く事になりました!!

特別支援学校の特別おもしろ祭り

8/18 東京・府中市にある支援学校・けやきの森学園 で開催された
『特別支援学校の特別おもしろお祭り』

普通の学校の夏祭りではなく、
未来を感じるワクワクする技術・コンテンツをたくさん結集して特別支援学校の新たな可能性を提示するという超クリエイティブなイベント!   
特別おもしろい『スポーツ』『食』『音楽』『ファッション』『イタズラ』『仕事』『トイレ』『乗り物』『ディスコ』の合計9個のブース。
協賛4団体、協力15団体、
スタッフ150人以上、お客さん400名というすごい規模!

テレビのニュースでも取り上げられてました!
www.news24.jp


私の製作物に関して

きっかけ

今回私が担当させて頂いたのが、「特別面白い乗り物」ブース
その担当メンバーで議論したところ、
 「電車好きな多様な男子たちが多く参加する事が予想されるため
  普段の自分の車椅子をワクワクする様な電車にしてみたい」

という

『ウィルチェア・トレイン
 (Wheelchair Train)』

の構想が持ち上がりました。

「普通の乗り物に移乗困難なな子供でも楽しめ、
 普段の自分の車椅子が一日限りのワクワク乗り物に変身!」

のコンセプトが気に入り、夏休み期間を最大限使って製作に没頭しました!


[要求仕様]
 ・何よりも電車感がある事(見た目や音など)
 ・普段の車椅子・バギーに装着&脱着する事が容易である事
 ・指定コースを走行する想定で、発車時・停車時にアナウンスが欲しい。
  また、行中にモードが切り替わる事 (走っているとドンドン変化していく)
  ただし、車椅子などの制御情報(操作ボタンやタイヤエンコーダ)は使えない前提。
  (どんな車椅子が来るか分からないため)
 ・当日のお手伝いスタッフ(技術知識なし)でもお手軽に操作できる

完成品

当日はドクターイエロー版」「新幹線はやぶさ版」の二種類を作成しました。

はやぶさ版を歩行器(非電動)に取り付けた動画がこちら。


本番ではたくさんの子供たちの車椅子に取り付けて、コースを走行して楽しんで貰いました!
好きすぎた子供は、乗り物にすら乗らず新幹線部分を手持ちで楽しんでくれてました(笑)

手動バギーや手動車いすについては、株式会社るーと様(https://root-ca.jp/)が持ってこられた簡易電動ユニット CarryLoco 及び その子供の症例に合わせた操作スイッチ を使い、「子供たちが自分の意志で操作する体験」をサポートされていました!

特に電車好きの子供達が自分の作ったモジュールを使い、楽しそうにコースを走ってる姿を見て、すごく胸熱く感じました!
作って良かったー!  

上記動画をTwitter上に投稿したところ、かなり拡散されて、気が付けば 2019/8/31 21:00時点で動画再生回数 3.5万回、いいね2000回以上、たくさんの人に興味を持ってもらい暖かいコメントを頂けたのがとにかく嬉しいですね。

みんなで、子ども達の笑顔、そしてやってみたいという気持ちをを引っ張り出す
暖かい世界だなぁ~

概要仕様

本番コースでの走行を想定して、以下のシナリオでの運用を想定しました。
f:id:motokiinfinity8:20190831222427j:plain


[手順]
・子供の車椅子にモジュールを装着
・コーススタート位置でボタンを押すと「発車アナウンス」が流れる
・ ボタンを押して「ドアを閉める」操作をする
・ 車椅子を前に走らせると「発車音」が流れる
・ 走行中のコース途中で表示変更
・ ゴールが近づくと「停車音」が流れる
・ 車椅子を停止させると「終了アナウンス」が流れる

ハードウェア

今回のコンセプトは、「普段の車椅子に簡単に脱着可能である事」です。なので、制御部や走行状態センシングはモジュール内で完結させる必要があります。更に、当日は大勢の人に取り付ける必要があり、操作の簡易さ/起動の速さ/安定性を加味した結果、マイコンを使ったシステムに決めました。
いつもお馴染み「M5Stack」を中心とした制御モジュールで進めます。


システム構成図になります。
f:id:motokiinfinity8:20190831222500j:plain

M5Stack Grayを使い、全体的な制御 及び 内蔵加速度センサを使っての走行状態センシングをおこないます。また、液晶に電車コクピット映像を映して気分を高めます!

アナウンス音については、M5Stackのスピーカではボリューム不足 かつ 他操作の影響を排除してキレイな音声再生を安定再生させるためDF Player miniモジュール+8Wスピーカを別回路で用意しました。NeoPixel LEDテープはおなじみで、今回は144個/mの密度の高いモノを使い、LEDグラデーションを表現しました。また、長時間の使用に耐えるために、モバイルバッテリーを使用します。NeoPixel LEDテープは非常に大きな電流(2A以上)を流すため、2.4A出力のモノを使いました。

完成したモジュールは以下です。すべてを簡単に持ち運べる様に3Dプリンタで制御部分の外装を作りました。



新幹線の筐体ですが、柔軟に取り付け・取り外しが可能な様に、段ボールタイプを使用しました。

f:id:motokiinfinity8:20190831223412j:plain

こちらの市販品を購入 & 組み立てして、背面部に荷物運搬用のロープ&マジックテープを取り付けました。車椅子へは背面でくくりつける形で固定します。なお、モジュールは新幹線の上に配置しました。

ソフトウェア

走行検出/モード切替について

今回の一番の悩みは、走行中でのモード切替方法。
せっかくなので「自分が動いた事によって動作が変わったんだという達成感」を持って欲しかったので、
一定時間でモード自動遷移する案は保留。

カメラやタイヤエンコーダ情報を使ってオドメトリを取得し自己位置認識を行い、一定場所に到着したらモードが切り替わる、という案も検討しましたが、残念ながら本番当日までコース試走が困難であったため、安定性を優先してこの案も保留。


という事で、ここはシンプルに
・走行開始有無はモジュールの加速度センサで検出
・モード切替はジャイロセンサからのYAW角情報をもとに、スタート時点からの回転方向の変化(例えば90度曲がった場合)に行う
・ゴール到達は、ボタン長押しで手動表示 (次回以降の課題)

 
としました。
※次回は、ライントレース等によるコース認識や、Jetson Nano等を使った自己SLAMにもトライしてみてみたい!

発進検出

M5Stack内部の加速度センサーの値を取得しました。
モジュールの取り付け方法が相手の車椅子に応じて異なる事が予想されたため、
 ・X,Y,Zどの方向に対しても一定以上の閾値を一定期間(800ms以上)超えた場合
と定義して行いました。

幸いな事に、電動車椅子駆動時には必ず振動が発生するので、うまく発車/停車検出できました

※課題として、車椅子の種類によっては移動時の振動が少なく検知できないケースもあったため、
 走行/停止の閾値判定をキャリブレーションする仕組みはあっても良かったかなぁ。

旋回検出

これが曲者でした。
一般的にRoll/Pitch角の検出は重力の変化が起きるのでやりやすいのですが、
Yaw角検出は難しいのです。

ちなみに、M5Stackのサンプルコードである
MPU9250BasicAHRS
を使っても、YAW角は不安定でした。

そこで様々に調査した結果、M5Stack内部で使用している MPU9250という加速度センサは
バイス内部でDMPというYAW角算出のハード回路を有していますので、
加速度/ジャイロから計算するのではなく、ハードレジスタを読み出す形で行います。



これに対応したライブラリが以下にあるので、これを M5Stack用に改修してやるイメージです。
github.com


M5Stackへの適用方法は以下を参照ください。一部ライブラリの書き換えは必要になります。

qiita.com

#include <M5Stack.h>
#include <NeoPixelBrightnessBus.h> // instead of NeoPixelBus.h
#include <SparkFunMPU9250-DMP.h>


MPU9250_DMP IMU;


double comAccX,comAccY,comAccZ=0;  
double comAccX_old,comAccY_old,comAccZ_old=0;  
double gravityX, gravityY, gravityZ=0;

const double alpha = 0.9;//lowpassfilter
uint32_t timer;

float y_org=0.0;
float p_org=0.0;
float r_org=0.0;
float y_mod, y_mod_old, y_raw = 0.0;
float p_mod, p_raw = 0.0;
float r_mod, r_raw = 0.0;
float y_base = 0.0;


(中略)

void setup(){
    M5.begin();
    dacWrite(25, 0); // Speaker OFF
    Serial.begin(115200);

    Wire.begin();
    if (IMU.begin() != INV_SUCCESS){
      while (1){
         Serial.println("Unable to communicate with MPU-9250");
         Serial.println("Check connections, and try again.");
         Serial.println();
         delay(5000);
       }
    }
    IMU.setSensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);
    IMU.setGyroFSR(2000); // Set gyro to 2000 dps
    IMU.setAccelFSR(2); // Set accel to +/-2g
    IMU.setLPF(5); // Set LPF corner frequency to 5Hz
    IMU.setSampleRate(10); // Set sample rate to 10Hz
//    IMU.setCompassSampleRate(10); // Set mag rate to 10Hz

    IMU.dmpBegin(DMP_FEATURE_6X_LP_QUAT | // Enable 6-axis quat
               DMP_FEATURE_GYRO_CAL, // Use gyro calibration
              10); // Set DMP FIFO rate to 10 Hz
 
}

void loop() {

  // Check for new data in the FIFO
  if ( IMU.fifoAvailable() ){
    // Use dmpUpdateFifo to update the ax, gx, mx, etc. values
    if ( IMU.dmpUpdateFifo() == INV_SUCCESS){
      // computeEulerAngles can be used -- after updating the
      // quaternion values -- to estimate roll, pitch, and yaw
      IMU.computeEulerAngles();

      // 前値からの差分が0.5°以内の変動は温度ドリフト分として 原点想定位置(y_org)を更新
      float y_raw_old = y_raw;
      y_mod_old = y_mod;
      y_raw = IMU.yaw;
      if(abs(y_raw-y_raw_old) < 0.5) y_org += (y_raw - y_raw_old);
      if(y_raw-y_raw_old > 355.5)    y_org  += (y_raw - y_raw_old)-360;
      if(y_raw-y_raw_old < -355.5)   y_org  += 360+(y_raw - y_raw_old);
      y_mod = IMU.yaw   - y_org;
      if(y_mod >= 360) y_mod -= 360;
      if(y_mod < 0) y_mod += 360;
      r_mod = IMU.roll  - r_org;
      if(r_mod >= 360) r_mod -= 360;
      if(r_mod < 0) r_mod += 360;
      p_mod = IMU.pitch - p_org;
      if(p_mod >= 360) p_mod -= 360;
      if(p_mod < 0) p_mod += 360;

//      Serial.print("R/P/Y: " + String(r_mod) + ", "
//            + String(p_mod) + ", " + String(y_mod)+ "   ");
    }
  }
    
   // 加速度センサのデータ受信
   acc_val_max = 0;
   //if ( IMU.dataReady()){
     IMU.update(UPDATE_ACCEL | UPDATE_GYRO | UPDATE_COMPASS);
     //printIMUData();

    double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
    timer = micros();

    /*速度を求める*/
    // 重力加速度を求める
    gravityX = alpha * gravityX + (1 - alpha) * IMU.calcAccel(IMU.ax);
    gravityY = alpha * gravityY + (1 - alpha) * IMU.calcAccel(IMU.ay);
    gravityZ = alpha * gravityZ + (1 - alpha) * IMU.calcAccel(IMU.az);

    // 補正した加速度
    comAccX = IMU.calcAccel(IMU.ax) - gravityX;
    comAccY = IMU.calcAccel(IMU.ay) - gravityY;
    comAccZ = IMU.calcAccel(IMU.az) - gravityZ;

    velX = velX + (comAccX + comAccX_old)/2*dt;
    velY = velY + (comAccY + comAccY_old)/2*dt;
    velZ = velZ + (comAccZ + comAccZ_old)/2*dt;
   
    comAccX_old = comAccX;
    comAccY_old = comAccY;
    comAccZ_old = comAccZ;

    // 動いているときのみ点灯
    //if(comAccX > 0.02 || comAccX < -0.02 || comAccY > 0.02 || comAccY < -0.02 || comAccZ > 0.02 || comAccZ < -0.02){
    if(comAccX > 0.02 || comAccX < -0.02 || comAccY > 0.02 || comAccY < -0.02){
    //if(comAccY > 0.03 || comAccY < -0.03){
      move_flg = true;
      g_stopping_time = millis();  //時間リセット
    }else{
      move_flg = false;
      g_moving_time = millis();  //時間リセット
    }





}



上記以外のコードについては、
 ・状態遷移の記載
 ・LEDユニットの点灯処理
 ・スピーカ再生音設定
に関しては、過去のソフトウェアを流用していますので、特にブログに特記なしとします。
(もし興味がありましたら、個別にお問い合わせください)


最後に

息子のために作ってきた各種工作品、これが他の子供達の笑顔に繋げられるのかと思うと…
なんだか感慨深いです。。。

息子のためにモノづくりを始め1年半。趣味の活動が、多くの子供たちを喜ばせる事に繋がるなんて…
エンジニアとしての幸せなんやろなぁ、って思います。
モノを作るのは純粋に楽しい。
色々と苦労を乗り越えて、完成した時・思い通り動いた時の達成感は堪らない。
だけど、作った満足感だけで終わるのでなく、その先にある
「自分が作ったものが誰かの役に立つ嬉しさ」
「誰かをちょっぴり笑顔にする楽しさ」

を自分は大事にしていきたいな(^-^)

残りの夏休み宿題をこなしている中で、夏休みの絵日記を書いて貰ったら、
父「この夏休み、何が一番楽しかった?」
娘「お父さんと東京にいったときの、支援学校のお祭り!

娘にとっても色々と得るものが多い東京遠征やったのかなぁ、と思うと、なんだか嬉しい!



そして、これがご縁となり、なんとテレビから取材依頼がくることになったのです!
その話については、また別記事で書きたいと思います。

f:id:motokiinfinity8:20190901021746j:plain

【2019/8/27】フジテレビ~めざましテレビ~ 歩けない息子のため…父の発明品

昨日に突然報告させて頂きました
めざましテレビ」出演の件、
本日8/27(火) に同番組内で放送して頂きました。

youtu.be


・特特祭に向けて製作した
「車椅子をワクワク新幹線に変えるモジュール」

・すべての製作原点である
「息子の歩行リハビリのためのメロディ靴」


を2分半の中で非常に分かりやすく、また暖かくまとめて放送頂く事ができました。
めざましスタッフの方、私の意図を等身大の言葉で丁寧に表現頂き、ありがとうございました!!
そして、非常に大きな反響を頂き、本当にありがとうございました! メッセージや頂いたコメントは随時返信させて頂けばと思います。
※製作番組ディレクター様に相談したところ、放送動画の公開許可を頂きました。

今回の放送では、
『父が障害を息子ためにモノを作る想い』
にピックアップした感動ストーリーになってましたが、

『子供たちやハンデを持った方と、
その方々の笑顔を引き出そうと取り組む
心暖かい人/面白い人達が
実はこの世界にたくさんいて、
自分自身がモノを作り発信し続けた事で、
その世界を知る事ができたワクワク感』
点をインタビュー時には多く伝えてました。

ロボット技術で孤独を解消しようと頑張る方達もいる。
障害当事者と一緒に身近な課題を解決するモノづくりを頑張る方達もいる。
パーソナルモビリティの世界を広げて足が不自由でも自由に移動できる世界を作ろうとする人もいる。
ICT技術を駆使してコミュニケーションをサポートしようと情熱を持って取り組む方達もいる。
歩行できない子供が少しでも新しい体験ができる様に地道にリハビリや作業療法に取り組む方達もいる。
子供たちの笑顔を引き出そうと全力で楽しませようとする先生方、大人たち、子供たちもいる
重度の子供たちが自分の意志を示す機会を作ろうと頑張るお母さん達もいる、
障害という社会課題の解消のために、継続的に維持できるビジネス仕組みを作ろうと奮闘している方々もいる


本当に色んな人達が、障害の有無を気にしなくて済む暖かい世界を創ろうとしてるんだなぁ、と思うと、すごく希望が湧いてきます!
それに励まされ続けている我が家だったりします!


2年前は全く知らなかった世界。
障害を持った息子や家族が将来どうなるか分からない不安感、
その不安感を解消するために
息子や家族のために自分達が出来る事が何かを考え、
自分の得意であるモノづくり技術を使ってサポートしようと決意してから、
志願して職種を変えてロボット技術で息子の足代替を作ろうとして、

また個人でのモノづくり活動をはじめつつ、
考え方・視野を変えてとにかく行動していった中で、
たくさんのご縁に恵まれた結果、
知る事ができた新たな世界です。

そして、たくさんの大人と関わるんだけど、ほんと優しい世界。とても居心地いいことが多い。みんなで、子ども達の笑顔、そしてやってみたいという気持ちをを引っ張り出すんです。
そして、その笑顔に僕たち大人もまた頑張ろうって思えるんです!
2年経った今。

すごく感じてるのは、
『世界ってこんなにおもしろかったんだぁ』
という事です。今回の特特祭のテーマがまさに自分で一番体感してます!

だいぶ長文になりましたが、とりあえず想いをつらつら書きました。
とにかく、一区切り!

Maker Faire Tokyo 2019 出展情報 (ブース紹介)


出展情報

8/3(土)~4(日)に東京・ビックサイトで開催される
メーカーイベント Maker Faire Tokyo 2019に
個人として出展
します。

2019年5月のMaker Faire Kyoto 2019に続き、人生2回目の展示会参加になります。

日時 :

2019年
8月3日(土)12:00~19:00
8月4日(日)10:00~18:00

場所

東京ビッグサイト 西3、西4ホール
https://makezine.jp/event/mft2019/


私は、今年5月にMaker Faire Kyotoでの展示コンセプトは同じで、
『家族のためのモノづくり』
というテーマで、昨年から取り組み続けてる 息子や家族のために作った自作リハビリ機器・改造おもちゃを多数展示予定ですー!
アシスティブテクノロジー&キッズ向けのカテゴリーで展示します。

以下が公式サイトでの私のブース説明になります。
ブースは【C-03-05】になります

makezine.jp


また、Maker Faire Tokyo2019 公式ブログに見どころとして弊ブースが紹介されております!!
なんと!ありがたや~!!
個人の取り組みがこうして注目して貰えると嬉しいなぁ~

makezine.jp




展示作品紹介

『実際に触って体験できる』
をコンセプトにしたいと思っていますので、是非とも積極的に遊んでいってください!(特にお子様、大歓迎!)

「あれも見て欲しい」「これも見て欲しい」と欲張った結果、展示物は 合計10点! とにかくたくさん展示してます(笑)


(1) 歩行リハビリを楽しくする「歩くと音の鳴る&光る&振動する靴」

MFK同様に動作デモを含めて現物展示予定。
今回は輸送都合で歩行器は持ってこれないので、代わりの移動サポート機器を用意。
元々は息子用のために子供靴にセンサーを埋め込んでおりますが、今回は展示会用として大人用スリッパに装着 or 手持ちタイプとして疑似体験できる様に準備しています!
是非体験していってください
ogimotokin.hatenablog.com




(2) 【新作】おかん分身ロボット用 遠隔操作オムニ台車

息子が手術入院する事になり、関西に残った妻(おかん)&息子が、分身ロボットを使って当日は説明員として参加、さらに客引き役として遠隔操作で移動できるオムニ台車ユニットも開発しました!
500km離れた自宅から、あたかもその場に来て、自分の意志で自由に動き回る雰囲気を楽しんでもらえれば、と思います。(無事にWifi混信がなければ、ですがw)


※そういえば、作るのに必死で、製作記事を書くのをすっかり忘れてました。後日、製作技術メモを公開しますー


(3) 【新作】電車でGo!コントローラで動かすプラレール

最近電車が好きになってきた息子を喜ばせようとした電車工作品。電車でGo!コントローラでモビリティを動かす事も出来ますが、モビリティは今回輸送が難しかったので、プラレールのみになります。


※こちらも後日製作記事を整理予定



(4) 【開発中】電車ごっこを楽しくするイルミネーション

8月中旬のロールアウトに向けて開発中。まだ途中段階ですが、この機会を使って使用感フィードバックを貰ってみたいため、参考展示します! 特に電車好きの方に体験してもらってのご意見お待ちしています



(5) 【進化】ボタンを押すと暴走するワンワン

実際にボタンを押して触ってもらう体験予定!
前回よりも更に元気に暴走するワンワンを見て、笑ってください!





(6) ワンボタンでじゃんけんが出来るじゃんけん義手

こちらはMFK同様に、動作デモを含めて現物展示予定です。娘とじゃんけん勝負、しましょう!




(7) 電動車椅子の操作練習のための自作ジョイスティック+二輪走行ロボット

操作コントローラ3種類×操作ロボット2種類持っていきます!
操作体験もできますよ!
ogimotokin.hatenablog.com






Special Thanks

今回はなんと、モノづくり仲間である てらきゅーとーま(https://twitter.com/toma18720)さんに
2日間 幣ブースのサポートを引き受けていただく事になりました!!!

とーまさんは今回
分身ロボットOriHimeを遠隔操作できるObniz戦車(OriTank)
を持ってきてくれます!


もしかしたら、OriHimeパイロットさん達も遠隔から分身参戦してくれるかも!?
Maker Faire はまさにロボットと人が混在した世界なので、
「見た目はロボット、中身は人間」な存在がたくさんいても違和感なさそう!!

私の妻の操作するOriOmni と OriTankとのコラボ、どうなるか分からないワクワク感でいっぱいです!!



意気込み

想いはMFKと変わりません!

障害を持った当事者や家族をサポートするアシスティブテクノロジー
大事なのは
『当事者に近い位置にいる事』
であると、この1年で強く感じました。そして、一品モノづくりができるメーカーズ活動と、個々の症例に対してカスタマイズが必要な障害支援テクノロジーは本当に相性が良いと思ってますー

・個人の超具体的な課題に対して解決案を考えれる
 (謎解き好きなエンジニアには格好のテーマがたくさん)
・実際に自分が手を動かして仕上げていける
 (モノづくりの楽しさ)
・自分が作ってくれたモノで喜んでくれる、その姿が目の前で見れる
 (エンジニアのやりがい)

エンジニアと当事者が繋がってテクノロジーを作っていく活動・世界をこの1年でたくさん見てきました!
そんな世界がこれからどんどん広がっていく事を願いつつ、自分もその一つのきっかけが出来れば、と考えてます。そんな、一番身近な人の困り事を解決するモノづくり活動の一例として、何かを一つでも伝えれれば、と思いますー

上記の展示物を見て頂ければ分かる通り、決してすごく難しい技術は使っていません。Maker Faireというモノづくりのプロが集まる祭典で、難しい技術を求める人にとって弊ブースは少し物足りないかもしれません。
あくまで、幣ブースの特徴は、

「必要とする人のニーズ目線で
 ①日常使用を目指し
 ②具体的な誰かを
 ③ちょっぴり笑顔にさせる
個人モノづくり活動」

だと思っているので、その視点で暖かい目で見て貰えれば、と思います~


日常使用を目指した暖かみある自作アシスティブテクノロジー
是非とも触って感想等頂けると嬉しいです!!

YOLO v3による一般物体認識をROS上で試してみた

f:id:motokiinfinity8:20190701230409j:plain

はじめに

前回の記事で取り上げた深度計測カメラD435 と 自己位置認識カメラT265

ogimotokin.hatenablog.com

これを使って、『息子と自動で鬼ごっこをするロボット』や『息子からひたすら逃げる立位支援ロボット』などを作りたいというモチベーションがでてきました! そのために必要なのは、ある程度正確な『息子の位置&距離を計測するか』、です。 息子個人を認識するのは次のステップで実施するとしても、まずは人認識をして人との距離情報をカメラから取得するというやり方です。 一番単純なのはOpenCVに搭載されている顔検出機能を使う手段ですが、息子は普段はズリバイなど地面と接している機会が多く、なかなか顔を見せてくれません。なので、背中を向いていてもしっかり認識してくれる手段が必要です。

そんな時、ちょうどROS上で比較的簡単に動く darknet_rosノードがあるという情報を聞いたので、息子認識に対してどの程度有用であるか、早速試してみたいなぁ、と思います

darknet_ros セットアップ

開発環境

今回は、GPU搭載の開発用ゲーミング用PCで実行してみます。
 ・CPU : i7-8750H
 ・GPU : GeForce GTX 1060
 ・OS : Ubuntu16.04 LTS
いずれはJetson Nanoに移植しますが、まずは高スペック機で動作確認。

インストール手順

以下のサイトを参考にインストールを進めました。
demura.net

$ git clone --recursive https://github.com/leggedrobotics/darknet_ros.git
$ cd ../../
$ catkin_make -DCMAKE_BUILD_TYPE=Release

しかし、下記エラーで停止

CMake Error at darknet_ros/darknet_ros/CMakeLists.txt:161 (add_library):
Cannot find source file:
src/activation_layer.c
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
CMake Error: CMake can not determine linker language for target: darknet_ros_lib
CMake Error: Cannot determine link language for target "darknet_ros_lib".

ん?なぜだろう…とよく見てみると

darknet_ros,/ darknet_ros,/CMakeList.txt内の ${DARKNET_PATH} が何故かルートファイル直下になっている。
原因が分からないが、これを回避するため、~/catkin_ws/src/darknet_ros/darknet/に置換することで回避した。
なんという力技(笑)

おかげで無事にcmakeは通りました!

次に、YOLO ver3のモデルのインストールは下記で実施します。

  wget http://pjreddie.com/media/files/yolov3.weights
  wget http://pjreddie.com/media/files/yolov3-voc.weights

上記は、/catkin_ws/src/darknet_ros/darknet_ros/yolo_network_config/weights/how_to_download_weights.txt にも記載されています。

動作確認

まず、使うカメラのトピック名を確認します!
D435で実施する場合であれば、RGB画像のトピック名は、
/camera/color/image_raw
になるはずなので、その場合は darknet_ros/darknet_ros/config/ros.yaml  を書き換えます。

[catkin_ws/src/darknet_ros/darknet_ros/config/ros.yaml]
subscribers:
  camera_reading:「
    topic: /camera/color/image_raw
    queue_size: 1

となっていればOKです。

その上で、一つ目のターミナル上で

roslaunch realsense2_camera rs_camera.launch

でRealsense D435カメラを起動。
その後に、darknet_ros を起動

roslaunch darknet_ros darknet_ros.launch

それで、認識画像も表示してくれます。これだと、1.0fps くらい。。。
雰囲気枯らして、おそらくCPU処理のみっぽそう

GPUでの動作確認

darknetでYOLOv3を動かしてみた。 - Qiita

を参考にして、darknet/Makefile を以下に変更

GPU=1
CUDNN=1
OPENCV=0
OPENMP=0
DEBUG=0

そして、再度ビルドすると……120fps!!!
GPUすごっ!!

実際に、息子で試してみると、顔が見えない側面や背面でも人物と認識していそう〜!
時々は、ネコとか認識してるが(笑)

ちなみに、認識結果は、
/darknet_ros/bounding_boxes
トピックに表示されるので、このトピックをサブスクライブすれば認識結果をいろいろと使えそうですね。

上記動画は、スコアの低い認識結果も表示しているのでビジーに見えるが、スコアの高いモノだけ表示する様にすれば
それなりに信頼度の高いデータのみを抽出できそうなので、そのあたりはチューニングしていきたいと思います。

D435で検出した人物との距離を測定する

上記の bouding_boxes 情報から人物のいるRGB画像上の座標を抽出し、その座標に対応した位置の深度画像から距離を抽出することとする。
D435 で使用するトピックは以下
・RGB画像 : /camera/color/image_raw
・深度画像 : /camera/aligned_depth_to_color/image_raw

深度画像は、/camera/depth/image_rect_raw' でも表示されるが、これだとRGB画像と座標相関がないため、上記にトピックを使用する。

サンプルコードは以下(Pythonで例を記載しています)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This import is for general library
import os
import threading

# This import is for ROS integration
import rospy
from sensor_msgs.msg import Image,CameraInfo
from cv_bridge import CvBridge, CvBridgeError
import numpy as np
from darknet_ros_msgs.msg import BoundingBoxes,BoundingBox
import cv2

class PersonDetector():
    def __init__(self):

        # cv_bridge handles
        self.cv_bridge = CvBridge()

        self.person_bbox = BoundingBox()

        # ROS PARAM
        self.m_pub_threshold = rospy.get_param('~pub_threshold', 0.40)

        # Subscribe
        sub_camera_rgb     =  rospy.Subscriber('/camera/color/image_raw', Image, self.CamRgbImageCallback)
        sub_camera_depth   =  rospy.Subscriber('/camera/aligned_depth_to_color/image_raw', Image, self.CamDepthImageCallback)
        sub_darknet_bbox   =  rospy.Subscriber('/darknet_ros/bounding_boxes', BoundingBoxes, self.DarknetBboxCallback)

        return

    def CamRgbImageCallback(self, rgb_image_data):
        try:
            rgb_image = self.cv_bridge.imgmsg_to_cv2(rgb_image_data, 'passthrough')
        except CvBridgeError, e:
            rospy.logerr(e)

        rgb_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2RGB)

        # 人がいる場合
        if self.person_bbox.probability > 0.0 :

           # 一旦、BoundingBoxの中心位置の深度を取得 (今後改善予定)
            m_person_depth = self.m_depth_image[(int)(self.person_bbox.ymax+self.person_bbox.ymin)/2][(int)(self.person_bbox.xmax+self.person_bbox.xmin)/2]

            cv2.rectangle(rgb_image, (self.person_bbox.xmin, self.person_bbox.ymin), (self.person_bbox.xmax, self.person_bbox.ymax),(0,0,255), 2)
            rospy.loginfo('Class : person, Score: %.2f, Dist: %dmm ' %(self.person_bbox.probability, m_person_depth))
            text = "person " +('%dmm' % m_person_depth)
            text_top = (self.person_bbox.xmin, self.person_bbox.ymin - 10)
            text_bot = (self.person_bbox.xmin + 80, self.person_bbox.ymin + 5)
            text_pos = (self.person_bbox.xmin + 5, self.person_bbox.ymin)
            cv2.rectangle(rgb_image, text_top, text_bot, (0,0,0),-1)
            cv2.putText(rgb_image, text, text_pos, cv2.FONT_HERSHEY_SIMPLEX, 0.35, (255, 0, 255), 1)

        cv2.namedWindow("rgb_image")
        cv2.imshow("rgb_image", rgb_image)
        cv2.waitKey(10)
        cv2.normalize(self.m_depth_image, self.m_depth_image, 0, 32768, cv2.NORM_MINMAX)
        cv2.namedWindow("depth_image")
        cv2.imshow("depth_image", self.m_depth_image)
        cv2.waitKey(10)
        return


    def CamDepthImageCallback(self, depth_image_data):
        try:
            self.m_depth_image = self.cv_bridge.imgmsg_to_cv2(depth_image_data, 'passthrough')
        except CvBridgeError, e:
            rospy.logerr(e)
        self.m_camdepth_height, self.m_camdepth_width = self.m_depth_image.shape[:2]
        return

    def DarknetBboxCallback(self, darknet_bboxs):
        bboxs = darknet_bboxs.bounding_boxes
        person_bbox = BoundingBox()
        if len(bboxs) != 0 :
            for i, bb in enumerate(bboxs) :
                if bboxs[i].Class == 'person' and bboxs[i].probability >= self.m_pub_threshold:
                    person_bbox = bboxs[i]        
        self.person_bbox = person_bbox



if __name__ == '__main__':
    try:
        rospy.init_node('person_detector', anonymous=True)
        idc = PersonDetector()
        rospy.loginfo('idc Initialized')
        idc.start()
        rospy.spin()
        idc.finish()

    except rospy.ROSInterruptException:
        pass

その他参考情報

darknet_rosを使ったサンプルコード等は以下です。適宜参考にしていきます。

github.com
robot.isc.chubu.ac.jp

RealSense D435(距離計測カメラ) & T265(自己位置認識カメラ) をROS上で動かした

f:id:motokiinfinity8:20190605001720j:plain

はじめに

現在、息子の遊び相手になってくれる自律移動ロボット 及び 息子の手動車いすを電動化かつ半自動運転化する仕組みを個人で検討中。
その中で、今更ながら Intel Realsenseカメラを入手することができたので、導入に向けて早速立ち上げてみました。

Realsenseの様な深度計測カメラは2年ほど前に、Realsense R200 / SR300 を使ったことはあり、これをROS上に組み込んで、ペットボトルを高速で追従させたり、
しまいには子供の顔位置を認識させてその口元に正確にスプーンを運ぶ「自動ご飯食べさせアームロボット」を本気で制作したりしていました(遠い目)

しかし、R200もSR300 も Intel提供のドライバが不安定だったのか、一度開発環境が崩れてしまって、その後に復旧できないという悲劇に襲われてしまい、それきりになってしまいました。
ファームウェアエンジニアの友人に解析協力を依頼しましたが、結局ハマってしまい、復活不可という自体になってました)

今回のD435 / T265のドライバはだいぶ安定しているという噂を聞いたので、以前の悪夢を忘れられたらよい、ですが。。。

Realsense D435

普通のカメラ同様のRGB映像の取得に加えて、ステレオビジョンによる距離計測が可能なカメラです。最小11cm〜最大10mまでの各映像の奥行き値を計測可能とのことです。
そのため、主な用途は
 ・物体検出時に物体との距離が分かる
なので、ものを掴むための位置を把握したり、障害物との距離を検知したり、かなり広い用途での活躍が期待できます。
近距離用だったSR300と比べても圧倒的にコンパクトなので、幅広いロボットに取り付け可能なのも利点。

ちなみに、IMU(加速度/ジャイロ)搭載のD435i という品番もあります。今から買うならこちらの方が良いかも。
(単独でVisual SLAMができます)

Realsense T265

2対の魚眼カメラと、IMU(加速度/ジャイロ)搭載しており、カメラだけで完結してVisual SLAMが実行できます。
つまり、主な用途は、
 ・カメラが移動した際の現在位置情報を把握できる
なので、移動ロボットに搭載しておくだけで簡単に現在位置が把握できるということですね。Visual SLAMなので、これだけだと絶対的な位置が分からない(あくまで実行開始場所からの相対位置)のと、特徴の少ない場所(例えば、真っ白な部屋)では使えないなどのデメリットはあるものの、日常的な場所で使いモノになるのかは、じっくり見ていきたいと思います。

初期確認 @ D435

Windows上でまずは動作確認をしてみました。
ツールは以下を参照。
Releases · IntelRealSense/librealsense · GitHub

RealSense SDK もしくはViewerをダウンロード して確認します。普通のRGBカメラ映像 と 距離画像(グレイスケール)の映像が見えれば、カメラ自体は正しく動いているのがわかりました。

D435のファームアップ

D435購入時期が古かったため、念の為もカメラのファームウェアバーションを上げておきます。

以下のサイトを参照にして、バージョンを5.9.2→5.10.13(当時では最新)に変更しました。

Download Latest Firmware for Intel® RealSense™ D400 Product Family
からZIPファイルをダウンロード。Signed_Image_UVC_5_10_13_0.binファイルがあったので、
Download Windows* Device Firmware Update Tool for Intel® RealSense™ D400 Product Family
にあるIntel RealSense D400 Series DFU Tool for Windows.zipツールもダウンロードして、これを起動する。
③ ②でダウンロードしたintel-realsense-dfu.exeを「管理者として実行」を行う
④ Realsense D435をPCのUSB3.0に刺した状態で、「2」を選択。カメラバージョンが読める事を確認する
⑤ 「1」を選択してバージョンアップ作業開始。「1」

Ubuntu上でのカメラ動作確認 (D435/T265)

インストール環境

私の開発環境に合わせて以下を入れました
 ・開発PC : Intel Core i5-8250U
 ・開発OS : Ubuntu16.04 LTS

インストール手順

naonaorange.hatenablog.com

上記サイトを参考にしながら設定を進めました。
まずは関連パッケージのインストール

sudo apt-key adv --keyserver keys.gnupg.net --recv-key C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C8B3A55A6F3EFCDE
sudo apt-get update

そして、ここからrealsenseドライバのインストールになります。D435だけで使用していた際には、aptから realsense2関連パッケージを入れていたのですが、
今回はT265で SDK1.22.0 以降が要求されております。 (なぜかaptから入れると 1.18.1から更新されない…)
なので、私は一旦、公式gitサイトからSDK一式を落としてきて、buildしておりますのでご注意を!

github.com
にしたがってインストール。

git clone https://github.com/IntelRealSense/librealsense.git
sudo apt-get install git libssl-dev libusb-1.0-0-dev pkg-config libgtk-3-dev
sudo apt-get install libglfw3-dev
./scripts/setup_udev_rules.sh
./scripts/patch-realsense-ubuntu-lts.sh
sudo make install
カメラ画像確認方法

realsense-viewer で SDK起動。
まず、D435を接続して… 普通のRGBカメラ映像 と 距離画像の映像が見えることを確認します。
f:id:motokiinfinity8:20190605013557p:plain
左側が距離画像、右側がRGBカメラ画像になります。左側の距離画像を見ると…前方のおもちゃの土台までの距離は32cmとなっています。
実際にものさしで測ってみると…33cm程度なので誤差は1cm程度、とても優秀です!!
RGB映像と距離画像は画角が違う様で近距離になる程、ずれ量がある点には注意。おそらく画素位置の補正は必要だろうなぁ〜

次に T265 を接続。普通に魚眼カメラ映像×2が見えます。同時に画面右側にはソフト起動時を原点とした座標を表示しています。
f:id:motokiinfinity8:20190605014559p:plain
こちらは座標の軌跡を3D表示しています。座った状態でカメラを起動した後、立ち上がってぐるっとリビングを移動したので、その軌跡が残っています。
しっかりとloop closeできているので、それなりに自己位置認識の精度はありそうですね。
f:id:motokiinfinity8:20190605014642p:plain

ROSでの起動方法

以下のサイトからダウンロード。
github.com

あとは、catkin_make のビルドでOK

D435確認方法

RGB映像の確認方法は以下

roslaunch realsense2_camera rs_camera.launch
rosrun image_view image_view  image:=/camera/color/image_raw

上記に加えて、深度映像を確認します。

rosrun image_view image_view image:=/camera/depth/image_rect_raw

で深度映像が見えます。

次に、D435の特徴である画像をPointCloud で取得できます。これをRviz上に表示してみます。

roslaunch realsense2_camera rs_rgbd.launch enable_pointcloud:=true align_depth:=false depth_registered_processing:=true align_depth:=true

別ターミナルにて

cd ~/catkin_ws/src/realsense2_camera/rviz
rviz -d pointcloud.rviz

おぉ、各画素位置が深度情報に応じて立体的にマッピングされている! なんだか面白い(月並みなセリフ)
[RGB画像]
f:id:motokiinfinity8:20190605215252p:plain
[PointCloud画像]
f:id:motokiinfinity8:20190605215329p:plain
これを使えば Visual SLAMが綺麗に可視化される訳ですね!

T265確認方法

asukiaaa.blogspot.com
を参照しています。

roslaunch realsense2_camera rs_t265.launch

で起動して、その後に

rostopic echo /tf

でカメラの現在位置(
カメラを動かすと x,y位置が変わって、自己位置(相対位置)が取得できることが分かります。

また、

roslaunch realsense2_camera demo_t265.launch

を使えば、 起動時の場所を原点として、カメラの現在の位置と角度がrviz上に表示されます。おぉ、素晴らしい!
f:id:motokiinfinity8:20190605221924p:plain

今後の参考文献 (都度更新)

本ブログをアップする直前のタイミングで、からあげ先生のサイトで「D435+Jetson Nano」の設定方法がアップされてました(光栄です!)
今後のJetson移植時に参考にします。
qiita.com

D435でVisual SLAMをするなら参考になりそうなサイトです。
qiita.com

まとめ

周囲の障害物との距離を算出できる距離計測カメラD435 と 周囲の画像を元に自己位置を認識するカメラT265 をROS上にて動かすための情報を整理してみました。
今回は一旦はノートPC上で実装しましたが、本当はロボットにのせるエッジデバイスでカメラは使用するべきなので、最終的にはそちらで再度環境を立ち上げようと考えています。
ちょうどいま、Jetson Nanoを注文しているので、入手次第 そちらでの環境セットアップを進めて、簡単な自律移動ロボットで遊んでみたいと思います!