フレンドリーなロボットを追跡する全方向性の人々
コンポーネントと消耗品
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 10 | ||||
| × | 1 | ||||
| × | 1 |
必要なツールとマシン
> |
| |||
|
アプリとオンラインサービス
> |
|
このプロジェクトについて
最初の提出
「ハックスター・ターミネーター・コンペティション」コンペティションへの最初の提出は、人間を探すロボットを作成することでしたが、ターミネーターの世界のものとは異なり、人を殺すことはなく、代わりにその力を永久に使用しました。
この全方向性ロボットは、あなたを見つけ、検出し、家に帰り、あなたを褒め称えます!
私が自分自身に指定した要件の1つは、電子機器を自分で作成しなくても確実に作成できるようにすることです。このロボットの内部のすべての部品はeBayから購入でき、無料で入手できるチュートリアルを使用して接続でき、動作するはずです。ケースは3D印刷可能になるため、自分で印刷することも、3Dハブで作成することもできます。このプロジェクトはこの目標を達成していると思います。次に、独自の Hunter Flatterer Robot を作成する手順を説明します。
すべての仕組み!
それでは、ロボットのすべての部品とそれらがどのように接続されるかを示すシステム図から始めましょう。ビルド全体でこれを参照し、進行中にチェックします。
<図>これまでモーターを使用したことがない場合でも、この図に気を悪くしないでください。それは基本的に4つの主要な部分に要約されます:
- 左側は、バッテリーを取り出して、システムの電圧が正しいことを確認しています。
- 賢いビットはci20で行われます
- Arduinoは、モーターに何をすべきかを指示するために使用されます
次の4つのセクションでは、このリストを反映し、各パーツの設定について説明します。
電気製品の取り扱い
それで、あなたはあなた自身にバッテリーを持っています、次は何ですか?
<図>上の図は、電源用にすべてのコンポーネントを接続する方法を示しています。回路図の配線に従うと、これが実際の表現になります。
ArduinoをL298Nに接続する
これを説明することはできますが、私が行ったチュートリアルに従う方がよいでしょう:http://www.instructables.com/id/Arduino-Modules-L298N-Dual-H-Bridge-Motor-Controll。
これですべてが配線されました。青いライトがいたるところに点滅し、青い煙が出ていないので、準備は完了です。この悪い男の子を機能させることに取り掛かりましょう。
自分でケースを3Dプリントする
これを設計したとき、私は2つのことを実現したいと思いました。それは、見た目がかっこよく、Ci20を可能な限り誇示しています。これが競争のポイントだということですか?
私はこのロボットを完全に3D印刷できるように設計しました。設計はすべて、以下から入手できます。基本的にこの時点で、上、下、ホイールを自分で印刷します。 3Dプリンターにアクセスできない場合は、www.3dhubs.comをチェックして、誰かに印刷してもらうことができます。以下のデザインをチェックできます
これは、ci20がフィットし、場所に誇りを持っていることを確認するために私が行ったデザインのかなりのレンダリングです
<図>すべて印刷したら、上記のようにすべての部品を接着できます(または、自信がない場合はマスキングテープを使用します。モーターを固定するには、M4ボルトが必要です。
CI20に魔法をかける
CI20は上司であり、手術の頭脳です。それがないと、ロボットはヒラヒラします。それで、それは何をしますか?
ci20はOpenCVを使用して顔を検出し、適切なコマンドをシリアル経由でArduinoに送信して、モーターを正しい方向に動かします。
ステップ1:OpenCVをインストールする
このガイドで言ったように、私はアップルカートを作り直そうとはしていませんでした。私はあなたが家でできる何かを構築し、比較的簡単に拡張しようとしています。したがって、OpenCVをインストールするには、次のチュートリアルに進んでください:
OpenCVを起動して実行する手順を説明します。
ステップ2:コードを実行する
フェイストラッキングコードをコンパイルして実行する必要があります。Ci20のファイルに対してこのコマンドを実行してください。
g ++ -I / usr / local / include / opencv -I / usr / local / include / opencv2 -L / usr / local / lib / -g -o binary main.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching
作成するバイナリファイル:FaceTracking:main.cpp> ソースファイル:FaceTracking.cpp
<図>簡単ですよね?
Ci20とArduinoMagic
以下の添付ファイルのコードでArduinoをフラッシュした後。 ArduinoをCI20のUSBポートに接続し、最近作成したFaceTrackerを実行します。カメラフィードがポップアップ表示され(そうです、ウェブカメラを接続します)、顔を真ん中に突き刺すと、ロボットの車輪が前方に移動し始めます!
仕事は終わりましたか?
今は時間の制約のため、他に何もすることができませんでした。そこで、これまでに経験した人にとっては、ここに挑戦があります。このボットを非常に素晴らしいものにするために追加できるものが2つあります。
スピーカーのセットといくつかのサウンドファイルを追加して、画面上で顔が十分に大きいときに、その人にサウンドファイルを再生するようにします
- ロボットが1〜2分以内に顔を検出しなかった場合は、その場で回転させます。これを行うには、コマンド「RXX」をArduinoに送信します。 XXを、向きを変えたい時間に置き換えます。
コード
- Arduinoスケッチ-メイン
- Arduino Sketch-MotorControl
- Ci20のFaceTrackingC ++
Arduinoスケッチ-メイン Arduino
このArduinoコードは、シリアル経由でCi20から駆動コマンドを受け取り、モーターが正しい方向に進むように正しい方法で駆動されることを保証します。私はもともとRaspberryPi用にこれを作成しましたが、Ci20でも動作します
// Motor 1int dir1PinA =3; int dir2PinA =2; int speedPinA =9; //モーター速度を制御できるようにするにはPWMピンである必要があります//モーター2intdir1PinB =4; int dir2PinB =5; int speedPinB =8; //モーター速度を制御できるようにするにはPWMピンである必要があります//モーター3intdir1PinC =6; int dir2PinC =7; int speedPinC =10; //モーター速度を制御できるようにするにはPWMピンである必要がありますintx =0; int y =0; intdominantUltrasonic =0; bool moveMotor =false; int startTime =0; void setup(){Serial.begin(9600); pinMode(dir1PinA、OUTPUT); pinMode(dir2PinA、OUTPUT); pinMode(speedPinA、OUTPUT); pinMode(dir1PinB、OUTPUT); pinMode(dir2PinB、OUTPUT); pinMode(speedPinB、OUTPUT); pinMode(dir1PinC、OUTPUT); pinMode(dir2PinC、OUTPUT); pinMode(speedPinC、OUTPUT); startTime =millis();} String rpiString; void loop(){readDataFromRPi(); //これは、最後の1秒間にRPiから値を受け取ったかどうかをテストします。 //移動コマンドが連続していないため、停止と開始を継続しないように効果的にバッファとして機能します// RPiからnothignが着信した場合にも停止を許可します// intlapsedTime =millis()-startTime; // if(elapsedTime> 1000)// {// x =0; // y =0; // dominantUltrasonic =0; // moveMotor =false; // startTime =millis(); // //} // XとYをモーターに送信します// if(moveMotor ==true &&(x!=0 &&y!=0))// {//Serial.println("MovingMotor "); // driveInDirection(x、y); //} // if(x ==0 &&y ==0)// {//Serial.println("ZeroMMotor "); // driveInDirection(x、y); //} //これは超音波から残っている可能性があります-delay(30);} void readDataFromRPi(){// Rpiから読み取るwhile(Serial.available()){delay(3); //バッファがいっぱいになるまでの遅延if(Serial.available()> 0){char c =Serial.read(); //シリアルバッファから1バイトを取得しますrpiString + =c; //文字列をreadStringにしますif(c =='n'){break; }}} // ENDWHILE // RPiから何かが読み取られた場合は、それをx、y&domniantUltrasonicに入れますif(rpiString.length()> 0){Serial.println(rpiString); //受信したものを確認しますStringisRotate =getValue(rpiString、 ''、0);文字列xval =getValue(rpiString、 ''、1);文字列yval =getValue(rpiString、 ''、2); x =xval.toInt(); y =yval.toInt(); startTime =millis(); if(isRotate =="r"){rotate(x); } else {driveInDirection(x、y); } rpiString =""; } // ENDIF} String getValue(String data、char separator、int index){int found =0; int strIndex [] ={0、-1}; int maxIndex =data.length()-1; for(int i =0; i <=maxIndex &&found <=index; i ++){if(data.charAt(i)==Separator || i ==maxIndex){found ++; strIndex [0] =strIndex [1] +1; strIndex [1] =(i ==maxIndex)? i + 1:i; }} return found> index? data.substring(strIndex [0]、strIndex [1]): "";}
Arduino Sketch-MotorControl Arduino
これはメインのinoファイルに対応し、同じプロジェクトファイルに含める必要があります/ **モーター制御コード**このクラスには、ロボットを任意の方向に移動させて*中心点を中心に回転させるコードが含まれます。 * / void driveInDirection(float newX、float newY){delay(20); float x =newX; float y =newY; float theta =atan2(y、x); float mag =sqrt((x * x)+(y * y)); float vx =mag * cos(theta); float vy =mag * sin(theta); float w1 =-vx; float w2 =0.5 * vx-sqrt(3)/ 2 * vy; float w3 =0.5 * vx + sqrt(3)/ 2 * vy; //最大のw値を取得しますfloatwSet [] ={w1、w2、w3}; float maximumValue =0.0; for(int i =0; i <3; i ++){if(abs(wSet [i])> maximumValue){largestValue =abs(wSet [i]); }} float speedCoef =(float)147.0 / maximumValue; w1 =w1 * speedCoef; w2 =w2 * speedCoef; w3 =w3 * speedCoef; if(x ==0 &&y ==0){w1 =0; w2 =0; w3 =0; } Serial.println(w1); Serial.println(w2); Serial.println(w3); w1 =制約(w1、-150、150); w2 =制約(w2、-150、150); w3 =制約(w3、-150、150);ブールw1_ccw =w1 <0?真/偽;ブールw2_ccw =w2 <0?真/偽;ブールw3_ccw =w3 <0?真/偽;バイトw1_speed =(バイト)map(abs(w1)、0、150、0、255);バイトw2_speed =(バイト)map(abs(w2)、0、150、0、255);バイトw3_speed =(バイト)map(abs(w3)、0、150、0、255); printMotorSpeed(w1_speed、1); printMotorSpeed(w2_speed、2); printMotorSpeed(w3_speed、3); analogWrite(speedPinA、w1_speed); // PWMを介して速度変数を設定しますanalogWrite(speedPinB、w2_speed); analogWrite(speedPinC、w3_speed); // PWMを介して速度変数を設定しますdigitalWrite(dir1PinA、!w1_ccw); digitalWrite(dir2PinA、w1_ccw); digitalWrite(dir1PinB、!w2_ccw); digitalWrite(dir2PinB、w2_ccw); digitalWrite(dir1PinC、w3_ccw); digitalWrite(dir2PinC、!w3_ccw);} voidrotate(floatミリ秒){float w1 =255; float w2 =255; float w3 =255;ブールw1_ccw =w1 <0?真/偽;ブールw2_ccw =w2 <0?真/偽;ブールw3_ccw =w3 <0?真/偽;バイトw1_speed =(バイト)map(abs(w1)、0、150、0、255);バイトw2_speed =(バイト)map(abs(w2)、0、150、0、255);バイトw3_speed =(バイト)map(abs(w3)、0、150、0、255); printMotorSpeed(w1_speed、1); printMotorSpeed(w2_speed、2); printMotorSpeed(w3_speed、3); analogWrite(speedPinA、w1_speed); // PWMを介して速度変数を設定しますanalogWrite(speedPinB、w2_speed); analogWrite(speedPinC、w3_speed); // PWMを介して速度変数を設定しますdigitalWrite(dir1PinA、!w1_ccw); digitalWrite(dir2PinA、w1_ccw); digitalWrite(dir1PinB、!w2_ccw); digitalWrite(dir2PinB、w2_ccw); digitalWrite(dir1PinC、w3_ccw); digitalWrite(dir2PinC、!w3_ccw); delay(ミリ秒); analogWrite(speedPinA、0); // PWMを介して速度変数を設定しますanalogWrite(speedPinB、0); analogWrite(speedPinC、0); // PWMを介して速度変数を設定します} void printMotorSpeed(byte motorSpeed、int motor){Serial.print( "Motor"); Serial.print(モーター); Serial.print( ":"); Serial.println(motorSpeed); }
Ci20 C / C ++のFaceTrackingC ++
Story#include "opencv2 / objdetect / objdetect.hpp" #include "opencv2 / highgui / highgui.hpp" #include "opencv2 / imgproc / imgproc.hpp" #include#include using namespace std; using namespace cv; CascadeClassifier face_cascade、eyes_cascade; String window_name ="Face Detection"; #include #include #include #include #include #include #include #include int sendSerial(char * message){int fd =open( "/ dev / ttyUSB0 "、O_RDWR); if(fd ==-1){perror(" dev / ttyUSB0 "); return 1;} struct termios tios; tcgetattr(fd、&tios); tios.c_iflag =IGNBRK | IGNPAR; tios.c_oflag =0; tios.c_lflag =0; cfsetspeed(&tios、B9600); tcsetattr(fd、TCSAFLUSH、&tios); usleep(1000); // char msg [] ="50 50"; write(fd 、message、strlen(message)); return 0;} / ** *面を検出し、その周りに楕円を描画します* / void detectFaces(Mat frame){std ::vector faces;マットframe_gray; //グレースケールに変換cvtColor(frame、frame_gray、COLOR_BGR2GRAY); //ヒストグラムを均等化しますequalizeHist(frame_gray、frame_gray); //顔を検出face_cascade.detectMultiScale(frame_gray、faces、1.1、3、0 | CASCADE_SCALE_IMAGE、Size(30,30)); //すべての面を反復処理for(size_t i =0; i 目; //各顔の内側で目を検出しようとします//eyes_cascade.detectMultiScale(face、eyes、1.1、2、// 0 | CASCADE_SCALE_IMAGE、Size(50、50)); // if(eyes.size()> 0)//顔の周りに楕円を描画しますellipse(frame、center、Size(faces [i] .width / 2、faces [i] .height / 2)、0、0、360 、Scalar(255、0、255)、4、8、0); if(center.x> frame.cols / 3 &¢er.x =0)//ブレークを一時停止; } return 0;}
カスタムパーツとエンクロージャー
これは、すべての部品をはめ込み、蓋を取り付けるように私が設計した全方向性ロボットのベースです。これは、Ci20の栄光を際立たせる蓋です。 オムニディレクショナルホイール
これが全方向ホイールのオリジナルデザインです。私はこれの半分をリムで使用し、それを編集して、thingiverse.com のモーターシャフトCADファイルを含めました。 シングバースリンクからのリミックスホイール 回路図
ストーリーセクションのより良い説明を参照してください 製造プロセス