catkin_make徹底理解
catkinワークスペース
STEP1
- ROS_PACKAGE_PATHの確認、設定
- $ mkdir ~/test_catkin_ws/src
- $ cd ~/test_catkin_ws/src
- $ catkin_init_workspace
ここで、~/test_catkin_ws/src にCMakeKist.txtが作成される
STEP2
- cd ~/test_catkin_ws
- catkin_make
ここで、buildとdevelができる
buildとは
- catkinパッケージを構成するためにCMakeを呼び出し、さまざまな処理を行う場所でビルドスペースと呼ばれる
develとは
- 生成される目的コードをインストールする前に作業を行うスペースであり、開発スペースと呼ばれる
develや/opt/ros/indigoの中に設定ファイル.bashがある
/opt/ros/indigo設定読み込み
- コアパッケージへのパスが反映
devel設定読み込み
- ユーザーのワークスペースにインストールされたパッケージを反映
パッケージ作成
ROSパッケージをビルドするには
- CMakeList.txt
- package.xml
が必要
$ catkin_create_pkg <package_name> [depend1] [depend2] ... ex: catkin_create_pkg test_package roscpp rospy std_msgs
こうすることで、依存関係がpackage.xmlに追加される
- 同じパッケージがある場合は$ROS_PACKAGE_PATHに記載の順番で呼ばれる
コードの変更、修正時
- package.xml
- CMakeLists.txt
を修正
package.xml
現在のパッケージの名前や、ほかのパッケージとの依存関係、コンパイル時のフラグなどの基本情報が定義
大事なタグ
<build_depend> 現在のパッケージをインストールする前に、先にインストールする必要のあるパッケージの名前を指定する <run_depend> 現在のパッケージを実行する際に必要とするほかのパッケージの名前や現在のパッケージが依存するランタイムライブラリ名などを指定する <test_depend> 現在のパッケージの機能テストを行う際に依存するパッケージ名を指定する <buildtool_depend> 現在のパッケージを構築する際に使用されるシステムツールを指定する 一般的にはcatkin <export> 現在のパッケージをコンパイルする際に必要となるフラグやヘッダファイル、ライブラリなどのパス情報を指定する
CMakeLists.txt
- CMakeビルドシステムに使われる設定ファイル
- このファイルの中にはターゲットを生成する際に必要なツールや関連するライブラリおよび生成方法などを記述する。CMakeでビルドするときに、このファイルを参照してターゲットを生成する
記述する内容
. 関連するほかのcatkinパッケージ名
ex: find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
. メッセージ・サービス・アクションジェネレータ
ex: add_message_files( FILE Message1.msg)
. メッセージ・サービス・アクションのデータタイプの生成
ex: generate_message(DEPENDENCIES std_msgs)
. パッケージの構築情報
ex: catkin_package(~)
. 構築するターゲットの指定
ex: add_executable(~)
. インストール方法
ex: install(~)
. テスト項目
ex: catkin_add_gtest(~)
- . メタパッケージの記述
単一のパッケージのみビルドしたい場合
catkin_make --pkg <package name>
ROSを勉強している方々のブログまとめ
お世話になっております。
大感謝。全部目を通したい。
rosとは
参考
[ROSロボットプログラミング] ROSで使われる専門用語 - Qiita
わかりやすいチュートリアル
ROS Tutorials — ROS Tutorials 0.5.1 documentation
ブログまとめ
ロボットとお話しよう2(音声でラジコン操作)
の続き
[Raspberry Pi]USBマイクと音声認識ソフトJuliusを使って音声認識を試す(2) : 工作と競馬
[Raspberry Pi]USBマイクと音声認識ソフトJuliusを使って音声認識を試す(3) ~ フルカラーLEDを音声で操作 ~ : 工作と競馬
をとても参考にさせていただきました。 感謝です。
目標
声を使ってラジコンを操作
準備
dictation-kit-v4.3.1-linuxからmodelファイルをコピーしてこれから作業するフォルダにおく
手順
- teleop.dic(utf-8で作成)ファイルの作成
右 m i g i 左 h i d a r i 前 m a e 後ろ u sh i r o 停止 t e i sh i
- juliusの設定ファイルのteleop.jconfの作成
-w teleop.dic #単語辞書ファイル #-v model/lang_m/bccwj.60k.htkdic #N-gram、または文法用の単語辞書ファイルを指定$ -h model/phone_m/jnas-tri-3k16-gid.binhmm #使用するHMM定義ファイル -hlist model/phone_m/logicalTri #HMMlistファイルを指定する -n 5 #n個の文仮説数が見つかるまで検索を行う -output 1 #見つかったN-best候補のうち、結果として出力する個数 -input mic #-demo #マイク使用 -zmeanframe -rejectshort 600 #検出された入力が閾値以下なら棄却 #-charconv euc-jp utf8 #入出力エンコード指定(内部euc-jp, 出力utf-8) -lv 1000 #入力の振幅レベルの閾値(0~32767)
- juliusを起動するシェルスクリプトrun_teleop.shの作成
#! /bin/sh export ALSADEV=“plughw:1,0” julius -C teleop.jconf -demo -input alsa -nostrip -module > /dev/null & echo $! sleep 3
- juliusから送られるコマンドを受け取りarduinoに送る
以下com_julius_arduino.pyを作成。 これを実行すると音声入力に対し、cmd_velがpubされる。
#!/usr/bin/python # coding:utf-8 import rospy from sensor_msgs.msg import Joy from geometry_msgs.msg import Twist import socket import subprocess import xml.etree.ElementTree as ET HOST = "localhost" PORT = 10500 teleop_cmd = [ u"右" , \ u"左" , \ u"前" , \ u"後ろ" , \ u"停止" ] class RosSet(object): def __init__(self): rospy.init_node('voice_twist') self.twist_pub = rospy.Publisher('cmd_vel', Twist, queue_size=100) self.twist = Twist() def sendCmd(self, cmdName): if cmdName==u"前": self.twist.linear.x = 10 self.twist.angular.z = 0 elif cmdName==u"後ろ": self.twist.linear.x = -10 self.twist.angular.z = 0 elif cmdName==u"右": self.twist.linear.x = 0 self.twist.angular.z = -10 elif cmdName==u"左": self.twist.linear.x = 0 self.twist.angular.z = 10 elif cmdName==u"停止": self.twist.linear.x = 0 self.twist.angular.z = 0 rospy.loginfo(self.twist) self.twist_pub.publish(self.twist) def main(): rosset = RosSet() p = subprocess.Popen(["sh run_teleop.sh"], stdout=subprocess.PIPE, shell=True) pid = p.stdout.read() # juliusのプロセスIDを取得 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) try: data = "" while 1: if "</RECOGOUT>\n." in data: root = ET.fromstring('<?xml version="1.0"?>\n' + data[data.find("<RECOGOUT>"):].replace("\n.", "")) for whypo in root.findall("./SHYPO/WHYPO"): if whypo.get("WORD") in teleop_cmd: # 判別した言葉を表示する print whypo.get("WORD") rosset.sendCmd(whypo.get("WORD")) else: print "Unknown" data = "" else: try: data = data + client.recv(1024) except: print "ps kill." p.kill() # subprocess.call(["kill " + pid], shell=True) client.close() break except KeyboardInterrupt: print "KeyboardInterrupt occured." p.kill() # subprocess.call(["kill " + pid], shell=True) client.close() if __name__ == "__main__": main()
参考:
rosとarduinoでラジコンをつくる(arduino+pcをxbeeでつなぐ)
Xbeeのセットアップ
に追加で、baud rateを57600に変更。9600のままだとうまくいかなかった。 以下参照。
baud rate parameter in rosserial_python arduino - ROS Answers: Open Source Q&A Forum
手順
rosとarduinoでラジコンをつくる(pc側)
joy stickでコマンドを送り、arduinoにros経由で信号を送る
pythonでjoy stickのコマンドを受け取り(sub)送る(pub)コードを書く
手順
ターミナル1
$ roscore
ターミナル2
$ rosrun joy joy_node
ターミナル3
以下のpythonコードを実行
$ python joy_twist.py
import rospy from sensor_msgs.msg import Joy from geometry_msgs.msg import Twist class JoyTwist(object): def __init__(self): self._joy_sub = rospy.Subscriber('joy', Joy, self.joy_callback, queue_size=1) self._twist_pub = rospy.Publisher('cmd_vel', Twist, queue_size=100) self.operation = [0.0, 0.0, 0.0] def joy_callback(self, joy_msg): self.operation[0] = joy_msg.axes[0] self.operation[1] = joy_msg.axes[1] if __name__ == '__main__': rospy.init_node('joy_twist') rate = rospy.Rate(10) # 10hz joy_twist = JoyTwist() twist = Twist() while not rospy.is_shutdown(): twist.linear.x = joy_twist.operation[1] twist.angular.z = joy_twist.operation[0] rospy.loginfo(twist) joy_twist._twist_pub.publish(twist) rate.sleep()
Joy Stick Library
rosとarduinoでラジコンをつくる(arduino側)
めちゃくちゃ手抜き笑
rosでcmd_velを受け取って(subscribe)、arduinoのモーターを動かす
準備
- arduino
- motor shield
- dc motor
手順
- 以下からモーターシールドのライブラリインストール
Library Install | Adafruit Motor Shield | Adafruit Learning System
#include <AFMotor.h> int Vl,Vr,kl,kr; #include <ros.h> #include <std_msgs/String.h> #include <geometry_msgs/Twist.h> ros::NodeHandle nh; //モーターボードの3,4を使用しているため AF_DCMotor motor3(3, MOTOR12_64KHZ); // create motor #3, 64KHz pwm AF_DCMotor motor4(4, MOTOR12_64KHZ); // create motor #4, 64KHz pwm void MotorCmdCallback(const geometry_msgs::Twist& msg){ // Vl = msg.linear.x+0.13/2*msg.angular.z; // Vr = msg.linear.x-0.13/2*msg.angular.z; // Vl = kl*Vl; // Vr = kr*Vr; if (msg.linear.x>0){ motor3.run(FORWARD); // forward motor4.run(FORWARD); } else if (msg.linear.x<0){ motor3.run(BACKWARD); // backward motor4.run(BACKWARD); } else if (msg.angular.z>0){ motor3.run(FORWARD); // turn right motor4.run(BACKWARD); } else if (msg.angular.z<0){ motor3.run(BACKWARD); // turn left motor4.run(FORWARD); } else{ motor3.run(RELEASE); // stopped motor4.run(RELEASE); } } ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", MotorCmdCallback); void setup() { //Serial.begin(9600); // set up Serial library at 9600 bps //Serial.println("Motor test!");//↑rosserialはserial.beginをコメントアウトしないと使用できない(XCTUの設定で回避可能?) motor3.setSpeed(200); // set the speed to 200/255 motor4.setSpeed(200); // set the speed to 200/255 nh.initNode(); nh.subscribe(sub); } void loop() { nh.spinOnce(); delay(1); }
ロボットの認識をつくろう(Tensorflowをつかう)
物体認識をtensorflowを使って行う。
OTLさんが既にrosで動かしてくれていた↓