obniz 4足歩行ロボット、サーボを両面テープでバッテリーに貼りつるだけでできちゃった!

#■はじめに
4足歩行ロボット、なかなかうまく歩かなくて苦労したのですが、結果的には***非常に簡単な歩行プロセスにモデリング***することができたので、***サンプルプログラムとして公開***します。また、***ロボット本体も簡単すぎるほど簡単にサーボを両面テープで貼り付けるだけ***でできちゃったので、併せて紹介します。ロボットを本格的に極めたいわけじゃないけど、何となく興味はあるという方、ぜひお試しを。
#■まずは動作デモから
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://twitter.com/hashtag/4%E8%B6%B3%E6%AD%A9%E8%A1%8C%E3%83%AD%E3%83%9C%E3%83%83%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#4足歩行ロボット</a><br>サーボ4台を両面テープでモバイルバッテリーに貼りつけただけの4足歩行ロボット。 <a href="https://t.co/ftqBBy5z3b">pic.twitter.com/ftqBBy5z3b</a></p>&mdash; Google Homer (@google_homer_) <a href="https://twitter.com/google_homer_/status/1105032589755080705?ref_src=twsrc%5Etfw">2019年3月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
#■ロボット組み立てに必要なもの
① サーボモーター Tower Pro SG90 × 4 
② 両端ロングヘッダピン 12ピン
③ 強力タイプの両面テープ少々
④ モバイルバッテリー 2A、120g、10cm×6cm×1.5cm (だいたいの感じでOK)
#■ロボットの組み立て方
***・サーボをモバッテリーの裏に両面テープで貼り付ける。***
***・足はサーボ付属のホーンを使う。***
***・回転角度90度で直立するよう取り付ける。***
***・サーボの向きは必ず写真と同じにする。***
***・0番ピン側をgndにして、後左足→後右足→前左足→前右足の順で刺す。***
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234533/eccd7126-4b9b-8c92-8628-17f0edb62e45.png)

#■操作方法
① サンプルコードのobniz IDを自分のものにして起動かけて下さい。下記画面表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234533/65ab42bc-2a86-c969-1d5c-cae1e5863afa.png)
② スライダーで***直立の微調整をして、コードの【A】部分に設定***して下さい。
③ プログラムを再起動してください。
後は、準備運動/前進/後進のボタンを押して動作をお楽しみください。

重さやサイズが異なったり微妙に取り付け位置が違ったりすると、うまく歩かない事もあるかもしれません。そんな時はコードのコメントを参考にしながら、色々いいじってみて下さい。

(参考)
学術上の類型の「***トロット歩容***」という歩き方を参考にしました。学者に言わせると違うといわれるかもしれませんが、あしからず。
#■サンプルコード

```html

<!-- HTML Example -->
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/obniz@2.0.2/obniz.js" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/obniz-parts-kits@0.9.5/ai/index.js"></script>
</head>
<body>
obniz 4足歩行ロボット サンプルプログラム
<br><br>
■直立角度調査用【A】
<br>
BL:後左足サーボの角度(前←◇→後)
<input id="BL_SLIDER" type="range"  min="0" max="180"/>    
<span id="BL_ANGLE"></span>
<br>
BR:後右足サーボの角度(後←◇→前)  
<input id="BR_SLIDER" type="range"  min="0" max="180"/>   
<span id="BR_ANGLE"></span>
<br> 
FL:前左足サーボの角度(前←◇→後)  
<input id="FL_SLIDER" type="range"  min="0" max="180"/>
<span id="FL_ANGLE"></span> 
<br>
FR:前右足サーボの角度(後←◇→前)  
<input id="FR_SLIDER" type="range"  min="0" max="180"/>
<span id="FR_ANGLE"></span>
<br><br>
■動作指令
<br>
<button id="junbi">準備運動</button>
<br>
<button id="forward">前進</button>    
<br>
<button id="back">後進</button>    
<script>

//【A】スライダーで調べた各足の直立角度を設定
const BLhome =  90; //後左足 直立角度
const BRhome =  90; //後右足 直立角度
const FLhome =  90; //前左足 直立角度
const FRhome =  90; //前右足 直立角度
//【B】動作スピードをお好みで設定　速い(200)～遅い(500)程度　
const SPJ    = 250; //準備運動のスピード
const SPW    = 400; //歩くスピード
  
var obniz = new Obniz("XXXX-XXXX"); 
obniz.onconnect = async function () {
   var BLservo = obniz.wired("ServoMotor", {gnd:0, vcc: 1, signal: 2});　//後左足
   var BRservo = obniz.wired("ServoMotor", {gnd:3, vcc: 4, signal: 5});  //後右脚
   var FLservo = obniz.wired("ServoMotor", {gnd:6, vcc: 7, signal: 8});  //前左足
   var FRservo = obniz.wired("ServoMotor", {gnd:9, vcc:10, signal:11});  //前右脚

   //SLIDER操作　(直立角度調査用)
   $("#BL_SLIDER").on('input', function() {
      var angle = $("#BL_SLIDER").val(); BLservo.angle(angle); $("#BL_ANGLE").text(angle);      
   })
   $("#BR_SLIDER").on('input', function() {
      var angle = $("#BR_SLIDER").val(); BRservo.angle(angle); $("#BR_ANGLE").text(angle); 
   })
   $("#FL_SLIDER").on('input', function() {
      var angle = $("#FL_SLIDER").val(); FLservo.angle(angle); $("#FL_ANGLE").text(angle);
   })
   $("#FR_SLIDER").on('input', function() {
      var angle = $("#FR_SLIDER").val(); FRservo.angle(angle); $("#FR_ANGLE").text(angle);
   })
   //ボタン操作 (歩行バリエーション)
   $("#junbi").on('click',async function(){
      await junbi();　    //準備運動
   })
   $("#forward").on('click',async function(){
      await forward();   //前進
   })
   $("#back").on('click',async function(){
      await back();      //後進
   })

   /***************/
   /*準備運動関数 */
   /***************/
   async function junbi(){
      //(前屈)
      for ( let n=0; n<3; n++ ){
         await move(80,"↑","↑",80,
                     5,"↓","↓",5 , SPJ );
         await move( 5,"↑","↑",5 ,
                     5,"↓","↓",5 , SPJ );
      }  
      //(後屈)
      for ( let n=0; n<3; n++ ){
         await move( 5,"↑","↑",5 ,
                    80,"↓","↓",80, SPJ );
         await move( 5,"↑","↑",5 ,
                     5,"↓","↓",5 , SPJ );
      } 
      //(左屈)
      for ( let n=0; n<3; n++ ){
         await move(70,"↑","↑",5 ,
                    70,"↓","↓",5 , SPJ ); 
         await move( 5,"↑","↑",5 ,
                     5,"↓","↓",5 , SPJ );
      }
      //(右屈)
      for ( let n=0; n<3; n++ ){
         await move( 5,"↑","↑",70,
                     5,"↓","↓",70, SPJ );
         await move( 5,"↑","↑",5 ,
                     5,"↓","↓",5 , SPJ );
      }
      //(戦闘態勢)
      await move(60,"↓","↓",60,
                 60,"↑","↑",60,SPJ );
      await move(70,"↑","↑",70,
                  5,"↓","↓",5 ,SPJ );
   }
  
   /************/
   /* 前進関数 */
   /************/
   async function forward(){
      for ( let n=0 ; n<8 ; n++ ){　　　//下記2つのActionの繰り返し
         await move(60,"↑","↓",60,        //Action-1:左右反対方向、斜め対向同じ方向、前足角度を大きく取り前かがみに
                    30,"↓","↑",30, SPW);
         await move(60,"↓","↑",60,        //Action-2:全足反転
                    30,"↑","↓",30, SPW);
      } 
   }
  
   /************/
   /* 後進関数 */
   /************/
   async function back(){              //下記2つのActionの繰り返し
      for ( let n=0 ; n<8 ; n++ ){         //Action-1:左右反対方向、斜め対向同じ方向、後足角度を大きく取り後かがみに
         await move(30,"↑","↓",30,
                    60,"↓","↑",60, SPW);
         await move(30,"↓","↑",30,       //Action-2:全足反転
                    60,"↑","↓",60, SPW);
      }      
   }
   
   /*********************************************************/
   /* 4足動作基本関数                                       */
   /*　 XXagl：各足(XX)の直立角度(XXhome)からの相対移動角度 */
   /*   XXdir：各足(XX)の足を出す方向、"↑":前、"↓":後     */
   /*   Speed：サーボ動作後のwait時間(≒歩くスピード)       */
   /**********************************************************/
   async function move(FLagl,FLdir,FRdir,FRagl,
                      BLagl,BLdir,BRdir,BRagl,Speed){
      //サーボ取り付け位置の関係で反転している+/-を補正と、絶対角度を求める
      if ( BLdir == "↑" ) BL = BLhome-BLagl; else BL = BLhome+BLagl;
      if ( BRdir == "↑" ) BR = BRhome+BRagl; else BR = BRhome-BRagl;
      if ( FLdir == "↑" ) FL = FLhome-FLagl; else FL = FLhome+FLagl;
      if ( FRdir == "↑" ) FR = FRhome+FRagl; else FR = FRhome-FRagl;
      //4足同時に動かす
      FLservo.angle(FL);
      FRservo.angle(FR); 
      BLservo.angle(BL);    
      BRservo.angle(BR);
      //歩くスピードの調整(速すぎるとサーボ異常動作もあり)
      await obniz.wait(Speed);
   }

}
</script>
</body>
</html>
```

#■まとめ
obnizは色々なものを直刺しできるので、ロボットのような筐体も単純構造でできちゃうんですね。他にも色々とチャレンジして行きたいと思います。