【C++】仮引数を受け取るコンストラクタ
- コンストラクタ関数には引数を渡すことができる
study48.cpp
#include <iostream> #include <cstring> #include <cstdlib> using namespace std; class strtype { char *p; int len; public: strtype( char * ); ~strtype(); void show(); }; strtype::strtype( char *ptr ) { len = strlen( ptr ); p = ( char *) malloc( len + 1 ); if ( !p ) { cout << "メモリ割り当てエラー" << endl; exit(1); } strcpy( p, ptr ); } strtype::~strtype() { cout << "pを開放する" << endl; free( p ); } void strtype::show() { cout << p << " - 長さ:" << len << endl; } int main() { strtype s1("This is a test."), s2("I like C++."); s1.show(); s2.show(); return 0; }
コンパイル
$ g++ -o study48 study48.cpp
実行
$ ./study48 This is a test. - 長さ:15 I like C++. - 長さ:11 pを開放する pを開放する
引用・参考はこちら
【C++】コンストラクタ関数とデストラクタ関数
study41.cpp
#include <iostream> #include <cstring> #include <cstdlib> using namespace std; #define SIZE 255 class strtype { char *p; int len; public: strtype(); ~strtype(); void set( char * ); void show(); }; strtype::strtype() { p = ( char * ) malloc(SIZE); if ( !p ) { cout << "メモリ割り当てエラー" << endl; exit(1); } *p = '\0'; len = 0; } strtype::~strtype() { cout << "pを開放する" << endl; free(p); } void strtype::set( char *ptr ) { if ( strlen( ptr ) >= SIZE ) { cout << "文字列が大きすぎる" << endl; return; } strcpy( p, ptr ); len = strlen( p ); } void strtype::show() { cout << p << " - 長さ:" << len << endl; } int main() { strtype s1, s2; s1.set( "This is a test." ); s2.set( "I like C++." ); s1.show(); s2.show(); return 0; }
コンパイル
$ g++ -o study41 study41.cpp
Warningがでますが、今回は気にしないということで。
実行
$ ./study41 This is a test. - 長さ:15 I like C++. - 長さ:11 pを開放する pを開放する
引用・参考はこちら
【C++】オーバーロード
- 関数オーバーロードの主な用途として、コンパイル時ポリフォーリズムを行うことが挙げられる
- 1つの名前をオーバーロードすることで、複数あるデータの方の種類などに対応できる
- 関数をたくさん作り、それぞれ別の名前をつける必要がない
study29.cpp
#include <iostream> using namespace std; int myabs( int ); long myabs( long ); double myabs( double ); int main() { cout << "-10の絶対値:" << myabs(-10) << endl << endl; cout << "-10Lの絶対値:" << myabs(-10L) << endl << endl; cout << "-10.01の絶対値:" << myabs(-10.01) << endl << endl; } int myabs( int n ) { cout << "整数用のmyabs()" << endl; return n<0 ? -n : n; } long myabs( long n ) { cout << "長整数用のmyabs()" << endl; return n<0 ? -n : n; } double myabs( double n ) { cout << "倍精度浮動小数点数用のmyabs()" << endl; return n<0 ? -n : n; }
コンパイル
g++ -o study29 study29.cpp
実行
$ ./study29 整数用のmyabs() -10の絶対値:10 長整数用のmyabs() -10Lの絶対値:10 倍精度浮動小数点数用のmyabs() -10.01の絶対値:10.01
引用・参考はこちら
【C++】クラスの作成
概要
- 1つのクラスに対して複数のオブジェクトを作ることができる。
- 今回はstackクラスに対して、s1とs2という名前でオブジェクトを作成する。
- オブジェクト同士は干渉しない
study21.cpp
#include <iostream> using namespace std; #define SIZE 10 // 文字列の保存 class stack { char stck[SIZE]; int tos; public: void init(); void push( char ch ); char pop(); }; void stack::init() { tos = 0; } void stack::push( char ch ) { if ( tos == SIZE ) { cout << "スタックはいっぱいです"; return; } stck[tos] = ch; tos++; } char stack::pop() { if ( tos == 0 ) { cout << "スタックは空です"; return 0; } tos--; return stck[tos]; } int main() { stack s1, s2; int i; s1.init(); s2.init(); s1.push('a'); s2.push('x'); s1.push('b'); s2.push('y'); s1.push('c'); s2.push('z'); for ( i=0; i<3; i++ ) cout << "s1をポップする:" << s1.pop() << endl; for ( i=0; i<3; i++ ) cout << "s2をポップする:" << s2.pop() << endl; return 0; }
コンパイル
g++ -o study21 study21.cpp
実行
s1をポップする:c s1をポップする:b s1をポップする:a s2をポップする:z s2をポップする:y s2をポップする:x
引用・参考はこちら
【C++】オブジェクト指向プログラミング
カプセル化
- プログラムコードとプログラムコードが扱うデータを一体化して、外部の干渉から両者を保護するための仕組み。
- 実際にはprivateやpublicといった機能を使用する。publicはprivateの制御インターフェースを提供されるっために使われる。
ポリモーフィズム
継承
- 1つのオブジェクトがほかのオブジェクトの性質を獲得するプロセスのこと。
- オブジェクトは特定の性質を汎用セットとして受け継いだ上で、そのオブジェクトの機能を独自に追加できる。
- 例えば、家は「建物」という汎用クラスの一部、「建物」は「建築物」というクラスの一部、そして「建築物」は汎用的な「人工物」のクラスの一部
- どのクラスえも、小クラスは親クラスが持つ性質をすべて継承し、独自の性質を追加して定義
引用・参考はこちら
独習C++ 第4版
Amazon CAPTCHA
【ROS】tfを用いた座標変換
tfとは
- 座標系管理システム
- ROSでは順運動学の問題にtfを使用している
tfの特徴
- 時間動機ができる
- 分散システムが使える
- rvizとの連携が強力
以下のようなものを作る場合には必須
- 自立移動ロボット
- 複数の関節を持つロボットアーム
- 3次元物体の認識プログラム
$ roslaunch pr2_gazebo pr2_empty_world.launch
$ cd catkin_ws/src/ $ git clone https://github.com/OTL/ez_utils.git $ cd ../ $ catkin_make $ rosrun rviz rviz
表示させるものをいい感じに選択する(下の画像の左メニューを参考に)
そして、TFの「head_plate_frame」と「I_gripper_led_frame」にチェックを入れる
するとこのように、必要なものだけを表示させることができる
相対関係を取得する
- /head_plate_frameが頭
- /I_gripper_led_frameが左手先
tf_echoでこれらのフレーム間の相対位置を調べることができる
$ rosrun tf tf_echo /head_plate_frame /l_gripper_led_frame At time 817.691 - Translation: [0.756, 0.188, -0.271] - Rotation: in Quaternion [-0.002, -0.391, 0.000, 0.920] in RPY (radian) [-0.005, -0.803, 0.003] in RPY (degree) [-0.286, -46.031, 0.167]
そして、look_hand.pyを作成する
#!/usr/bin/env python import rospy import tf2_ros from ez_utils.ez_joints import EzJoints if __name__ == "__main__": rospy.init_node( 'pr2_look_left_hand' ) tf_buffer = tf2_ros.Buffer() tf_listener = tf2_ros.TransformListener( tf_buffer ) # make EzJoints instance and this topic to Publish head = EzJoints( '/head_traj_controller' ) left_arm = EzJoints( '/l_arm_controller' ) yaw_angle = 0.0 # init pitch_angle = 0.0 # init rate = rospy.Rate(10.0) while not rospy.is_shutdown(): try: trans = tf_buffer.lookup_transform( 'head_plate_frame', 'l_gripper_led_frame', rospy.Time() ) # decide angle yaw_angle = trans.transform.translation.y / 1 pitch_angle = -trans.transform.translation.z / 1 print trans.transform.translation head.set_positions( [yaw_angle, pitch_angle] ) # Send angle except ( tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException ): rospy.logwarn( 'tf not found' ) rate.sleep()
- 4行目:EzJointsを使うとPR2の関節を簡単に動かすことができる
- 8、9行目:TFのデータを蓄えるバッファを作成し、引数にしてTransformListenerを作り、tf_listenerに代入する。このtf_listenerを使用してTFの機能にアクセスする
- 20行目:指定したフレーム間の相対関係を取得する。rospy.Time()は取得可能な最新の時間。また、この関数lookup_transformは失敗すると例外を投げるため、try, exceptで例外処理をする
$ chmod 755 look_hand.py $ rosrun ros_start look_hand.py
$ rosrun rqt_ez_publisher rqt_ez_publisher
- topicを選択
- スライダを増やすために+をクリックする
これで上の画像のようになる。
この時、PR2このように顔が手の方向を向いていることが分かる。
【ROS】rviz・rqt_plot
rviz
ROSの可視化といえばrviz
$ rosrun rviz rviz
で起動
Turtlebotのシミュレータを使用してみる
$ sudo apt-get install -y ros-kinetic-turtlebot-gazebo $ source ~/.bashrc $ roslaunch turtlebot_gazebo turtlebot_world.launch
$ roslaunch turtlebot_gazebo amcl_demo.launch
$ rosrun rviz rviz
- 左下のAddをクリック
- RobotModelを選択
すると、TurtleBotが表示される
- Addをクリックし、ByTopicタブを選択
- /mapのmapを選択し、OKをクリック
この地図は予め製作されたもので、Gazeboの画面と比較すると同じようになっていることが分かる。
次に/camera/depth/pointsを追加する。
- AddからBy topicを選択し、/camera/depth/pointのPointCloud2を選択する
次にKinectのセンサ情報をロボットの現在位置に重ねる
- /odom/Odometry
- /move_base/NavfnROS/plan/path
を追加する。
赤い矢印がロボットモデルに重ねて表示される
この画面で、左のメニューのOdometryを開きCovarianceのチェックを外す
このようにrvizではPublishされているTopicから表示したいTopicを選択すると3次元的に表示させることができる
要するに、rostopic echoで表示される文字列がrvizで可視化できる
また、rvizでは出力だけでなく入力もできる
上のメニューの2D Nav Goalを選択し、
このように矢印をひっぱりると
このように赤い矢印が表示される。
別の角度で実行してみると、緑の線が出ていることも分かる。
赤い矢印が履歴として表示され、緑の細い線(/move_base/navfnROS/plan)がロボットがどこに移動使用しているのかを表している。
rqt
- Robot + Qt のこと
- Qtはマルチプラットフォームに対応したGUIのフレームワーク
- rqtはQtを使用したロボットのGUIフレームワーク
- rqt_graphやrqt_consoleなどがある
rqt_ez_publisherを使う
Topicをスライダーなどを使ってpublishできる
$ sudo apt-get isntall ros-kinetic-rqt-ez-publisher $ roscore
$ rosrun turtlelesim turtlesim_node
$ rosrun rqt_ez_publisher rqt_ez_publisher
そして、/turtle1/cmd_velを選択
- 画面を最大化するとスライダーを動かしやすくなる
- このGUIで亀を動かすことができる
- スライダを動かすたびにMessageがpublishされる
rqt_plotを使ってみる
$ rqt_plot
Topic名と変数を繋いで書くことでPlotしたい要素を指定
リアルタイムで描画される