ここまで、Isaac Sim上でTurtlebot3を動かす方法について説明した。実際にシミュレーション上のロボットと実機ロボットを同期させる時には、物理演算などでズレが発生する場合がある。高度な物理演算機能を持つIsaac Simには、オブジェクト同士の摩擦係数やタイヤ回転のステータスなど設定が必要な多くのパラメータがあり、ズレを調整することは容易ではない。
そこで今回、実機から送信される/odomトピックを使って、Isaac Sim上のTurtlebot3の位置を実機のTurtlebot3とリアルタイムで同期させてみよう。
Omni Graphには/odomを受信するノードがないため、Isaac Sim APIを使用して、Pythonから/odomトピックを受信し、ロボットの位置を調整する手法を用いる。Isaac SimはGUIから起動する方法の他に、Pythonから起動してその中でAPIを使いながらシミュレーションを動かす機能を有している(図18)。
ここでは、Turtlebot3実機ではROS 2によるセットアップ(ROBOTISのe-Mnualの「3.Quick Start Guide」まで)が完了しているものとする。また、ROS 2通信のため、Isaac SimのPCとTurtlebot3実機は同一ネットワーク上に置く。
(1)/odomを受信し、APIを用いてロボットの位置を調整するコード(リスト6)を作成する。
from omni.isaac.kit import SimulationApp
import argparse
#ROS2 Bridgeの有効化設定
parser = argparse.ArgumentParser(description="Generate Occluded and Unoccluded data")
parser.add_argument("--test", action="store_true")
parser.add_argument(
"--ros2_bridge",
default="omni.isaac.ros2_bridge",
nargs="?",
choices=["omni.isaac.ros2_bridge", "omni.isaac.ros2_bridge-humble"],
)
args, unknown = parser.parse_known_args()
# Isaac Simの初期設定
simulation_app = SimulationApp({"renderer": "RayTracedLighting", "headless": False})
import omni
from omni.isaac.core import SimulationContext
from pxr import Gf
#ROS2 Bridgeの有効化
from omni.isaac.core.utils.extensions import enable_extension
enable_extension(args.ros2_bridge)
import rclpy
from rclpy.node import Node
from nav_msgs.msg import Odometry
# /odomを受信し、位置同期を行うノード
class Subscriber(Node):
def __init__(self):
super().__init__("move_robot_subscriber")
#Isaac Simの起動処理
usd_path = "〇〇.usd”※「2.2.3 Isaac SimとROSの連携」で作成したUSDステージのファイルパス
omni.usd.get_context().open_stage(usd_path, None)
self.stage = omni.usd.get_context().get_stage()
simulation_app.update()
print("Loading stage...")
from omni.isaac.core.utils.stage import is_stage_loading
while is_stage_loading():
simulation_app.update()
print("Loading Complete")
self.simulation_context = SimulationContext(physics_prim_path ="/Environment/physicsScene")
self.simulation_context.play()
self.simulation_context.step()
for frame in range(60):
self.simulation_context.step()
#変数の初期化
self.x_initial=0.0
self.y_initial=0.0
self._robot_position = (0, 0, 0)
self._robot_orientation = Gf.Quatd(0.0, 0.0, 0.0, 1.0)
self._topic_sub_flg= False
self.ros_sub = self.create_subscription(Odometry, "odom", self.move_robot_callback, 10)
def move_robot_callback(self, data):
if self.simulation_context.is_playing():
topic_pos=data.pose.pose.position
topic_orientation= data.pose.pose.orientation
#/odomの初期値をIsaacSimの(0,0)とする
if self.x_initial == 0.0:
self.x_initial = topic_pos.x
self.y_initial = topic_pos.y
#位置,角度情報の格納
self._robot_position = (topic_pos.x-self.x_initial , topic_pos.y-self.y_initial, topic_pos.z)
self._robot_orientation = Gf.Quatd(topic_orientation.w, topic_orientation.x, topic_orientation.y, topic_orientation.z)
self._topic_sub_flg= True
def run_simulation(self):
#Isaac Simの実行処理
self.simulation_context.play()
while simulation_app.is_running():
self.simulation_context.step(render=True)
rclpy.spin_once(self, timeout_sec=0.0)
if self.simulation_context.is_playing():
if self.simulation_context.current_time_step_index == 0:
self.simulation_context.reset()
#/odomを受信したら位置を同期
if self._topic_sub_flg:
obj = self.stage.GetPrimAtPath("/World/turtlebot3_burger/base_link")
obj.GetAttribute("xformOp:translate").Set(self._robot_position)
print(self._robot_orientation)
obj.GetAttribute("xformOp:orient").Set(self._robot_orientation)
self._topic_sub_flg= False
self.simulation_context.stop()
self.destroy_node()
simulation_app.close()
if __name__ == "__main__":
rclpy.init()
subscriber = Subscriber()
subscriber.run_simulation()
(2)作成したコードを任意の場所に保存する。
今回は“~/.local/share/ov/pkg/isaac_sim-2022.2.1/ standalone_examples/api/omni.isaac.ros2_bridge/”に“turtlebot3_move.py”で保存する。
(3)Isaac Sim起動のため、ROSの環境変数設定を行う(リスト7)。
$ unset LD_LIBRARY_PATH $ export FASTRTPS_DEFAULT_PROFILES_FILE=~/.ros/fastdds.xml
(4)~/.local/share/ov/pkg/isaac_sim-2022.2.1上でリスト8のコマンドを用いて、保存したPythonコードを実行する。Isaac Simが起動し、Turtlebot3が表示される。
$ cd ~/.local/share/ov/pkg/isaac_sim-2022.2.1 $ ./python.sh standalone_examples/api/omni.isaac.ros2_bridge/turtlebot3_move.py
(5)実機側のターミナルで、Turtlebot3で用意されているROS 2での実機制御プログラムを起動する(リスト9)※3)。
$ ros2 launch turtlebot3_bringup robot.launch.py
/cmd_velでTurtlebot3を操作すると、Isaac Sim上のTurtlebot3と実機のTurtlebot3の動きが同期していることが分かる(図19)※4)。
プログラムの仕組みとしては、Isaac Simの起動処理後、/odomトピックを受信するノードによって、Isaac Sim内のオブジェクト位置を変更するAPIを用いて位置を同期している。
Turtlebot3の/odomにはタイヤの回転角とIMUによるロボットのスタートからの進行距離が格納されているため、それをIsaac Simの位置と同期するという仕組みだ。
Copyright © ITmedia, Inc. All Rights Reserved.
組み込み開発の記事ランキング
コーナーリンク
よく読まれている編集記者コラム