えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

Ubuntu21.04を試してみた。インストール方法とUIの変更点まとめ

2021年4月22日にUbuntu21.04がリリースされますが、Ubuntu 21.04の事前リリース(4月7日)があったので、試してみました。このバージョンは正式ローンチ直前ということもあり、ほとんど変わらないものと思われます。

itigic.com

イメージのダウンロード

 Ubuntuのサイトにアップされています。ほしいイメージファイルをダウンロードします。

cdimage.ubuntu.com

 取得したイメージファイルをUSBメモリに焼きます。以前は「rufus」をよく使用していましたが、最近は「Raspberry Pi Imager」を使用しています。

Raspberry Pi OS – Raspberry Pi

 PCを起動し、Del連打でBIOS起動し、USBを優先的にブートするように設定します。

 USBブートに成功すれば、次のような画面が出ます。ここではUbuntuを選択します。

f:id:Ray_ar:20210409171546j:plain
起動方法選択

 Ubuntuを試すかインストールするかを聞かれます。「Install Ubuntu」の方を選択しました。言語は英語推奨です。

 f:id:Ray_ar:20210409171710j:plain

 キーボードの言語を選択します。

 f:id:Ray_ar:20210409171925j:plain

 接続するネットワークを選択します。設定しなくても問題ないです。

 f:id:Ray_ar:20210409172559j:plain

 インストールの種類を選択します。基本は「Minimal Installation」でいいです。

 f:id:Ray_ar:20210409172746j:plain

 OSのインストールパーティションの種類を選択します。ここは、用途と状態に合わせて選択してください。今回はクリーンインストール(Dualbootなし)するので、「Erase disk and install Ubuntu」を選択しました。

 f:id:Ray_ar:20210409173013j:plain

 確認画面です。間違えていないかどうかをチェックしてください。

 f:id:Ray_ar:20210409173032j:plain

 地域の設定をします。

 f:id:Ray_ar:20210409173105j:plain

 ユーザネームとパスワードの設定をします。パスワードは推測されにくいものを使用しましょう。

 f:id:Ray_ar:20210409173147j:plain

 インストールが完了しました。毛のたくさん生えたカバの壁紙が強烈です。(前のゴリラもなかなかでしたが)

 f:id:Ray_ar:20210409173342p:plain

Ubuntu20.04からの変更点

 基本的にはUbuntu20の延長線上のアプデなので、あまり変わりませんが、気づいたところを列挙します。

1. Python3.9がデフォルトのPythonになる。

 デフォルトのバージョンがPython3.9になりました。Anaconda等を使うことがほとんどだと思うのであまり関係ないと思いますが…

2. ブックマークバーから「Desktop」が消える

 デスクトップがデフォルトのブックマークから消えました。ブックマークに登録することで、追加はできます。

f:id:Ray_ar:20210409174102p:plain
ブックマークバーの違い。左が20.04、右が21.04

 

3. パワーセーブが追加された。

 Ubuntu21.04では、対応していれば低消費電力モードを設定から選択できるようになったようです。

f:id:Ray_ar:20210409174237j:plain

4. デスクトップフォルダでのファイル作成・削除が自然になった。

 Ubuntu20.04では、デスクトップフォルダにファイルを作成・削除すると、一瞬だけファイルが非表示になるのですが、Ubuntu21.04では解消されたようです。


 正式ローンチ直前のUbuntu21.04を試しにインストールしてみました。GUIがかなりきれいなので、Ubuntu21.04と20.04を併用しながら使ってみたいです。ただ、基本はUbuntu20.04をベースに開発や研究を行って行く予定です。

ROS1-Noeticでuvc_camera_nodeを動かす(備忘録)

 ROS1-Melodicではros-melodic-uvc-cameraパッケージでインストールできるのに、ROS-Noeticではインストールできない。usb_cam - ROS Wikiにドライバはあるものの、実行できない…

 ROSのコミュニティでは、ROS2への移行が進んでいますが、大学の研究室やロボコンサークル等ではまだまだROS1が現役で使われると思うので、備忘録として残して置きます。

※ros-noetic-desktop-fullのインストールが終わっているものとします。

 ウェブカメラの依存パッケージのインストール

$ sudo apt install libv4l-dev

 GitHubからusb_cameraをダウンロードしてコンパイル

$ mkdir -p ~/ros1_ws/src
$ cd ~/ros1_ws/src
$ catkin_init_workspace
$ git clone https://github.com/ros-drivers/usb_cam.git

コンパイル

$ cd ~/ros1_ws/
$ catkin_make

実行(ウェブカメラを接続しておくこと)

ターミナル1

$ source /opt/ros/noetic/setup.bash
$ roscore

ターミナル2

$ source /opt/ros/noetic/setup.bash
$ source ~/ros1_ws/devel/setup.bash
### $ rosrun uvc_camera uvc_camera_node
$ rosrun usb_cam usb_cam_node

補足

 これでよくね??

$ sudo apt install ros-noetic-usb-cam

自己位置推定してずっと同じ方向を向くやつを作った(rclpy+tf2+T265)

 https://ar-ray.hatenablog.com/entry/2021/04/03/180000の続きです。

tf2とは

 ※曖昧な部分が多いので、ROSWikiを見るのが確実だと思います。

 tf2とは、簡単に言うとシミュレーションにも対応するロボットの座標変換ライブラリです。ROSの中でも重要なライブラリであると同時に初見殺しがひどいライブラリです(個人的な感想)。tf2C++Pythonで扱うことができます。

 また、tfはトピック通信と異なり、同じ時系列のデータをリンクさせてデータを取得する必要があるため、ブロードキャスタとリスナが用いられます。tfが持つ情報はタイムスタンプ、リンクの親子関係、相対座標があります。座標については、平行移動にVector3、回転移動にQuaternionを用います。

実現したいこと

 前回使用したロボットについて、T265のオドメトリをもとにメカナムホイールの中心を求めて自己位置推定をします。

 さて、自己位置推定したい場合、どの位置関係を利用するのがよさそうでしょうか??

f:id:Ray_ar:20210326132449p:plain

 Rviz2では、odom_frameから見たときにロボットの移動が確認できたので、Rviz2で確認した視点と同じ場所から確認すればbase_link(=ロボット)の移動を確認できそうです。つまり、odom_frame→base_linkの相対位置を求めればよいということになります。

f:id:Ray_ar:20210326140206p:plain

 この位置関係を取得して位置を求めればよさそうです。次にアルゴリズムのブロック図を示します。

f:id:Ray_ar:20210327094438p:plain

 これをPythonで記述していきます。現段階では理解が十分でないので、適宜修正してく予定です。

github.com

 抜粋して説明します。


#tf2twsistクラス内
def __init__(self):

    _node = Node("tf2twist")

    qos_profile = QoSProfile(depth=10)
      
    tfBuffer = Buffer()
    listener = TransformListener(tfBuffer,_node, qos=qos_profile)

    twist_data = geometry_msgs.msg.Twist()

    pub_cmd_vel = _node.create_publisher(geometry_msgs.msg.Twist, "cmd_vel", qos_profile)

 whileループ前はモジュールの宣言を行います。ここでは、tfの時間を格納するBufferとリスナ、cmd_velの出力になるTwistの宣言を行いました。


#tf2twsistクラス内
while rclpy.ok():
    rclpy.spin_once(_node)

        now = _node.get_clock().now() - rclpy.duration.Duration(seconds=0,nanoseconds=1000000)
        try:
                trans = tfBuffer.lookup_transform('odom_frame', 'base_link', now, rclpy.duration.Duration(seconds=0, nanoseconds= 0))
            
                roll, pitch, yaw = self.quaternion_to_euler(trans.transform.rotation.x, trans.transform.rotation.y, trans.transform.rotation.z, trans.transform.rotation.w)

                if(yaw> 0.3):
                        twist_data.angular.z = 70.0#yaw*125*1.3
                elif(yaw< -0.3):
                        twist_data.angular.z = -70.0#yaw*125*1.3
                else:
                        twist_data.angular.z = 0.0
                pub_cmd_vel.publish(twist_data)

 while内では取得した相対座標をもとにロボットの回転を算出します。tfBuffer.lookup.transformで座標を取得します。この時、時間nowは現在の時刻よりも前にする必要があります。(この時はエラーの原因が分からず、やけくそで1000000にしてしまっています。)取得したら、後述する関数でクオータニオンオイラー角に変換してそのうちangular.zをTwistに格納してパブリッシュします。


def quaternion_to_euler(self, q0, q1, q2, q3):
    q0q0 = q0 * q0
    q0q1 = q0 * q1
    q0q2 = q0 * q2
    q0q3 = q0 * q3
    q1q1 = q1 * q1
    q1q2 = q1 * q2
    q1q3 = q1 * q3
    q2q2 = q2 * q2
    q2q3 = q2 * q3
    q3q3 = q3 * q3

    a = math.atan2(2.0 * (q1q2 + q0q3), q0q0 + q1q1 - q2q2 - q3q3)
    b = math.asin(2.0 * (q0q2 - q1q3))
    c = math.atan2(2.0 * (q2q3 + q0q1), q0q0 - q1q1 - q2q2 + q3q3)

    return a , b, c

 クオータニオンオイラー角に変換する関数です。オイラー角とクォータニオン間の変換とベクトルの回転を参考にコードを記述しました。本来はc,b,aの順でroll,pitch,yawだったと思いますが、実在のロボットの位相にそろえるために、a=roll,b=pitch,c=yawで返す関数になっています。


 tf2+rclpyの記事はとても少ないと感じているので、進捗があればちまちまと書いていきます。

ROS2でURDFを記述してRviz2でロボットを表示してみた

 これまで私はROSをロボットあまり関係ない分野で使ってきましたが、やはりROSユーザを名乗るからにはロボットらしいプログラム(?)をしたいところです。そこで、Rvizで表示したりtfを扱うためにロボットをURDFで記述しました。ROS1で図形をURDFで記述したことはありましたが、ロボットの部品位置を確認しながらURDFを作成するのは初めてだったので結構苦戦しました。また、現時点でのURDFはシミュレーション用には作っていないので、タイヤの軸などは作っていません。

 urdfやlaunchはGitHubにアップしています。このリポジトリは継続的にアップデートしていく予定です。

github.com

メカナムロボットにおけるURDF記述

 URDFは、ロボットの位置関係を定義するファイルです。URDFは複雑になりがちなロボットの関節などの記述を簡潔にすることができ、tf2と連携することで座標変換の手間を省くことができます。現在のロボットはRealsense T265を使用してオドメトリを取得しています。しかし、T265がロボットの中心かと言われるとそうではありません。当然、ロボットの中心は4つのメカナムホイールの中心です。今のところはそれほど複雑なロボットではないので直接座標を計算するプログラムを書いてもいいかもしれません。しかし、ほかのロボットにT265を取り付ける場合や他の可動関節を取り付ける場合などのアップグレードがある場合はいちいちメンテナンスするのが面倒になります。

 今回は、ROS2でのURDF記述や今後のtf2練習のためにURDFを記述してRviz2に表示したいと思います。

ロボットのリンク関係

 ロボットにリンクを示すマーカーをつけて分かりやすくしてみました。tfはループが発生してはいけない(=親子孫の関係)ので、Rvizフレームがない場合はT265が基準となります。そして、メカナムロボットの中心となるフレーム(base_link)はT265(odom)の子となります。そして、base_linkから各ホイールとLRFにつなぎます。

f:id:Ray_ar:20210328110826p:plain

 これをURDFとして記述します。次に、GitHubから抜粋したものを示します。なお、衝突判定などの記述は省略します。

リンク作成

1.odom(=T265)の記述

 T265の模型を作成します。長方形を作成しているだけです。

<link name="odom">
    <inertial>
        <mass value="1"/>
        <inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" />
    </inertial>
    <visual>
        <origin xyz="0 0 0" />
        <geometry>
            <box size=".015 .105 .02" />
        </geometry>
        <material name="black">
            <color rgba="0 0 0 1"/>
        </material>
    </visual>
</link>

2.base_link(メカナムロボットの本体)の記述

 メカナムロボットの中心とそのビジュアルを作成します。

<link name="base_link">
    <inertial>
        <mass value="1"/>
        <inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" />
    </inertial>

    <visual>
        <origin xyz="0 0 .0575" />
        <geometry>
            <box size=".21 .15 .12" />
        </geometry>
        <material name="white">
            <color rgba="1 1 1 1"/>
        </material>
    </visual>
</link>

3.wheel(メカナムホイール)とlidar(LRF)の記述

 メカナムホイールとLRFの記述をします。ここではメカナムホイールの1輪のみ示します。メカナムホイールは円柱を使用して表現しました。円柱は高さと半径を指定します。

<link name="wheel0">
    <visual>
        <geometry>
            <cylinder length="0.03" radius="0.04"/>
        </geometry>
        <origin xyz="0 0 0" rpy="1.57 0 0"/>
        <material name="blue">
            <color rgba="0 0 1 1"/>
        </material>
    </visual>
</link>

ジョイント作成

1.odom→base_linkの作成

 odom→base_link間はx軸方向に-12cm、z軸方向に-5.5cmずれていました。parentはodom、childはbase_linkです。

<joint name="base_linkconnect" type="fixed">
    <origin xyz="-.12 0 -.055" />
    <parent link="odom"/>
    <child link="base_link"/>
</joint>

2.base_link→wheel・lidarの作成

 parentがbase_link、childが各リンクの関係になるように記述します。

<joint name="wheel0_connect" type="fixed">
    <origin xyz=".05 .105 .04" />
    <parent link="base_link"/>
    <child link="wheel0"/>
</joint>

URDF確認

 robot_state_publisherの引数にURDFを指定することで反映することができます。launch.pyでは次のように設定します。このプログラムから抜粋しています。

#抜粋
use_sim_time = LaunchConfiguration('use_sim_time', default='false')
urdf_file_name = 'ar_ray_robot.urdf.xml'

robot_state_pub = Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            name='robot_state_publisher',
            output='screen',
            parameters=[{'use_sim_time': use_sim_time}],
            arguments=[urdf]
        )

 また、Realsense T265の設定は次のようにします。

#抜粋
t265_base_frame_id = LaunchConfiguration('base_frame_id', default='odom')
t265_serial_no = LaunchConfiguration('serial_no', default='925122110087')
    
t265_node = Node(
    package='realsense_node',
    node_executable='realsense_node',
    node_namespace="/t265",
    output='screen',
    remappings=[('/t265/camera/odom/sample','/odom')],
    parameters=[{'serial_no':t265_serial_no ,'base_frame_id': t265_base_frame_id}]
    )

 Rvizも起動します。

#抜粋
config_file_name = 'ar_ray_robot.rviz'

rviz_config = os.path.join(
    get_package_share_directory('ar-ray-robot'),
    config_file_name)
#    
# ・・・
# returnの中
Node(
    package='rviz2',
    executable='rviz2',
    name='rviz2',
    output='screen',
    arguments=['-d', rviz_config]),

 実行結果です。

f:id:Ray_ar:20210326132114p:plain
起動後
f:id:Ray_ar:20210326132140p:plain
軸を消したあと

 リンクの関係は発行されたtf_treeで確認できます。画像は、出力されたtf_treeに先ほどのリンクマーカーを当てはめた結果です。ちゃんと親子関係が守られています。ロボットを動かして移動していることを確認する場合は、Rviz2のfixed_frameodom_frameに変更してください。

f:id:Ray_ar:20210326132449p:plain

次回はこのモデルを使用して、実際に座標変換します。

ブログ開設1年。これまでとこれからについて

 4月1日、私がブログを開設してから1年経ちました。1年が経過するのは意外とあっという間だなぁと感じさせられる1年でした。

 昨年の今は、専攻科進学のために推薦書や面接練習などの文章を書いていた記憶があります。また、コロナ禍で緊急事態宣言が出されていて、いろいろな活動が制限されていたころでした。緊急事態宣言の影響で学校開始も1か月後に先延ばしになりました。

これまでについて・ブログを開設した理由

 私が昨年のこの日にブログを開設した理由は、「ものづくりのモチベーションを保つため」でした。私は、「高専ロボコン」というロボット競技に4年間参加しました。5年生は、研究と進路決定というイベントがある年なので、ロボコンに参加しないことは前々から決めていました。春休みも学校に通ってものづくりに取り組む予定だったので。

 しかし、3月から自宅での待機となってから学校に行く機会もなく、お金もなくとてももどかしい思いでした。おそらく皆さんもそうだったと思います。

 ある日、親がどこでもらってきたのかは分かりませんが、踏切のペーパークラフトをもらってきたみたいで、私に渡しました。

 私は昔電車が好きだったみたいで、買い物途中の踏切で電車を見るためだけに足を止めていたらしいです。福岡に住んでいた小学校低学年の時は西鉄(天神~大牟田間を結ぶ民鉄)の駅名を全て暗記したことをおぼえています。引退列車に思いを馳せるほどの熱心なファンではありませんでしたが、リレーつばめ787系)廃止(当時は引退だと思っていた)時はもう見られなくなるのかと寂しく思いました。

 ペーパークラフトをもらった時は、正直ばかにしているのかとも思いましたが、当時は本当になにも作るものがなかったのでとりあえず組み立てることにしました。

 この踏切は踏切柄の鉛筆を挿す向きを変えることができるみたいで、とりあえず鉛筆を挿して放置していましたが、転がっていたサーボモータを見て電車が好きだった昔の自分を思い出しました。「そうだ、これを動くようにしよう!」

 私は、近くのダイソーで電車のおもちゃとその他数点の目的のものを購入しました。

 また、電車もコントローラで動かしてみました。

 久しぶりにものづくりをしたので慣れない部分もありましたが、完成した時は久々の達成感を感じました。この頃は、部活内のWikiなるものを書いたりして文章もそこそこ書いていたので、片手間でちょっとしてみようかなと思いブログをとりあえず4月1日に開いたんじゃないかなーと思います。(もう1年前のことなので正確には覚えていません) 残念ながら、12月ころまでは学会への参加が何度かあり、資料作成が忙しくてあまり投稿していませんでした。

大きな転機・ROS2の使用

 大きな転機があったのはROS2の使用を開始した11月頃からでした。ROS2は、研究で使用していたROS1が仕組み使いにくかったことがきっかけです。何も下調べしていないのに移行を進める自分も異常なのではと思ってしまいますが、ROS2Arduinoや複数台前提のシステムに夢を持ち始め、移植を開始。実際は1週間程度でシステムの移植は終わりました。

 しかしそこで感じたのは、ROS2やROS2Arduinoの記事はまだ十分ではないというところです。私は、この頃から備忘録としてROS2の記事をちまちまと投稿するようになりました。また、Twitterコミュニティを通して意見を頂くことも多く、ROS2の使用例などの投稿をして貢献したいと感じるようになり、記事投稿に対するモチベーションが向上しました。冬休みからはほとんど毎日投稿するようになり、現在は2日に1日投稿するペースになっています。

これからについて・あと2年どう生きるか

 私は今年度は専攻科に入学し、あと2年学生ができるようになりました。周囲(友達や教員)からは大学院に行かないのかと言われることもよくありますが、資金面、学力面からその可能性はないと思います。あまり時間はありません。

 卒業まであと2年しかない中で私は研究以外のことで何かの活動に参加したいと考えています。現時点ではロボマスチームへの参加かつくばチャレンジに参加したいなーと考えています。もちろん、そのどちらに参加しなくても忙しいのですが、実環境で動くロボットを実際に制御する経験は積みたいと考えています。実際には入学して授業と研究の様子を見ながら考えることになりそうです。

 ブログについては、現在は、ROS2での(実例的な意味での)貢献をしたいと考えています。これからはROS-Foxy・ROS-Rollingで誰もあまり扱っていない内容(tf2やシミュレーション系・統合系)に挑戦してその記事を書きたいと考えています。とくに5月~7月は非常に忙しくなることが予想されるので、記事の内容が薄くなると思います。成果が出れば公表すると思います。

 オープンソースのロボットプロジェクト「ar-ray-robot(仮称)」や画像処理のROS実装の検討についても進めていきます。

github.com

 できれば、執筆した記事で収入が欲しいとも考えています。あまり言えることは多くないですが、研究とは関係ない範囲でROS関連の有料記事を作成したいと思っています。そのためにも自分の中の怠惰と闘い、自己研鑽に励みたいと思っています。

おわりに

 2020年4月1日から今日(3月31日現在)までの1年間で総PV数が984、2021年3月のみだと398件となりました。本当にありがとうございます。まだまだ半端なところが多いですがこれからもよろしくお願いします。

f:id:Ray_ar:20210329121305p:plain