■はじめに
4足歩行ロボット、なかなかうまく歩かなくて苦労したのですが、結果的には非常に簡単な歩行プロセスにモデリングすることができたので、サンプルプログラムとして公開します。また、ロボット本体も簡単すぎるほど簡単にサーボを両面テープで貼り付けるだけでできちゃったので、併せて紹介します。ロボットを本格的に極めたいわけじゃないけど、何となく興味はあるという方、ぜひお試しを。
■まずは動作デモから
# ■ロボット組み立てに必要なもの ① サーボモーター Tower Pro SG90 × 4 ② 両端ロングヘッダピン 12ピン ③ 強力タイプの両面テープ少々 ④ モバイルバッテリー 2A、120g、10cm×6cm×1.5cm (だいたいの感じでOK) # ■ロボットの組み立て方 ***・サーボをモバッテリーの裏に両面テープで貼り付ける。*** ***・足はサーボ付属のホーンを使う。*** ***・回転角度90度で直立するよう取り付ける。*** ***・サーボの向きは必ず写真と同じにする。*** ***・0番ピン側をgndにして、後左足→後右足→前左足→前右足の順で刺す。*** #obniz #4足歩行ロボット
— Google Homer (@google_homer_) 2019年3月11日
サーボ4台を両面テープでモバイルバッテリーに貼りつけただけの4足歩行ロボット。 pic.twitter.com/ftqBBy5z3b
■操作方法
① サンプルコードのobniz IDを自分のものにして起動かけて下さい。下記画面表示されます。
② スライダーで直立の微調整をして、コードの【A】部分に設定して下さい。
③ プログラムを再起動してください。
後は、準備運動/前進/後進のボタンを押して動作をお楽しみください。
重さやサイズが異なったり微妙に取り付け位置が違ったりすると、うまく歩かない事もあるかもしれません。そんな時はコードのコメントを参考にしながら、色々いいじってみて下さい。
(参考)
学術上の類型の「トロット歩容」という歩き方を参考にしました。学者に言わせると違うといわれるかもしれませんが、あしからず。
■サンプルコード
<!-- 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は色々なものを直刺しできるので、ロボットのような筐体も単純構造でできちゃうんですね。他にも色々とチャレンジして行きたいと思います。