Quantcast
Channel: demura.net
Viewing all 757 articles
Browse latest View live

ROS演習1:亀を動かす

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。ROSをインストールしたので、動作確認を兼ねて亀で遊んでみましょう。この記事は以下の記事を参考にしています。

—————————————————————

1. 亀を動かす

(1) 新しい端末を開き、「roscore」と入力しEnterキーを押し、roscoreを起動する。ノード間で通信するために必要。ノードはROSの実行プログラム。

roscore

(2) 新しい端末を開き、「 rosrun turtlesim turtlesim_node」と入力しEnterキーを押すと、亀のいる水色のウインドウが開く。rosrunコマンドの使い方は、rosrun  [パッケージ名] [ノード名]で、パッケージのノードを起動する。パッケージはある機能を実現するためのプログラムの集まり。この例では、turtlesimというパッケージの中のturtlesim_nodeノードを起動している。

turtlesim_node

turtlesim

(3) キーボードで亀を操作。新しい端末を開き「rosrun turtlesim turtle_teleop_key」と入力する。キーボードの矢印キーで亀を動かすことができる。動かない場合は、ここで入力した端末をクリックして選択する。亀のいるTurtleSimウインドウや他の端末をクリックして選択した場合は動かないので注意。

teleop

teleop2

2.解説

動作を確認するために亀と遊んだので少しお勉強。亀が矢印キーで動く仕組みは、turtlesimノードがturtle_teleop_keyノードから送られた(publish、出版)キーのデータを受け取り(subscribe、購読)、亀を動かしている。このデータのことをROSではトピック(topic)とよぶ。これはPublish/Subscribe (出版/購読型モデル)に基づいている。ROSではトピックを使った通信の他にクライアント/サーバーモデルのサービスもある。

3.演習

以下のROSチュートリアルの1.2 ROSトピックから最後まで説明に従って、自分のノートパソコンで動作を確認しよう!

4.ホームワーク

終わり

 


ROS演習2:はじめてのROSプログラミング

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。ROSでHellow Worldと表示するプログラムを作り、ビルドして実行してみましょう。この記事は以下のROS Wikiの記事を参考にしています。

———————–
1. ワークスペース(作業場所)の作成
これからROSでいろいろなプログラムを作っていきます。まずは、その専用ディレクトリ(フォルダ)を作りましょう。ROSではこれをワークスペースとよびます。catkin_init_workspaceコマンドでワークスペースを作ります。以下のコマンドを実行してください。なお、先頭の$は入力を受け付けるコマンドプロンプトなので打つ必要はありません。

$ source /opt/ros/indigo/setup.bash
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace

2. ビルドの方法
ROSではソースコードをビルドするときにcatkin_makeコマンドを使います。このコマンドを実行するときは~/catkin_wsに移動しなければいけません。重要なので覚えておきましょう。
次のコマンドを実行してください。
$ cd ~/catkin_ws
$ catkin_make
実行後にlsコマンドを実行すると、buildとdevelディレクトリが新たに作成されていることがわかります。

3.  設定
ここで作成したcatkin_wsを有効にするためには以下のコマンドを実行する必要があります。
$ source ~/catkin_ws/devel/setup.bash
毎回、実行するのは面倒なので~/.bashrcの一番最後にテキストエディターgeditで、上のコマンドを付け加え保存しましょう。まず、次のコマンドでgeditを実行します。
$ cd
$ gedit .bashrc
bashrc
.bashrcの中にsource /opt/ros/indigo/setup.bashがない場合は、下図赤枠のように2行追加してください。保存はgeditの上ツールバーにある「保存」をクリックします。では、うまく設定されたか、次のコマンドで確認しましょう。
$ source .bashrc
$ echo $ROS_PACKAGE_PATH
つぎのように表示されたら成功です。
path失敗した場合は、設定をもう一度実行してください。打ち間違えがないか注意しましょう。

4. パッケージの作成
準備ができたので早速、パッケージを作りましょう。パッケージは次のcatkin_create_pkgコマンドで作ります。依存パッケージはそのパッケージを作るために必要なパッケージです。
catkin_create_pkg <パッケージ名> [依存パッケージ1] [依存パッケージ2] [依存パッケージ3]
helloパッケージを作りましょう。ここではC++でコーディングするのでroscppパッケージしか使いません。Pythonを使う場合はrospyになります。
$ cd ~/catkin_ws/src
$ catkin_create_pkg hello roscpp
上手く作成しているか確認します。
$ cd ~/catkin_ws/src/hello
$ ls
CMakeLIsts.txt, include, package.xml, srcができていれば成功です。
package.xmlに作成者(maintainer)の情報などを書きます。ここでは省略します。ROS Wikiのpackage.xmlを参考にしてください。

5. ソースコードの作成とビルド
$ cd ~/catkin_ws/src/hello/src
$ gedit hello_node.cpp
エディタが開くので以下をソースコードを打ち込み保存する。
hello

~/catkin_ws/src/hello/CMakeLists.txtの129行目、136~138行目のコメントを次のように外す。
cmakelist
ビルドします。
$ cd ~/catkin_ws
$ catkin_make

6. 実行
以下のroscoreコマンドでMaster(マスター)を実行する。他のノードを実行する前に必要です。
$ roscore
ノードを実行するためにはrosrunコマンドを使います。使い方は次のとおり。
rosrun パッケージ名 実行ファイル名
別の端末を開き、rosrunコマンドでhello_nodeノードを実行する。
なお、hello_nodeは~/catkin_ws/devel/lib/hello/hello_nodeにcatkin_makeコマンドで作られたものです。
$ rosrun hello hello_node
次のように表示されたら成功。終わり。
hello_world

4.ホームワーク

ROS演習3:シミュレータを動かそう

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。シミュレータGAZEBOを使い、Turtlebotを動かします。次のROS Wikiを参考にしています。

1.  Turtlebot用のパッケージインストール
まず、Turtlebot用のパッケージをインストール。端末を開き、次のコマンドを実行。
$ sudo apt-get update
$ sudo apt-get install ros-indigo-turtlebot ros-indigo-turtlebot-apps ros-indigo-turtlebot-interactions ros-indigo-turtlebot-simulator ros-indigo-kobuki-ftdi ros-indigo-rocon-remocon ros-indigo-rocon-qt-library ros-indigo-ar-track-alvar-msgs
$ . /opt/ros/indigo/setup.bash
上はドットコマンド(.)といい、ドット(.)の後にスペース、そのあとにコマンドを入れる。機能は現在のシェルからそのコマンドを実行する。通常はコマンドを実行すると別のシェルが呼び出されコマンドを実行するが、現在のシェル変数などは引き継がれない。また、ドットコマンドは、そのコマンドの実行権限がなくても実行できる。ドットコマンドの代わりにsourceコマンドも利用できる。sourceコマンドを利用した場合は source /opt/ros/indigo/setup.bash となる。
シミュレータだけなら必要ないが、kobuki実機を動かす場合もあるので、自動でデバイスを使えるように以下のコマンドを実行しよう。
$ sudo rosrun kobuki_ftdi create_udev_rules

2. ロボットをキーボードから動かそう
これからキーボードでシミュレータ上のロボットを操縦しよう。まず、roslaunchコマンドでシミュレータを起動。
$ roslaunch turtlebot_gazebo turtlebot_world.launch
初回はネットからモデルを取得するので、私の環境で10分程度かかった。しばらくすると次のようなウインドウが開く。黒い円柱状のロボットがturtlebot。
turtlebot-gazebo

次に、ロボットを動かすための最小限(minimal)ノードを起動。ここで、turtlebot_bringupはパッケージ名。minimal.lauchはlaunchファイル。
$ roslaunch turtlebot_bringup minimal.launch

別の端末を開き、次のコマンドを入力するとキーボードからロボットを操縦するためのlaunchファイルを起動。
$ roslaunch turtlebot_teleop keyboard_teleop.launch

端末に下のように表示される。u  i o  j  k  l  m , .キーでロボットを操作できる。いずれかのキーを押してロボットを動かそう!マウスのカーソルがkeyboard_teleop.launchを起動した端末上になければ動かないので注意。

さらに、動かない場合は、minimal.launchを起動している端末ごと終了させて、再度、新しい端末を開いて、minimal.launchを起動する。
teleop

3. キーボードから動かすプログラムを作ろう!
次に、キーボードからロボットを操縦するmy_teleopパッケージを作ろう。
ROS演習2と同じ要領でmy_teleopパッケージを作る。忘れた人はROS演習2を見ながらやろう。今週の例ではhello, hello_nodeをmy_teleopに置き換える。

以下のプログラムはmy_teleop.cpp。なお、このプログラムはトピック通信のpublisher(配信者)プログラムの簡単な例になっている。プログラムの説明はソースコード内のコメントを参照。テキストエディタ(gedit)にコピペして名前を付けて保存。
保存ディレクトリは~/catkin_ws/src/my_teleop/srcの中。

#include "ros/ros.h"  // rosで必要はヘッダーファイル                                    
#include <geometry_msgs/Twist.h> // ロボットを動かすために必要                          
using namespace std;

int main(int argc, char **argv)
{
  ros::init(argc, argv, "my_teleop");
  // initでROSを初期化し、my_teleopという名前をノードにつける                        
  // 同じ名前のノードが複数あるとだめなので、ユニークな名前をつける                 

  ros::NodeHandle nh;
  // ノードハンドラの作成。ハンドラは必要時に起動される。                         

  ros::Publisher  pub;
  // パブリッシャの作成。トピックに対してデータを送信。                                 

  ros::Rate rate(10);
  // ループの頻度を設定。この場合は10Hz、1秒間に10回数、1ループ100ms。                  

  geometry_msgs::Twist vel;
  // geometry_msgs::Twist この型は並進速度と回転速度(vector3:3次元ベクトル) を合わせたもので、速度指令によく使われる                                           

  pub= nh.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop", 10);
  // マスターにgeometry_msgs::Twist型のデータを送ることを伝える                         
  // マスターは/cmd_vel_mux/input/teleopトピック(1番目の引数)を購読する                
  // 全てのノードにトピックができたことを知らせる(advertise)。                          
  // 2番目の引数はデータのバッファサイズ                                                

  std::cout << "f: forward, b: backward, r: right, l:left" << std::endl;

while (ros::ok()) // このノードが使える間は無限ループ                                 
    {
      char key;  // 入力キーの値                                                        

      cin >> key;
      cout << key << endl;

      switch (key) {
      case 'f': vel.linear.x  =  0.5; break;
      case 'b': vel.linear.x  = -0.5; break;
      case 'l': vel.angular.z =  1.0; break;
      case 'r': vel.angular.z = -1.0; break;
        // linear.xは前後方向の並進速度(m/s)                                            
        // angular.zは回転速度(rad/s)                                                   
      }

      pub.publish(vel); // 速度メッセージを送信                                         
      ros::spinOnce();  // コールバック関数を呼ぶ                                       
      vel.linear.x  = 0.0; // 並進速度の初期化                                              
      vel.angular.z = 0.0; // 回転速度の初期化
      rate.sleep();     // 指定した周期でループするよう寝て待つ                         

     
    }

  return 0;
}

では、以下のコマンドでビルドして実行しよう。

$ cd ~/catkin_ws
$ catkin_make

先ほどの、roslaunch turtlebot_teleop keyboard_teleop.launch の代わりに、次のコマンドを実行する。keyboard_teleop.launchを起動した端末は閉じる。
$ rosrun my_teleop my_teleop

f, b, l, rキーでロボットが移動したら成功。キーを押した後はエンターキーを押す。お疲れ様!

終わり

ROS演習4:双方向通信しよう!(サービス)

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。今回はROSのサービスを理解しましょう。次のROS Wikiを参考にしています。

サービスはROSの通信方法の一つで、双方向通信に使います。ある仕事をお願いするクライアントとそれを処理して返すサーバーからなります。今回、作成するプログラムは速度指令値を送るクライアントと、それをロボットへ伝え(リクエスト)、ロボットから現在の速度を取得しクライアントに返す(レスポンス)サーバーです。次の手順でやりましょう。この例は、前回学んだトピック通信も入れていますので、実践的な内容です。

1.my_serviceパッケージの作成
$ cd ~/catkin_ws/src
$ catkin_create_pkg my_service std_msgs rospy roscpp

2.srvファイルの作成。srvファイルはやり取りするデータの型を表すテキストファイル。拡張子がsrv、この例のファイル名はWheel.srv。
$ cd ~/catkin_ws/src/my_service
$ mkdir srv
$ cd srv
$ gedit Wheel.srv
内容は次のコード。——-の上が入力(リクエスト)、下が出力(レスポンス)を表す。

float64 target_linear_velocity
float64 target_angular_velocity
---------------
float64 current_linear_velocity
float64 current_angular_velocity

並進、回転速度指令値target_linear_velocity, target_angular_velocityがリクエストされると、
現在の並進、回転速度current_linear_velocity, current_angular_velocityがリスポンスされる。

3.Package.xmlの変更
~/catkin_ws/src/my_service/Package.xmlの35、39行目のコメントタグを次のように外す。message_generation, message_runtimeを有効にする必要あり。

  <!-- Use build_depend for packages you need at compile time: -->              
  <build_depend>message_generation</build_depend>
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use run_depend for packages you need at runtime: -->                     
  <run_depend>message_runtime</run_depend>

4.CMakeLists.txtの変更
~/catkin_ws/src/my_service/CMakeLists.txtの11行目、std_msgsの下にmessage_generationを追加。

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospyp
  std_msgs
  message_generation
)

次の54~59行目を

## Generate services in the 'srv' folder                                        
# add_service_files(                                                            
#   FILES                                                                       
#   Service1.srv                                                                
#   Service2.srv                                                                
# )   

以下に変更。

## Generate services in the 'srv' folder                                        
 add_service_files(
   FILES
   Wheel.srv
 )

次の70~74行目

## Generate added messages and services with any dependencies listed here       
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

のコメントを外し、次にする。
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)

次に示す102~107行目

#catkin_package(                                                                
#  INCLUDE_DIRS include                                                         
#  LIBRARIES my_service                                                         
#  CATKIN_DEPENDS roscpp rospy std_msgs                                         
#  DEPENDS system_lib                                                           
#)   

を次に変更

catkin_package(                                                                
  INCLUDE_DIRS include                                                         
  LIBRARIES my_service                                                         
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime                                        
  DEPENDS system_lib                                                           
)   

5.ビルド
ソースコードを書く前にサービスのライブラリを作成するためにcatkin_makeしてビルドする。
$ cd ~/catkin_ws
$ catkin_make
ビルド時にエラーがでたら、Package.xml, CMakelists.txtに間違えがないか確認し、直して再度ビルド。

6.サービスサーバーのソースコード作成
では、依頼された仕事を処理するサーバープログラムを作ります。次のプログラムをgeditなどを使いwheel_server.cppというファイル名を付けて~/catkin_ws/src/my_service/src/wheel_server.cppと保存。一字でも打ち間違えると動かないのでコピペする。

#include "ros/ros.h"
#include <geometry_msgs/Twist.h>
#include "nav_msgs/Odometry.h"
#include "my_service/Wheel.h"  // 自動的に作られる                                         

class Server {
public:
  Server();      // コンストラクタ                                                         
  ~Server() {};  // デストラクタ                                                           
  // オドメトリのコールバック関数                                                          
  void odomCallback(const nav_msgs::Odometry::ConstPtr& odom);
  // サーバーのコールバック関数(サービスの本体)                                          
  bool wheelService(my_service::Wheel::Request  &req,
                    my_service::Wheel::Response &res);
  void loop(); // ループ関数                                                               

private:
  ros::Publisher cmd_pub;     // パブリッシャ                                              
  ros::Subscriber odom_sub;   // サブスクライバ                                            
  ros::NodeHandle nh;         // ノードハンドルの宣言                                      
  ros::ServiceServer service; // サービス                                                  
  double tmp_linear_velocity; // 現在の並進速度                                            
  double tmp_angluar_velocity; // 現在の回転速度                                           
  const static double max_linear_velocity =  0.7; // 最大並進速度                          
  const static double min_linear_velocity = -0.7; // 最小並進速度                          
  const static double max_angular_velocity =  1.2; // 最大回転速度                         
  const static double min_angular_velocity = -1.2; // 最小回転速度    
  geometry_msgs::Twist target_vel, tmp_vel; // 目標速度、現在の速度                        
};

// コンストラクタ                                                                          
Server::Server()
{
  ROS_INFO("Ready to wheel");

  //サービスの設定                                                                         
  service = nh.advertiseService("wheel",&Server::wheelService,this);

  // パブリッシャ(配信)の設定:                                                             
  cmd_pub= nh.advertise<geometry_msgs::Twist>("/mobile_base/commands/velocity", 10);

  // サブスクライバ(購読)の設定                                                            
  // /odomトピックはロボットの速度情報を持っている                                         
  odom_sub = nh.subscribe("/odom", 10, &Server::odomCallback, this);

  // 速度の初期化                                                                          
  target_vel.linear.x  = 0.0;
  target_vel.linear.y  = 0.0;
  target_vel.linear.z  = 0.0;
  target_vel.angular.x = 0.0;
  target_vel.angular.y = 0.0;
  target_vel.angular.z = 0.0;
  tmp_vel.linear.x  = 0.0;
  tmp_vel.linear.y  = 0.0;
  tmp_vel.linear.z  = 0.0;
  tmp_vel.angular.x = 0.0;
  tmp_vel.angular.y = 0.0;
  tmp_vel.angular.z = 0.0;
}

// サーバーのコールバック関数                                                              
bool Server::wheelService(my_service::Wheel::Request  &req,
                          my_service::Wheel::Response &res)
{
  ROS_INFO("Set velocity: linear=%.2f angular=%.2f",
           req.target_linear_velocity, req.target_angular_velocity);
  // 指令速度が最小、最大速度内かチェック                                                  
  if (min_linear_velocity  > req.target_linear_velocity ||
      max_linear_velocity  < req.target_linear_velocity)  return false;
  if (min_angular_velocity > req.target_angular_velocity ||
      max_angular_velocity < req.target_angular_velocity) return false;
  // クライアントからの速度をロボットの速度指令とする                                      
  target_vel.linear.x  = req.target_linear_velocity;
  target_vel.angular.z = req.target_angular_velocity;
  // /odomトピックからサブスクライブした速度情報をクライアントに返す                       
  res.current_linear_velocity  = tmp_vel.linear.x;
  res.current_angular_velocity = tmp_vel.angular.z;
  return true;
}
// オドメトリのコールバック関数(現在速度を知る)                                          
void Server::odomCallback(const nav_msgs::Odometry::ConstPtr& odom)
{
  tmp_vel = odom->twist.twist; // 現在の速度ゲット                                         
}

// ループ関数                                                                              
void Server::loop()
{
  ros::Rate loop_rate(30); // Hz                                                           

  while(ros::ok()) {
    // ロボットを動かすため目標速度をパブリッシュ                                          
    cmd_pub.publish(target_vel);
    // コールバック関数を呼ぶ                                                              
    ros::spinOnce();
    // 決められた周期でループするため寝て待つ                                              
    loop_rate.sleep();
  }
}

int main(int argc, char **argv)
{
  //ROSの初期化 wheel_serverはノード名                                                     
  ros::init(argc, argv, "wheel_server");

  Server svr;
  svr.loop();
  return 0;
}

7.サービスクライアントのソースコード作成
次に仕事を依頼するのクライアントのソースコートを作成する。以下のソースコードをwheel_client.cppという名前で~/catkin_ws/src/my_service/src/wheel_client.cpp保存する。

#include "ros/ros.h"
#include "my_service/Wheel.h"  // 自動的に作られる                                         

int main(int argc, char **argv)
{
  // 初期化 wheel_clientノード                                                            
  ros::init(argc, argv, "wheel_client");

  ros::NodeHandle nh;
  // サービスクライアントの設定                                                            
  ros::ServiceClient client = nh.serviceClient<my_service::Wheel>("wheel");

  my_service::Wheel srv;

  std::cout << "Input target linear  velocity:";
  std::cin >> srv.request.target_linear_velocity;
  std::cout << "Input target angular velocity:";
  std::cin >> srv.request.target_angular_velocity;

  // サービスを呼ぶ                                                                        
  if (client.call(srv)) {
    // 成功したらサーバーからのレスポンスを表示                                            
    ROS_INFO("Current linear_vel=%f  angular_vel=%f",
             (double) srv.response.current_linear_velocity,
             (double) srv.response.current_angular_velocity);
  }
  else {
    // 失敗したらエラー表示                                                                
    ROS_ERROR("Faild to call service wheel");
    return 1;
  }
  return 0;
}

8.CMakeLists.txtの変更とビルド
以下をCMakeLists.txtに追加

## Declare a C++ executable                                                                
add_executable(wheel_server src/wheel_server.cpp)
add_dependencies(wheel_server my_service_gencpp)
target_link_libraries(wheel_server ${catkin_LIBRARIES})

add_executable(wheel_client src/wheel_client.cpp)
add_dependencies(wheel_client my_service_gencpp)
target_link_libraries(wheel_client ${catkin_LIBRARIES})

$ cd ~/catkin_ws
$ catkin_make

9.実行
端末を4つ開き、各端末で以下のコマンドを実行
$ roslaunch turtlebot_gazebo turtlebot_world.launch
$ roslaunch turtlebot_bringup minimal.launch 
$ rosrun my_service wheel_server
サーバーは次のように表示される。
server1

$ rosrun my_service wheel_client
クライアントはキーボードから入力(速度指令値)をサーバーへ送る。速度指令値が最小、最大値の範囲外ならエラーを返す。それ以外は、シミュレータ上のロボットが動きます。
client1
成功したら終わり。うまく動かない場合は、打ち間違えや手順に間違いがないか確認し、再度実行しましょう。

なお、今回のソースコードをまとめてここmy_service.tgzに置いておきます。
解凍の仕方は次の通り。
$ cp ./my_service.tgz ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ tar xvzf my_service.tgz

turtlebot

ROS演習5:地図作製・自己位置推定(SLAM, AMCL)

$
0
0

rviz2この記事は私が担当している講義ロボットプログラミングⅡ用です。今回は地図作成(SLAM)と自己位置推定(AMCL)のパッケージを使いロボットにナビゲーションをさせましょう! 本記事を以下のチュートリアルを参考にしています。

1. 地図生成

(1) 端末を3つ開き以下のコマンドを実行する。

gazeboシミュレータを起動

  • $ roslaunch turtlebot_gazebo turtlebot_world.launch

地図生成のgmappingを起動

  • $ roslaunch turtlebot_gazebo gmapping_demo.launch

ROSのビジュアライションツールrvizを起動

  • $ roslaunch turtlebot_rviz_launchers view_navigation.launch

注:rvizがOpenGL関係のエラーで落ちる場合は、以下の1行を.bashrcの最後に付け加える。

  • export LIBGL_ALWAYS_SOFTWARE=1

(2) 端末を開き、以下のコマンドでロボットを動かし、地図を作る。

  • $ roslaunch turtlebot_teleop keyboard_teleop.launch

(3)  端末を開き、以下のコマンドで地図を保存する。mymapは保存する地図名なので適宜変更する。

  • $ mkdir  ~/maps
  • $ rosrun map_server map_saver -f  ~/maps/mymap

 

2. ナビゲーション

一度開いている端末を全部閉じ、ノードを落とす。

(1)  gazeboシミュレータを起動

  • $ roslaunch turtlebot_gazebo turtlebot_world.launch

(2) 自己位置推定ノードの起動
上で作成した地図を使ってナビゲーションできるが、ここではすでに作られている地図を使う。

  • $ roslaunch turtlebot_gazebo amcl_demo.launch map_file:=/opt/ros/indigo/share/turtlebot_gazebo/maps/playground.yaml

(3) rvizを起動

  • $ roslaunch turtlebot_rviz_launchers view_navigation.launch

(4) ロボット初期位置の設定
上で起動したrviz(上図)の”2D Pose Estimation”をクリックして選択し、下図シミュレータのロボットの向きと位置が合うように、rviz上でロボットの位置と向きを設定する。ロボットの位置にマウスのカーソールを持って行き、ロボットの向きにドラッグすると設定終わり。

(5) ゴールの設定
次にrvizの”2D Nav Goal”をクリックして、初期位置を設定したのと同様に、ゴールの位置と向きを設定する。設定するとロボットが自動で動き出す。

gazebo終わり

ROS演習6:シンプルなゴール(ActionLib)

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。今回はActionLibを使った以下のROSチュートリアルを実行しましょう。

ソース

 
// 本プログラムは
// http://wiki.ros.org/ja/navigation/Tutorials/SendingSimpleGoals
// を改変しています。
#include <ros/ros.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>

typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;

struct MyPose {
  double x;
  double y;
  double yaw;
};

int main(int argc, char** argv){
  MyPose way_point[] = {{5.0, 0.0, 0.5 * M_PI}, {0.0, 5.0, 0.5 * M_PI}, 
	                {999, 999, 999}};

  ros::init(argc, argv, "simple_goal");

  // アクションクライアンを作成。1番目の引数は接続するアクションサーバー名。
  // アクションサーバーが立ち上がっていないとだめ。
  // 2番目の引数はtrueならスレッドを自動的に回す(ros::spin()。
  MoveBaseClient ac("move_base", true);
  // アクションサーバーが起動するまで待つ。引数はタイムアウトする時間(秒)。
  // この例では5秒間待つ(ブロックされる)
  while(!ac.waitForServer(ros::Duration(5.0))){
      ROS_INFO("Waiting for the move_base action server to come up");
  }

  ROS_INFO("The server comes up");
  move_base_msgs::MoveBaseGoal goal;
  // base_link座標系(ロボット座標系)
  goal.target_pose.header.frame_id = "base_link";
  // 現在時刻                                                                       
  goal.target_pose.header.stamp = ros::Time::now();


  int i = 0;
  while (ros::ok()) {
    // ROSではロボットの進行方向がx座標、左方向がy座標、上方向がz座標
    goal.target_pose.pose.position.x =  way_point[i].x;
    goal.target_pose.pose.position.y =  way_point[i].y;
    goal.target_pose.pose.orientation.w = 1; 

    ROS_INFO("Sending goal: No.%d", i+1);
    // サーバーにgoalを送信
    ac.sendGoal(goal);

    // 結果が返ってくるまで30.0[s] 待つ。ここでブロックされる。
    bool succeeded = ac.waitForResult(ros::Duration(30.0));

    // 結果を見て、成功ならSucceeded、失敗ならFailedと表示
    actionlib::SimpleClientGoalState state = ac.getState();

    if(succeeded) {
      ROS_INFO("Succeeded: No.%d (%s)",i+1, state.toString().c_str());
    }
    else {
      ROS_INFO("Failed: No.%d (%s)",i+1, state.toString().c_str());
    }
    i++;
  }
  return 0;
}
  • packageのディレクトリ毎、圧縮したファイル
  • 展開・ビルド方法
    • $  cp  simple_goal.tgz    ~/catkin_ws/src/.
    • $  cd  ~/catkin_ws/src
    • $  tar  xvzf  simple_goal.tgz
    • $  cd  ~/catkin_ws
    • $  catkin_make

演習

  • 上で展開したsimple_goalを次の要領で実行しよう。
    • $ roslaunch turtlebot_gazebo turtlebot_world.launch
    • $ roslaunch turtlebot_gazebo amcl_demo.launch
    • $ rosrun simple_goal simple_goal
  • simple_goal.cppをベースに1周するプログラムを作ろう!

 

 

ROS演習7:ロボットビジョン (cv_bridge)

$
0
0


coke_can

この記事は私が担当している講義ロボットプログラミングⅡ用です。今回はcv_bridgeを使います。ROSでOpenCVを使いgazeboシミュレータのRGB-Dセンサから取得した画像を処理します。赤色の抽出とエッジ抽出を行います。

この記事は、以下のROSチュートリアルと「ROSで始めるロボットプログラミング、小倉著」を参考にしています。

ソース:ROSのチュートリアルと「ROSで始めるロボットプログラミング」をベースに改変しています。

 
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

static const std::string OPENCV_WINDOW = "Image window";

class ImageConverter
{
  ros::NodeHandle nh_;
  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  image_transport::Publisher image_pub_;

public:
  // コンストラクタ
 ImageConverter()
    : it_(nh_)
  {
    // カラー画像をサブスクライブ                                                                
    image_sub_ = it_.subscribe("/camera/rgb/image_raw", 1,
      &ImageConverter::imageCb, this);
    // 処理した画像をパブリッシュ                                                                                          
    image_pub_ = it_.advertise("/image_topic", 1);
 }

  // デストラクタ
  ~ImageConverter()
  {
    cv::destroyWindow(OPENCV_WINDOW);
  }

  // コールバック関数
  void imageCb(const sensor_msgs::ImageConstPtr& msg)
  {
    cv_bridge::CvImagePtr cv_ptr, cv_ptr2, cv_ptr3;
 try
    {
      // ROSからOpenCVの形式にtoCvCopy()で変換。cv_ptr->imageがcv::Matフォーマット。
      cv_ptr    = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
      cv_ptr3   = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::MONO8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

    cv::Mat hsv_image, color_mask, gray_image, cv_image2, cv_image3;
    // RGB表色系をHSV表色系へ変換して、hsv_imageに格納
    cv::cvtColor(cv_ptr->image, hsv_image, CV_BGR2HSV);

    // 色相(Hue), 彩度(Saturation), 明暗(Value, brightness) 
    // 指定した範囲の色でマスク画像color_mask(CV_8U:符号なし8ビット整数)を生成  
    // マスク画像は指定した範囲の色に該当する要素は255(8ビットすべて1)、それ以外は0                                                      
    cv::inRange(hsv_image, cv::Scalar(150, 100, 50, 0) , cv::Scalar(180, 255, 255, 0), color_mask);
    // ビット毎の論理積。マスク画像は指定した範囲以外は0で、指定範囲の要素は255なので、ビット毎の論理積を適用すると、指定した範囲の色に対応する要素はそのままで、他は0になる。
    cv::bitwise_and(cv_ptr->image, cv_ptr->image, cv_image2, color_mask);
    // グレースケールに変換
    cv::cvtColor(cv_ptr->image, gray_image, CV_BGR2GRAY);
    // エッジを検出するためにCannyアルゴリズムを適用
    cv::Canny(gray_image, cv_ptr3->image, 15.0, 30.0, 3);

    // ウインドウに円を描画                                                
    cv::circle(cv_ptr->image, cv::Point(100, 100), 20, CV_RGB(0,255,0));

    // 画像サイズは縦横半分に変更
    cv::Mat cv_half_image, cv_half_image2, cv_half_image3;
    cv::resize(cv_ptr->image, cv_half_image,cv::Size(),0.5,0.5);
    cv::resize(cv_image2, cv_half_image2,cv::Size(),0.5,0.5);
    cv::resize(cv_ptr3->image, cv_half_image3,cv::Size(),0.5,0.5);

    // ウインドウ表示                                                                         
    cv::imshow("Original Image", cv_half_image);
    cv::imshow("Result Image", cv_half_image2);
    cv::imshow("Edge Image", cv_half_image3);
    cv::waitKey(3);
 
    // エッジ画像をパブリッシュ。OpenCVからROS形式にtoImageMsg()で変換。                                                            
    image_pub_.publish(cv_ptr3->toImageMsg());
  }
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_converter");
  ImageConverter ic;
  ros::spin();
  return 0;
}

準備

  • $ cd ~/catkin_ws/src
  • $ catkin_create_pkg cv_bridge_tutorial sensor_msgs opencv2 cv_bridge roscpp std_msgs
  • $ cd cv_bridge_tutorial/src
  • $ gedit cv_bridge_tutorial.cpp
    上のソースコードをgeditにコピペして保存する。
  • $ cd ~/cakin_ws
  • $ catkin_make

簡単な準備:時間のない方は以下で準備してください。CMakeLists.txtやPackage.xmlを編集する必要がありません。

  • 以下のファイルを~/catkin_ws/srcの下にコピーする
  • $ cd ~/catkin_ws/src
  • $ tar xvzf cv_bridge_tutorial.tgz
  • $ cd ~/catkin_ws
  • $ catkin_make

実行方法

  • $ roslaunch turtlebot_gazebo turtlebot_world.launch
  • $ rosrun cv_bridge_tutorial cv_bridge_tutorial
  • 次のコマンドでロボットを動かしてカメラ画像が変わるのを確認しよう
    • $ roslaunch turtlebot_teleop keyboard_teleop.launch

演 習

  • シミュレータにコカ・コーラの缶(Coke Can)を挿入して、それを追うプログラムを作ろう

終わり

ROS演習8:ロボットアーム

$
0
0

arm2-gazebo

arm2-rviz

今週はgazeboを使い2自由度のロボットアームを作り、関節を動かします。2自由度ロボットアームのURDFは参考リンクを参照してください。このサンプルでは参考リンクのrrbot.xacroをベースに作っています。

ソース
Turtlebotをテレオペ(遠隔操作)したソースコードをベースに ~/catkin_ws/src/armbot2/src/teleop.cppを作成しました。ジョイント1とジョイント2の目標角度をパブリッシュし、/armbot2/joint_statesトピックをサブスクライブしジョイントの現在値を取得しています。この例では、目標角度に追従するのに時間がかかるのでループ毎に1秒スリープしてから現在値を取得しています。

 
// ~/catkin_ws/src/armbot2/src/teleop.cpp
#include "ros/ros.h"  // rosで必要はヘッダーファイル
#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

using namespace std;
std_msgs::Float64 tmp_joint1, tmp_joint2;
double pos_x, pos_y, pos_z;

void monitorJointState(const sensor_msgs::JointState::ConstPtr& jointstate)
{
  tmp_joint1.data = jointstate->position[0];
  tmp_joint2.data = jointstate->position[1]; 
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "teleop");  // ノードの初期化
  ros::NodeHandle nh; // ノードハンドラ  
  ros::Publisher  pub_joint1, pub_joint2;  // パブリッシャの作成
  ros::Subscriber sub_joints, sub_sensor;  // サブスクライバの作成

  std_msgs::Float64 target_joint1, target_joint2;

  pub_joint1 = nh.advertise<std_msgs::Float64>("/armbot2/joint1_position_controller/command", 100);
  pub_joint2 = nh.advertise<std_msgs::Float64>
("/armbot2/joint2_position_controller/command", 100);
  sub_joints = nh.subscribe("/armbot2/joint_states", 100, monitorJointState);

  target_joint1.data = 0;
  target_joint2.data = 0;

  while (ros::ok()) { // このノードが使える間は無限ループ
    char key;  // 入力キーの値

    ROS_INFO("[Input] j: Joint1++, f: Joint1--, k: Joint2++, d:Joint2--");
    cin >> key; 
    cout << key << endl;

    switch (key) {
    case 'j': target_joint1.data  +=  5 * M_PI/180.0; break;
    case 'f': target_joint1.data  -=  5 * M_PI/180.0; break;
    case 'k': target_joint2.data  +=  5 * M_PI/180.0; break;
    case 'd': target_joint2.data  -=  5 * M_PI/180.0; break;
    default: ROS_INFO("Input j,f,k,d");
    }
      
    pub_joint1.publish(target_joint1); // 角度を送信    
    pub_joint2.publish(target_joint2);
    ROS_INFO("Targe: Joint1=%f Joint2=%f", target_joint1.data, target_joint2.data);

    usleep(1000*1000); // 制御に時間がかかるので1秒寝て待つ
    ros::spinOnce();   // コールバック関数を呼ぶ
    ROS_INFO("Tmp:Joint1=%f Joint2=%f", tmp_joint1.data,    tmp_joint2.data);
  }
  
  return 0;
}

なお、ジョイントのPIDゲインやコントローラーは以下のファイルに記述されています。詳細については参考リンクをご覧ください。
~/catkin_ws/src/armbot2/config/armbot2_control.yaml
準 備

  • $ sudo apt-get update
  • $ sudo apt-get install ros-indigo-gazebo-ros-pkgs ros-indigo-gazebo-ros-control
  • $ sudo apt-get install ros-indigo-gazebo-plugins  ros-indigo-gazebo-ros
  • $ sudo apt-get install ros-indigo-moveit-*
  • $ sudo apt-get install ros-indigo-ros-control ros-indigo-ros-controllers  ros-indigo-joint-state-controller ros-indigo-effort-controllers ros-indigo-position-controllers ros-indigo-joint-trajectory-controller
  • $ sudo apt-get install liburdfdom-tools

プログラムとビルド

  • 以下をホームディレクトリ(/home/ユーザ名)にダウンロードする。
  • $ cd
  • $ cp  armbot2-150108.tgz  ~/catkin_ws/src
  • $ cd  ~/catkin_ws/src
  • $ tar  xvzf  armbot2-150108.tgz
  • $ cd  ~/catkin_ws
  • $ catkin_make

実 行
端末を2つ開き、次のコマンドを実行する。

  • $ roslaunch  armbot2  armbot2.launch
  • $ rosrun armbot2 armbot2
    • armbot2を実行している端末をクリックし、j, k, f, dコマンドを入力する毎にEnterキーを入力するとロボットアームが動く。各コマンドを入力する度にEnterキーを押さなければ動きません。jは第1関節を正方向、fは負方向、 kは第2関節を正方向、dは負方向に目標角度を5度ずつ変化させる。
  • 成功するとrvizとgazeboの2つのウインドウが開く。そのままではrvizにロボットモデルが表示されないので、次の設定を行う。

rvizの設定

rviz-gazebo

  • 次の操作を行う
    1. (1) Global Option -> Fixed Frameをbase_linkに設定
    2. (2) Addボタンをクリックする
    3. (3) RobotModelを追加する

ノードグラフ

ノードグラフは次のとおり。端末を開き、次のコマンドを実行。

  • $ rqt_graph

rqt_graph

参考リンク

 


ROS演習9:ロボットアームと位置センサ

$
0
0

arm_sensor
今回は先回作った2自由度のロボットアームの先端に位置センサを取り付け、先端位置を取得するプログラムを作ります。

位置センサ用プラグインの追加
gazeboのロボットモデルに位置センサを取り付けるために、~/catkin_ws/src/armbot2_sensor/urdf/armbot2_sensor.gazeboに以下のプラグインを追加します。

 
 <gazebo>
    <plugin name="p3d_base_controller" filename="libgazebo_ros_p3d.so">
      <alwaysOn>true</alwaysOn>
      <updateRate>100.0</updateRate>
      <bodyName>link_sensor</bodyName>
      <topicName>/armbot2_sensor/pose_ground_truth</topicName>
      <gaussianNoise>0</gaussianNoise>
      <frameName>base_link</frameName>
      <xyzOffsets>0 0 0</xyzOffsets> 
      <rpyOffsets>0 0 0</rpyOffsets>
    </plugin>
  </gazebo>

ソース
前週のソースコードにgroundTruthCallback関数を追加し、トピック/armbot2_sensor/pose_ground_truthTurtlebtをサブスクライブするだけで、位置センサからのデータを取得できます。

 
#include "ros/ros.h"  // rosで必要はヘッダーファイル
#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

using namespace std;

std_msgs::Float64 tmp_joint1, tmp_joint2;
double pos_x, pos_y, pos_z;


void groundTruthCallback(const nav_msgs::Odometry::ConstPtr& msg)
{ 
  //msg->pose.pose.position, msg->pose.pose.orientation, 
  pos_x = msg->pose.pose.position.x;
  pos_y = msg->pose.pose.position.y;
  pos_z = msg->pose.pose.position.z;
  ROS_INFO("Pose: x=%f y=%f \n",pos_x,pos_y);
}

void monitorJointState(const sensor_msgs::JointState::ConstPtr& jointstate)
{
  tmp_joint1.data = jointstate->position[0];
  tmp_joint2.data = jointstate->position[1]; 
}


int main(int argc, char **argv)
{
  ros::init(argc, argv, "teleop_sensor"); 
  // initでROSを初期化して、my_teleopという名前をノードにつける                        
  // 同じ名前のノードが複数あってはいけないので、ユニークな名前をつける

  ros::NodeHandle nh;
  // ノードハンドラの作成。ハンドラは必要になったら起動される。
  ros::Publisher  pub_joint1, pub_joint2;
  // パブリッシャの作成。トピックに対してデータを送信。

  ros::Subscriber sub_joints, sub_sensor;
  // サブスクライバの作成

  ros::Rate rate(10);
  // ループの頻度を設定。この場合は10Hz、1秒間に10回数、1ループ100ms。

  std_msgs::Float64 target_joint1, target_joint2;

  pub_joint1 = nh.advertise<std_msgs::Float64>("/armbot2_sensor/joint1_position_controller/command", 100);
  pub_joint2 = nh.advertise<std_msgs::Float64>("/armbot2_sensor/joint2_position_controller/command", 100);
  sub_sensor = nh.subscribe<nav_msgs::Odometry>("/armbot2_sensor/pose_ground_truth", 100, groundTruthCallback);
  sub_joints = nh.subscribe("/armbot2_sensor/joint_states", 100, monitorJointState);

  target_joint1.data = 0;
  target_joint2.data = 0;

  int loop = 0;
  while (ros::ok()) { // このノードが使える間は無限ループ
    char key;  // 入力キーの値

    ROS_INFO("[Input] j: Joint1++, f: Joint1--, k: Joint2++, d:Joint2--");
    cin >> key; 
    cout << key << endl;

    switch (key) {
    case 'j': target_joint1.data  +=  5 * M_PI/180.0; break;
    case 'f': target_joint1.data  -=  5 * M_PI/180.0; break;
    case 'k': target_joint2.data  +=  5 * M_PI/180.0; break;
    case 'd': target_joint2.data  -=  5 * M_PI/180.0; break;
    default: ROS_INFO("Input j,f,k,d");
    }
      
    pub_joint1.publish(target_joint1); // 角度を送信    
    pub_joint2.publish(target_joint2);
    ROS_INFO("Targe: Joint1=%f Joint2=%f", target_joint1.data, target_joint2.data);

    usleep(1000*1000);
    ros::spinOnce(); // コールバック関数を呼ぶ
    ROS_INFO("Tmp:   Joint1=%f Joint2=%f", tmp_joint1.data,    tmp_joint2.data);
    //rate.sleep();     // 指定した周期でループするよう寝て待つ
  }
 
  return 0;
}

準 備(ROS演習8:ロボットアームで実施した場合は必要なし)

  • $ sudo apt-get update
  • $ sudo apt-get install ros-indigo-gazebo-ros-pkgs ros-indigo-gazebo-ros-control
  • $ sudo apt-get install ros-indigo-gazebo-plugins  ros-indigo-gazebo-ros
  • $ sudo apt-get install ros-indigo-moveit-*
  • $ sudo apt-get install ros-indigo-ros-control ros-indigo-ros-controllers  ros-indigo-joint-state-controller ros-indigo-effort-controllers ros-indigo-position-controllers ros-indigo-joint-trajectory-controller
  • $ sudo apt-get install liburdfdom-tools

プログラムとビルド

  • $ cd
  • $ cp  armbot2_sensor-160122.tgz  ~/catkin_ws/src
  • $ cd  ~/catkin_ws/src
  • $ tar  xvzf  armbot2_sensor-160122.tgz
    • ここで、not in gzip formatと表示され展開できない場合は次のコマンドを実行する。
      tar  xvf  armbot2_sensor-160122.tgz
  • $ cd  ~/catkin_ws
  • $ catkin_make

実 行
端末を2つ開き、次のコマンドを実行する。

  • $ roslaunch  armbot2_sensor  armbot2_sensor.launch
  • $ rosrun armbot2_sensor armbot2_sensor
    • armbot2を実行している端末をクリックし、j, k, f, dコマンドを入力する毎にEnterキーを入力するとロボットアームが動く。各コマンドを入力する度にEnterキーを押さなければ動きません。jは第1関節を正方向、fは負方向、 kは第2関節を正方向、dは負方向に目標角度を5度ずつ変化させる。

演 習
(1) 運動学
運動学の計算結果と位置センサの出力を比較し、プログラムが正しいか確認する。
(2) 逆運動学
逆運動学を実装する。2自由度の場合は解が2つあるので、数字キー1を押すと解1、数字キー2を押すと解2を選択するにしなさい。

参考リンク

 

numpyメモ:列の挿入

$
0
0

numpyのメモ.行列に要素が全て1の列ベクトルを挿入

>>>import numpy as np
>>>X = np.array([[1,2],[3,4],[5,6]])
>>>print X
​[[1 2]
[3 4]
[5 6]]

>>>a = np.column_stack((np.ones((3,1)),X))
>>>print a​
[[ 1. 1. 2.]
[ 1. 3. 4.]
[ 1. 5. 6.]]

>>>import numpy as np
>>>b = np.concatenate((np.ones((3,1)),X),axis=1)
>>>print b
[[ 1. 1. 2.]
[ 1. 3. 4.]
[ 1. 5. 6.]]

>>>import numpy as np
>>>c = np.hstack((np.ones((3,1)),X))
>>>print c
[[ 1. 1. 2.]
[ 1. 3. 4.]
[ 1. 5. 6.]]

Kinect V2 + Ubuntu14.04 メモ

$
0
0

Kinect V2をUbuntu14.04で使用する設定をしたときのメモ。
カーネル3.16以上、USB3.0必須。
libfreenect2とiai_kinect2が必要。
OpenCLのインストールで少しはまったので記録に残す。OpenCLを使うとIntelの内蔵GPUを使えるので高速処理可能。

1. libfreenect2のインストール
https://github.com/OpenKinect/libfreenect2
のLinuxの部分を実行。

  • Get source
    • git clone https://github.com/OpenKinect/libfreenect2.git
    • cd libfreenect2
    • cd depends; ./download_debs_trusty.sh
  • build tool
    • sudo apt-get install build-essential cmake pkg-config
  • libusb
    • sudo dpkg -i debs/libusb*deb
  • TURBO JPEG
    • sudo apt-get install libturbojpeg libjpeg-turbo8-dev
  • OpenGL
    • sudo dpkg -i debs/libglfw3*deb; sudo apt-get install -f
    • sudo apt-get install libgl1-mesa-dri-lts-vivid(他のパッケージとコンフリクトしたら、インストールしない)
  • OpenCL
    • sudo apt-add-repository ppa:floe/beignet; sudo apt-get update; sudo apt-get install beignet-dev; sudo dpkg -i debs/ocl-icd*deb
  • Build
    • cd ..
    • mkdir build && cd build
    • cmake .. - DCMAKE_INSTALL_PREFIX=$HOME/freenect2
    • make
    • make install
  • UDEV設定
    • sudo cp ../platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/
  • Test
    • ./bin/Protonect  gl  (opengl利用)
    • ./bin/Protonect cl   (opencl利用)
      ウインドウに次のような画像が写っていない場合はopenclのインストールが失敗。

2. iai_kinect2のインストール
https://github.com/code-iai/iai_kinect2
ROSでKinect2を使うために上記のサイトの説明インストールする。

  • Install
    • cd ~/catkin_ws/src/
    • git clone https://github.com/code-iai/iai_kinect2.git
    • cd iai_kinect2
    • rosdep install -r –from-paths .
    • cd ~/catkin_ws
    • catkin_make -DCMAKE_BUILD_TYPE=”Release”
  • kinect2を接続して、次のラウンチファイルを起
    • roslaunch kinect2_bridge kinect2_bridge.launch
  • ここを読んでキャリブレーション
  • kinect2_bridgeを次のコマンドで再起動
    • roslaunch kinect2_bridge kinect2_bridge.launch (depthの処理にopenclを利用)
    • roslaunch kinect2_bridge kinect2_bridge.launch depth_method:=opengl  (depth処理にopenglを利用)
  • クラウドビュアーで表示
    •  rosrun kinect2_viewer kinect2_viewer kinect2 sd cloud
  • イメージビュアーで表示
    • rosrun kinect2_viewer kinect2_viewer kinect2 sd image

3. はまったところ
libfreenect2のProtonectでKinect V2からのイメージ画像とデプス画像を表示できたが、iai_kinect2のkinect2_viewerでは表示できなかった。原因はopenclのインストールがうまくいっていないことだった。roslaunch kinect2_bridge kinect2_bridge.launchのコマンドではdepthの処理にopenclをデフォルトで使うが、Protonectは標準でopenglを使っていたので原因特定まで半日要した。

つまり、openclでうまく動かない時は、以下を実行すればよい。

  • roslaunch kinect2_bridge kinect2_bridge.launch depth_method:=opengl
  • Image Viewer
    • rosrun kinect2_viewer kinect2_viewer kinect2 sd image
  • Cloud Viewer
    • rosrun kinect2_viewer kinect2_viewer kinect2 sd cloud

終わり

Kaldi-gstream-serverを使うためのメモ

$
0
0
  1. kaldi-gstreamer-serverを使うために、kaldiをソースコードからビルドする。
    $ cd ~/src
    $ git clone https://github.com/kaldi-asr/kaldi.git
    $ cd ~/src/kaldi-trunk/src
    $ ./configure –shared
    上のコマンドでkaldi.mkファイルが生成されるので、その中のCXXFLAGSの$(EXTRA_CXXFLAGS)の後に-O3 -DNDEBUGをつける。
    $ make depend
    $ make
    $ make ext
    1時間ぐらい時間がかかる。
  2. kaldi-gstreamer-serverのインストール
    $ pip install ws4py==0.3.2
    $ cd ~/src
    $ git clone https://github.com/alumae/kaldi-gstreamer-server.git
  3. kaldinnet2onlinedecoderのインストール
    $ cd ~/src
    $ git clone https://github.com/alumae/gst-kaldi-nnet2-online.git
    $ sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-pulseaudio gstreamer1.0-plugins-ugly gstreamer1.0-tools libgstreamer1.0-dev
    $ sudo apt-get install libjansson-dev
    $ cd ~/src/gst-kaldi-nnet2-online/src
    Makefileの中をKALDI_ROOT=/home/demulab/src/kaldi-trunk
    と書き換える.
    $ make depend
    $ make
    $ cp -a libgstkaldionline2.so ~/src/kaldi-trunk/src/gst-plugin/.
  4. dictate.jsのインストール
    $ cd ~/src
    $ git clone https://github.com/Kaljurand/dictate.js
  5. Recorder.jsのインストール
    $ cd ~/src
    $ git clone https://github.com/mattdiamond/Recorderjs.git
  6. 実行
    別端末で以下を実行
    (1) サーバーの起動
    $ cd ~/src/kaldi-gstreamer-server
    $ python kaldigstserver/master_server.py –port=8888
    (2) ワーカーの起動
    $ cd ~/src/kaldi-gstreamer-server
    $ python kaldigstserver/worker.py -u ws://localhost:8888/worker/ws/speech -c sample_english_nnet2.yaml
    (3) クライアントの起動
    $ cd ~/src/dictate.js/demos
    $ python -m SimpleHTTPServer
    ウェブブラウザを起動し、アドレスに以下を記入
    http://localhost:8000/demos/mob.html

Kaldi gstreamer server

$
0
0

KaldiとGstreamerを使った音声認識サーバーKaldi GStreamer serverをインストールしたときのメモ。 環境はUbuntu14.04。Kaldiはインストール済みとする。

  • 準備: Python用パッケージのインストール
    • 非同期のネットワークライブラリtornadoのインストール
      • pip install tornado
    • Python用ウェブソケットプロトコルのインストール
      • pip install  ws4py == 0.3.2
    • yamlのインストール
      • pip install pyyaml
    • JSONのインストール
      • pip install simplejson
  • kaldi-gstreamer-serverのインストール
    • cd
    • mkdir  src
    • cd src
    • git clone https://github.com/alumae/kaldi-gstreamer-server.git
  • gst-kaldi-nnet2-onlineのインストール
    • kaldiが~/src/kaldi-trunkにインストールされているとする
    • cd ~/src/kaldi-trunk/tools
    • git clone https://github.com/alumae/gst-kaldi-nnet2-online.git
    • cd ~/src/kaldi-trunk/src
    • ./configure  –shared
    • make  depend
    • make
  • 英語のニューラルネットモデルTEDLIUMのダウンロード。サイズが1.5GBあるので空き容量に注意。
    • cd ~/src/kaldi-gstreamer-server/test/models
    • ./download-tedlium-nnet2.sh
    • ~/. bashrcに以下を追加
      export GST_PLUGIN_PATH=~/src/kaldi-trunk/tools/gst-kaldi-nnet2-online/src
    • source  ~/.bashrc
  •  gstreamer-1.0のインストール
    • sudo add-apt-repository ppa:gstreamer-developers/ppa
    • sudo apt-get update
    • sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-pulseaudio gstreamer1.0-plugins-ugly gstreamer1.0-tools libgstreamer1.0-dev
    • sudo apt-get install libjansson-dev
    • cd  ~/src/kaldi-trunk/tools/gst-kaldi-nnet2-online/src
    • export    KALDI_ROOT=~/src/kaldi-trunk
    • make depend
    • make
  • 実行
    • サーバーの起動
      • cd src
      • python kaldigstserver/master_server.py –port=8888
    • ワーカーの起動
      • python kaldigstserver/worker.py -u ws://localhost:8888/worker/ws/speech -c sample_english_nnet2.yaml
    • クライアントの起動
      • python kaldigstserver/client.py -r 8192 test/data/bill_gates-TED.mp3

 

ThinkPad T450 (Nvidia 940m)にXubuntu14.04.5とCuda7.5を入れたときのメモ

$
0
0

ThinkPad T450にXubuntu14.04.5, Cuda7.5インストールしたときのメモ。 T450はNvidia 940mと Intel HD 5500のGPUを搭載しており、NVIDIAのOPTIMUSテクノロジーを使っている。Windowsでは問題ないが、UbuntuをインストールするとXが立ち上がらなくなるブラックスクリーン問題で悩まされた。

UnityとNvidiaの相性が悪いので、Unityを使わないXubuntuとCuda7.5rcに2年前に変更したら問題なくXが起動するようになった。昨年、学生が間違ってOpenGLを入れたところ再度Xが立ち上がらなくなり、復旧したがNVIDIAのGPUは使えない設定のままであった。DNNを使うために、NVIDIAのドライバやXなどを入れ直したが改善せず、最終的にXubuntu14.04.5のisoをダウンロードして、クリーンインストールしてnvidiaドライバやcudaを入れ替えすったもんだしたところなんとか動くようになった。以下はメモ。

  • 環境
    • ThinkPad T450
      (CPU: Intel i7-5500U, GPU: nvidia 940m)
    • xubunut14.04.5
    • Kernel 4.4.0-66-generic
    • gcc/g++ 4.8.4
  • 準備
    • インストールするとIntelのGPUでXが起動するので、Ctlr+Alt+F1でXを落とす
    • sudo apt-get update
    • sudo apt-get upgrade
    • sudo service lightdm stop
  •  NVIDIAドライバのインストール
    • sudo add-apt-repository ppa:xorg-edgers/ppa
      sudo add-apt-repository ppa:graphics-drivers/ppa
      sudo apt-get update
      sudo apt-get install nvidia-375
  •  NVIDIAのウェブサイトからCuda7.5のインストール
    • cuda_7.5.18_linux.runをダウンロード
    • sudo ./cuda_7.5.18_linux.run
    • いろいろ聞かれるが、NVIDIAドライバはすでにインストールしているので入れない。OpenGLを入れるとXが立ち上がらなくなるといった記事があったので入れない。後はデフォルトのまま。
    • .bahrcに以下を追加したCUDAのパスを通す
      • export CUDA_HOME=/usr/local/cuda
      • export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda/lib64
  • NVIDIAのウェブからcuDNNのインストール
    • tar xvzf cudnn-7.5-linux-x64-v5.1.tgz
    • cd cuda
    • sudo cp -a lib64/lib*   /usr/local/cuda/lib64/
    • sudo cp include/cudnn.h  /usr/local/cuda/include/

終わり

リアルタイム物体検出DNNのYOLO v2で少しはまる

$
0
0

facebookで先日、話題になっていた世界最先端の実時間物体検出DNN(Deep Neural Network)のYOLO v2 (real time object detection)を試したときのメモ。Cudaの out of memoryエラーで1日ハマったので他の方の参考になればと思う。

  • 環境
    • ThinkPad T450
      • CPU: Intel i7-5500U,
      • GPU: nvidia 940m, moemory 1GB
    • xubunut14.04.5
    • Kernel 4.4.0-66-generic
    • gcc/g++ 4.8.4
  • Darknetのインストール
  • Yolo: Real Time Object Detectionのインストール
    • cd darknet
    • 学習済みの重み(パラメータ)ファイルをダウンロード
      • wget http://pjreddie.com/media/files/yolo.weights
    • サンプルの実行
      • ./darknet detect cfg/yolo.cfg yolo.weights data/dog.jpg
  • 実行方法
    • ウェブカメラ
      •  ウェブカメラをPCに接続し以下のコマンドを実行
      • ./darknet detector demo cfg/coco.data cfg/yolo.cfg yolo.weights
    • 動画ファイル
      • Webm形式の動画ファイルは問題なく動作
      • ./darknet detector demo cfg/coco.data cfg/yolo.cfg yolo.weights <video file>
  • テスト
    • ウェブカメラで撮った信号機の動画を学習済みのパラメータで試したところ信号機は問題なく認識された。車は乗用車をtruckと間違えるときはあるが、位置は問題ない。ただ、私の環境では約4フレーム/秒。リアルタイムとはいかないが、つくばチャレンジや@Homeのタスクによっては使えるレベル。最新GPUを搭載し、メモリを多く積んだマシンが欲しい。
  • はまった原因
    • darknetを実行するとCuda out of memoryのエラーで悩まされた。nvidia-smiコマンドでGPUのメモリ使用量がわかる。上の画面では981MB中961MBを使用している。chromeなどのウェブブラウズを起動すると数十MB使用するので、chromeを起動しながらコマンドを実行したのでout of memoryになったわけだ。メモリを多く積んだマシンが欲しい。

ROS演習5:地図作製・自己位置推定(SLAM, AMCL)

$
0
0

rviz2この記事は私が担当している講義ロボットプログラミングⅡ用です。今回は地図作成(SLAM)と自己位置推定(AMCL)のパッケージを使いロボットにナビゲーションをさせましょう! 本記事を以下のチュートリアルを参考にしています。

1. 地図生成

(1) 端末を3つ開き以下のコマンドを実行する。

gazeboシミュレータを起動

  • $ roslaunch turtlebot_gazebo turtlebot_world.launch

地図生成のgmappingを起動

  • $ roslaunch turtlebot_gazebo gmapping_demo.launch

ROSのビジュアライションツールrvizを起動

  • $ roslaunch turtlebot_rviz_launchers view_navigation.launch

注:rvizがOpenGL関係のエラーで落ちる場合は、以下の1行を.bashrcの最後に付け加える。

  • export LIBGL_ALWAYS_SOFTWARE=1

(2) 端末を開き、以下のコマンドでロボットを動かし、地図を作る。

  • $ roslaunch turtlebot_teleop keyboard_teleop.launch

(3)  端末を開き、以下のコマンドで地図を保存する。mymapは保存する地図名なので適宜変更する。

  • $ mkdir  ~/maps
  • $ rosrun map_server map_saver -f  ~/maps/mymap

 

2. ナビゲーション

一度開いている端末を全部閉じ、ノードを落とす。

(1)  gazeboシミュレータを起動

  • $ roslaunch turtlebot_gazebo turtlebot_world.launch

(2) 自己位置推定ノードの起動
上で作成した地図を使ってナビゲーションできるが、ここではすでに作られている地図を使う。

  • $ roslaunch turtlebot_gazebo amcl_demo.launch map_file:=/opt/ros/indigo/share/turtlebot_gazebo/maps/playground.yaml

(3) rvizを起動

  • $ roslaunch turtlebot_rviz_launchers view_navigation.launch

(4) ロボット初期位置の設定
上で起動したrviz(上図)の”2D Pose Estimation”をクリックして選択し、下図シミュレータのロボットの向きと位置が合うように、rviz上でロボットの位置と向きを設定する。ロボットの位置にマウスのカーソールを持って行き、ロボットの向きにドラッグすると設定終わり。

(5) ゴールの設定
次にrvizの”2D Nav Goal”をクリックして、初期位置を設定したのと同様に、ゴールの位置と向きを設定する。設定するとロボットが自動で動き出す。

gazebo終わり

RoboCup2017世界大会@Homeリーグへ出場します!

$
0
0

happy miniチームがRoboCup2017世界大会@Home オープンプラットフォームリーグへの出場権を獲得しました。happy miniチーム(昨年まではdemura.netチーム)は金沢工業大学夢考房RoboCup@Homeプロジェクトと合同会社D.K.T.のコラボチームであり、世界大会へは2015年(9位)、2016年(8位)に引き続き3回目となります。なお、RoboCup@Homeプロジェクトは新しい形の夢考房プロジェクトでdemura.netから技術支援を受けて生活支援ロボットを開発しています。
 また、RoboCup2017世界大会Humanoid Leagueにも夢考房ロボカッププロジェクトチームが出場します。今年は、日本開催なので地元の利を生かして、両チームとも頑張れ!

Qualified Teams in Open Platform League for Nagoya, Japan 2017. Please confirm before March 29.

At Homeさんの投稿 2017年3月26日

Jetson TX1: JetPack3.0インストール後の作業

$
0
0

Jetson TX1にJetPack3.0をインストールした後の作業メモ

  •  ユーザの作成
    • System Settings -> User Accounts でMy Accountsを作る。この例ではアカウント名をここではhappyminiとする。
    • /etc/groupのvideoにアカウント名を加える。この例では以下になる。この作業をしないとそのアカウント名でloginできない。
      • video:x:44:ubuntu,nvidia,happymini
    • 新しく作成したアカウントでログインしたら、端末を開き、次のコマンドでubuntuアカウントの.bashrcをコピーする。
      • cd
      • cp  /home/ubuntu/.bashrc  .
  •  unityは重いのでxfceを利用する
    • sudo apt-get install xubuntu-desktop
    • sudo apt-get install xfce4 xfce4-goodies gnome-icon-theme-full
  • ウェブブラウザのインストール
    • sudo apt-get install chromium-browser
  • ROSのインストール
    • cd src
    • git clone https://github.com/jetsonhacks/installROSTX1.git
    • cd installROSTX1
    • ./installROSTX1
    • ./setupCatkinWorkspace.sh
  •  TX1キャリアボードがパッシブシートシンクなので温度測定とGUI表示ツールをインストール
    • sudo apt-get install lm-sensors
    • sudo apt-get install psensor
  • 各種アプリケーションをインストール
    • sudo apt-get install  emacs

Jetson TX1 :JetPack3.0のインストール

$
0
0

Jetson TX1へJetPack3.0をインストールしたときのメモ。

ホストPC環境

  • ThinkPad T450
  • CPU: Intel i7-5500U
  • GPU: nvidia 940m, moemory 1GB
  • xubunut14.04.5
  • Kernel 4.4.0-66-generic
  • gcc/g++ 4.8.4

NVIDIA EMBEDDED COMPUTINGのウェブサイトへ行き、下の[DOWNLOAD]をクリックする。

上から2つのTitle [JetPack]をクリック

DOWNLOADSの下のUbuntu [64.bit]をクリックする。

Embedded Developer Programのメンバーにならないとダウンロードできないので、未加入の場合は[Join now]に必要事項を入力してなる。既にメンバーの場合は、右の[Log in]からログインする。ログインするとダウンロードが可能になるのでダウンロードする。JetPack-L4T-3.0-linux-x64.run

ターミナル(端末)を開き、ダウンロード先へ移動し以下のコマンドを実行すると次のJetPack L4Tのウインドウが開く。

  • chmod +x JetPack-L4T-3.0-linux-x64.run
  • ./JetPack-L4T-3.0-linux-x64.run

実行すると下のWarningが出るが問題ないので、okayをクリック。

下のイントーラーウインドウがでるのでNextをクリック。

Nextをクリック。

Jetson TX1 Developer Kit (64bit) and Ubuntu Hostを選び、Nextをクリック。

管理者のパスワードを入力し、「認証する」クリック。

Fullを選択し、下の[Automatically resolve dependency conficts]にチェックを入れ、Nextをクリック。

注:ろ

ライセンスの同意を聞かれるので、Accept Allにチェックを入れて、Acceptをクリック。

 

Important Noteウインドウが開く。端末にメッセージが表示されるかもしれないので、注意を払っておく。OKをクリック。

インストールが始まり、インストールが終わるとCompletedと表示されるので、Nextをクリックする。

Jetsonとホストコンピュータの接続を聞かれるので、あっている方を選択し、Nextをクリック。

ネットワークのインタフェースを選択し、Nextをクリック。

インストール後の処理に移る。Nextをクリック。

Post Installationウインドウが開き、下の画面で処理が一度停止する。
1.  Jetsonの電源を切る。ACアダプタから給電している場合は、ACアダプタを抜く。
2. PCとJetsonをUSBケーブルで接続する。その際、Jetson側はUSB Micro-Bコネクタに接続する。
3. Jetsonの電源を入れる。
4. POWERボタンを押して放す。RECOVERYボタンを押しっぱなしにしながら、RESETボタンを押して放す。その2秒後にRECOVERYボタンを放す。
5. Jetsonがリカバリモードになったら、ターミナルでlsusbコマンドを実行し、NVIDIA Corpと表示されていれば成功。失敗した場合は再度、1から5までの作業をやり直す。
成功した場合は、Post Installationウインドウを選択して、エンターキーを押す。

mntウインドウが開く。

bootloaderウインドウが開く。

Finished Flashing OS. Determing the IP address of Target ..と表示され処理が停止されたままの場合は、インストールを止めてJetsonをrebootする。ホストPCは./JetPack-L4T-3.0-linux-x64.runを再度実行する。先ほどと違い、Component Managerで下図のようにFullではなくCustomを選択し、Flash OS Image to Targetをno actionに変更する。そうするとFlash OSの作業はスキップする。

作業が成功すると以下のウインドウが開くので、JetsonのIPアドレス、ユーザ名、パスワードを入力する。IPアドレスはターミナルを開き、ifconfigコマンドで調べる。ユーザ名、パスワードはJetson側で登録したものを使う。Jetsonで新しくアドミニストレータアカウントを作るとログインできない場合がある。その場合は、/etc/groupのvideoにそのユーザアカウント名を追加するとログインできるようになる。Nextをクリック。

なお、ユーザ名ubuntuは事前に登録されているので、User NameとPasswordにubuntuを入れても良い。

Nextをクリック。

以下の画面になったら、Jetsonへのインストールが終わりなのでエンターキーを押す。

インストール作業がすべて終了すると次の画面になりFinishを押し、作業を終了する。

インストールがうまくいったかCUDAのサンプルプログラムを動かしてみる。ターミナルを開き、以下のコマンドを実行する。図のようなウインドウが開いたら成功。

  • cd  NVIDIA_CUDA-8.0_Samples/5_Simulations/smokeParticles
  • ./smokeParticles

 

 

お疲れ様!

JETSON TX2: JETPACK3.0インストール後の作業

$
0
0

Jetson TX2にJetPack3.0をインストールした後の作業メモ

  • ユーザの作成
    • System Settings -> User Accounts でMy Accountsを作る。この例ではアカウント名をここではhappyminiとする。
    • /etc/groupのvideoにアカウント名を加える。この例では以下になる。この作業をしないとそのアカウント名でloginできない。
      • video:x:44:ubuntu,nvidia,happymini
    • 新しく作成したアカウントでログインしたら、端末を開き、次のコマンドでubuntuアカウントの.bashrcをコピーする。
      • cd
      • cp /home/ubuntu/.bashrc .
  • unityは重いのでxfceを利用する
    • sudo apt-get install xubuntu-desktop
    • sudo apt-get install xfce4 xfce4-goodies gnome-icon-theme-full
  • ウェブブラウザのインストール
    • sudo apt-get install chromium-browser
  • ROSのインストール
    • cd src
    • git clone https://github.com/jetsonhacks/installROSTX2.git
    • cd installROSTX2
    • ./installROSTX2
    • ./setupCatkinWorkspace.sh
  • 温度測定とGUI表示ツールをインストール
    • sudo apt-get install lm-sensors
    • sudo apt-get install psensor
  • 開発環境のインストール
    • sudo apt-get install python3-setuptools
    • sudo easy_install3 pip
    • sudo apt-get install python-dev
    • sudo apt-get install python3-dev
  • 各種アプリケーションをインストール
    • sudo apt-get install emacs
    • sudo apt-get install htop
  • tensorflow1.0.1のインストール(わっぜか株式会社の情報
Viewing all 757 articles
Browse latest View live