ROS MelodicでOpenCV

uvc_cameraパッケージをインストール

$ sudo apt install ros-melodic-uvc-camera

opencv_tutorialsパッケージの作成

$ catkin_create pkg opencv_tutorials sensor_msgs cv_bridge roscpp rospy std_msgs image_transport

パッケージの中身をいじる

  • /src/image_converter.cpp 以下のコードを書く。
#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_)
  {
    // Subscrive to input video feed and publish output video feed
    image_sub_ = it_.subscribe("/image_raw", 1,
      &ImageConverter::imageCb, this);
    image_pub_ = it_.advertise("/image_converter/output_video", 1);

    cv::namedWindow(OPENCV_WINDOW);
  }

  ~ImageConverter()
  {
    cv::destroyWindow(OPENCV_WINDOW);
  }

  void imageCb(const sensor_msgs::ImageConstPtr& msg)
  {
    cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

    // Draw an example circle on the video stream
    if (cv_ptr->image.rows > 60 && cv_ptr->image.cols > 60)
      cv::circle(cv_ptr->image, cv::Point(50, 50), 10, CV_RGB(255,0,0));

    // Update GUI Window
    cv::imshow(OPENCV_WINDOW, cv_ptr->image);
    cv::waitKey(3);

    // Output modified video stream
    image_pub_.publish(cv_ptr->toImageMsg());
  }
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_converter");
  ImageConverter ic;
  ros::spin();
  return 0;
}
  • CmakeLists.txtの修正 最後に以下を加える。
find_package(OpenCV REQUIRED)
include_directories(${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
add_executable(image_converter src/image_converter.cpp)
target_link_libraries(image_converter ${OpenCV_LIBRARIES} ${catkin_LIBRARIES})

ビルドする

$ catkin build opencv_tutorials
$ catkin source

実行してみる

$ roscore
$ rosrun uvc_camera uvc_camera_node
$ rosrun opencv_tutorials image_converter

ArduinoとROSを繋ぐ

Arduino IDEのダウンロード

$ tar Jxfv arduino-1.8.9-linux64.tar.xz
$ cd arduino-1.8.9
$ ./install.sh
  • シリアルポートのアクセス許可
$ ls -l /dev/ttyACM0
$ sudo usermod -a -G dialout `whoami`

rosserialのAruduino用ライブラリをインストール

$ sudo apt install ros-melodic-rosserial ros-melodic-rosserial-arduino
$ rosrun rosserial_arduino make_libraries.py ~/arduino-1.8.9/libraries/

サンプルプログラムの実行

新規ファイルから以下のコードをコピペして,ボードに書き込む.

#include <ros.h>
#include <std_msgs/Int32.h>

//PWM
const int PWM1 = 10;
const int PWM2 = 11;

//ノードハンドルの宣言
ros::NodeHandle nh;

void messageCb(const std_msgs::Int32& toggle_msg){
    analogWrite(PWM1, toggle_msg.data);  
}

// トピック名をtoggle_ledとしてSubscriberをインスタンス化し、messageCbを呼び出す
ros::Subscriber<std_msgs::Int32> sub("toggle_led", &messageCb );

void setup()
{ 
  nh.initNode();
  nh.subscribe(sub);

  pinMode(PWM1, OUTPUT);
  pinMode(PWM2, OUTPUT);
}

void loop()
{  
  nh.spinOnce();
  delay(1);
}

ターミナルで以下のコマンドを実行すると数字(ここでは255)に応じたPWMが生成される.

$ roscore
$ rosrun rosserial_pyhton serial_node.py /dev/ttyACM0
$ rostopic pub toggle_led std_msgs/Int32 255 --once

URDFファイルの書き方

注意点

URDFファイルはXMLで記述するため、コメントは<!-- コメント -->で挿入できるが、日本語でコメントを書くとエラーが発生するので、十分に注意しましょう。

各タグの属性

<link>タグの属性 (リンクの名前や以下の情報の設定)

  • <collision> : リンクの衝突計算のための情報の設定
  • <visual> : リンクの可視化のための情報の設定
  • <inertial> : リンクの慣性のための情報の設定
  • <mass> : リンクの重量の設定
  • <inertia> : 慣性テンソルの設定
  • <origin> : リンク座標系の設定
  • <geometry> : モデルの形状を設定。STLDAE形式の設計ファイルも読み込むことができる。
  • <material> : リンクの色とテクスチャの設定

<joint>タグの属性 (関節の名前、種類と以下の情報の設定)

  • <parent> : 関節の親リンクの名前の設定
  • <child> : 関節の子リンクの名前の設定
  • <origin> : 親リンクの座標系から子リンクの座標系への相対座標変換
  • <axis> : 回転軸の設定
  • <limit> : 関節の速度、力、制御値を設定

<transmission>タグの属性 (関節とアクチュエータとの間に作用する変数の設定)

  • <type> : 力の伝達方式の設定
  • <joint> : 関節情報の設定
  • <hardwareInterface> : ハードウェアインターフェースの設定
  • <actuator> : アクチュエータ情報の設定
  • <machanicalReduction> : アクチュエータと関節との間のギア比の設定

サンプルコード

<!-- リンク<link>については、名前とサイズ、重量、慣性モーメントなどが記載 -->
<!-- 関節<joint>については、名前、種類、各関節に繋がっているリンクなどが記載 -->
<!-- <transmission>タグは関節とアクチュエータの関係を定義する -->

<?xml version="1.0" ?>

<!-- robotタグによってすべての定義がはじまる -->
<robot name="testbot">

<!-- materialタグは、リンクの色や質感などを定義する -->
<!-- rgbaの4つめの数字は透明度に対応し、1.0に近いほど不透明 -->
  <material name="black">
    <color rgba="0.0 0.0 0.0 1.0"/>
  </material>
  <material name="orange">
    <color rgba="1.0 0.4 0.0 1.0"/>
  </material>

<!-- ベース -->
  <link name="base"/>

<!-- 関節 -->
  <joint name="fixed" type="fixed">
    <parent link="base"/>
    <child link="link1"/>
  </joint>

<!-- <link>タグは、衝突<collision>、可視化<visual>、慣性<inertial>タグで構成される -->
<!-- <collision> : リンクの干渉範囲を示す幾何学的な情報を記述 -->
<!--                <origin> : 干渉範囲の中心座標を記入 -->
<!--                <geometry> : originを中心に干渉範囲の形状や大きさを記入 -->
<!-- <visual> : 実際の形状を記述(STL,DAEなどのCADファイルを指定することもできる) -->
<!--             <origin> : 同上 -->
<!--             <geometry> : 同上 -->
<!-- <inertial> : リンクの重量と慣性モーメントを記入 -->

<!-- 最初のリンク -->
  <link name="link1">
    <collision>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
    </collision>
    <visual>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
      <material name="black"/>
    </visual>
    <inertial>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <mass value="1"/>
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

<!-- <joint>タグは、名前、種類(revolute, prismatic, continuous, fixed, floating, planar) -->
<!-- ベースに近いリンクをparent link,遠い方をchild linkとする -->
<!-- <origin>タグは、parentからchildへの相対座標変換を指定する -->
<!-- <axis>タグは、軸の情報を指定する(revolute型であれば、回転軸の方向) -->
<!-- <limit>タグは、関節動作の制限値を設定 -->
<!--        <effort> : 関節に与えられる力 -->
<!--        <lower, upper> : 最小・最大角度 -->
<!--        <velocity> : 最大速度 -->

<!-- 最初のジョイント -->
  <joint name="joint1" type="revolute">
    <parent link="link1"/>
    <child link="link2"/>
    <origin xyz="0 0 0.5" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit effort="30" lower="-2.617" upper="2.617" velocity="1.571"/>
  </joint>

  <link name="link2">
    <collision>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
    </collision>
    <visual>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
      <material name="orange"/>
    </visual>
    <inertial>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <mass value="1"/>
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

  <joint name="joint2" type="revolute">
    <parent link="link2"/>
    <child link="link3"/>
    <origin xyz="0 0 0.5" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <limit effort="30" lower="-2.617" upper="2.617" velocity="1.571"/>
  </joint>

  <link name="link3">
    <collision>
      <origin xyz="0 0 0.5" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 1"/>
      </geometry>
    </collision>
    <visual>
      <origin xyz="0 0 0.5" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 1"/>
      </geometry>
      <material name="black"/>
    </visual>
    <inertial>
      <origin xyz="0 0 0.5" rpy="0 0 0"/>
      <mass value="1"/>
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

  <joint name="joint3" type="revolute">
    <parent link="link3"/>
    <child link="link4"/>
    <origin xyz="0 0 1.0" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <limit effort="30" lower="-2.617" upper="2.617" velocity="1.571"/>
  </joint>

  <link name="link4">
    <collision>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
    </collision>
    <visual>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.5"/>
      </geometry>
      <material name="orange"/>
    </visual>
    <inertial>
      <origin xyz="0 0 0.25" rpy="0 0 0"/>
      <mass value="1"/>
      <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
    </inertial>
  </link>

</robot>

roslaunchの使用法

roslaunchコマンドとは

roslaunchコマンドは事前に指定しておいた複数のノードを一度に実行することができる。また、実行時にroscoreが起動されていなければ、勝手に起動してくれる。 roslaunchファイルをXMLによって記述し、roslaunch [パッケージ名] [roslaunchファイル名]で実行できる。

launchファイルのタグ

launchファイルでは以下のタグを使用できる。(入れ子は実行オプション)

  • <launch> : roslaunchによって実行される部分
  • <node> : ノードの起動や実行オプションを記述する。
    • pkg : パッケージ名
    • type : 実行するノードのノード名
    • name : 実際にROS上に登録されるノードの名称。同じノードを複数実行するときなどに利用。
  • <machine> : ノードを実行するPCのネーム。address, ros-root, ros-package-pathなどが設定できる。
  • <include> : 別のlaunchファイルを呼び出し、実行する。
  • <remap> : ノード名、トピック名など、ノードで使用している変数名を変更する。
  • <env> : PATH, IPなどの環境変数を設定する。
  • <param> : パラメータ名、タイプ、値などを設定する。
  • <rosparam> : rosparamコマンドのように、load, dump, deleteなど、パラメータ情報を確認・修正する。
  • <group> : 実行するノードをグループ化するときに使用する。
    • ns : ネームスペース
  • <test> : ノードのテストに使用する。<node>に似ているが、テストに用いるオプションが含まれる。
  • <arg> : launchファイル内での変数の定義に使用する。

Ubuntu18.04LTSにROS Melodicをインストールする方法(環境構築・環境設定)

ROSのインストール方法

--- NEP設定 ---
$ sudo apt install -y chrony ntpdate
$ sudo ntpdate -q ntp.ubuntu.com
--- Ubuntuでプログラミング言語を使用するためのライブラリをインストール ---
$ sudo apt update -y
$ sudo apt install -y build-essential
$ sudo apt install -y python-dev
$ sudo apt install -y python-pip
--- ソースリストの設定とキー設定 ---
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
$ sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
$ sudo apt update && sudo apt upgrade -y
--- ROS Melodicのインストール ---
$ sudo apt install ros-melodic-desktop-full
$ sudo apt install ros-melodic-rqt*
--- rosdepの初期化 ---
$ sudo rosdep init
$ rosdep update
--- その他諸々インストール ---
$ sudo apt install -y python-rosinstall
$ sudo apt install -y python-catkin-tools
$ sudo apt install -y ros-melodic-moveit
$ sudo apt install -y ros-melodic-moveit-visual-tools
$ sudo apt install -y ros-melodic-gazebo-ros-control
$ sudo apt install -y ros-melodic-ros-controllers

ROSの環境設定

ROSのインストールが終わったら,環境設定を行いましょう.

$ gedit ~/.bashrcで.bashrcを開き,一番下に以下を追加します.

# Set Default Editor
export EDITOR='gedit'

# Set ROS Melodic 
source /opt/ros/melodic/setup.bash
source ~/catkin_ws/devel/setup.bash
source `catkin locate --shell-verbs`

# Set ROS Network
export ROS_HOSTNAME=192.168.xxx.xxx      <- ifconfigのeno1のinetに書いてあるipアドレスを記入
export ROS_MASTER_URI=http://${ROS_HOSTNAME}:11311

追記が終わったらターミナルを一旦閉じて,開き直します.
以上が完了したら作業フォルダを生成し,初期化します.

$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws
$ catkin init
$ catkin build
$ catkin source

今後src内のプログラムが変更されるたびにcatkin build, catkin sourceを実行しましょう.

ROSの動作テスト

ターミナルを開いて,以下を実行.

$ roscore

2つ目のターミナルを開いて,以下を実行.

$ rosrun turtlesim turtlesim_node

3つ目のターミナルを開いて,以下を実行.

$ rosrun turtlesim turtle_teleop_key

矢印キーを押すとカメが動く!

ROSのアンインストール方法

$ sudo apt purge ros-melodic-*

Windows10(UEFIブート)が入ったPCにデュアルブートでUbuntu18.04 LTSを入れようとしたらひどい目にあった話

出回っているブログ等を参考にwindows10とUbuntu18.04をデュアルブートにしようと試みたところ,丸1日費やしてしまいました.

起こったこと

UbuntuをインストールしたもののUbuntuが無視されてWindowsのみが起動するようになってしまった.

原因

ブートに関する知識の欠如

BIOS(Basic Input/Output System:バイオス)のブートモードにはUEFIモード(GPTパーティション形式)とレガシBIOS(MBRファイル形式)があり,ライブUSBを作成する時に注意が必要だった.

インストール方法

  • パーテーション分割
    windowsスタートボタン右クリック -> ディスクの管理から空のパーテーションを作成. 僕は50GB確保した.

  • ライブUSBを作成する

    • Rufusをダウンロードする.
    • Ubuntuのホームページからisoファイルをダウンロードする.
    • パーテーション構成は絶対に必ずGPTを選択する. f:id:ya10345:20190420151031p:plain
  • BOOT MANAGERを開き,UEFIブートでUSBから起動
    PCを再起動し,メーカーロゴが出ている間にF12を連打してBOOT MANAGERを開き,USBを選択する.

  • インストール
    指示に従ってUbuntuのインストールを進め,このPCにはwindowsがインストールされていますと表示されたら成功です.windowsとは別にインストールしましょう.
    もしも,このPCにはOSがインストールされていませんと表示されたらライブUSBの作成をもう一度確認してください.

インストールが無事に終了したら

$ LANG=C xdg-user-dirs-gtk-update
$ sudo apt install curl
$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
$ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
$ sudo apt install apt-transport-https
$ sudo apt update
$ sudo apt install code
  • Google Chromeをインストール
    以下の4つのコマンドを実行するとあっという間にGoogle Chromeがインストールされます.
$ sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
$ sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
$ sudo apt update
$ sudo apt install google-chrome-stable
reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f

Ubuntuのアンインストール方法

デュアルブートから Ubuntu を削除する方法 | Windows10 と Ubuntu のデュアルブートからUbuntu を削除し UEFI ブートを修正する方法を参照下さい.

Hello World !!

おはようございます.
東京にある某大学の機械系に所属している大学生です.

自分の学習する内容の幅が広くなり,知識が頭に入りきらなくなってきたので,いつでも振り返ることができるように本ブログを開設致しました. ご自由にお使い下さい.

本ブログでは以下のような内容について書いていきたいと思います.