新たなロボットをmc_rtcでサポートする方法

mc_rtcには、以下の3つの方法でロボットを組み込むことができます。

  1. env/objectローダーを使用する
  2. JSON/YAMLファイルとjsonローダーを使用する
  3. C++でRobotModuleの実装を記述する

最初の方法は、センサーが取り付けられていないシンプルなロボット(名前が示すとおり、単なるオブジェクトと環境)に適しています。そうしたロボットの要件については、以下のセクションで説明します。

2番目の方法では、ロボットに関するより多くの情報を与えることができます。

最後の選択肢は最も柔軟性が高い方法です。この方法の主なメリットは、ロボットを極めて簡単に読み込むことができ、最小限の労力でさまざまなバリエーションのロボットを簡単に作成できる点にあります。

env/objectローダーを使用する

ロボットを読み込むには、以下のように呼び出しを行います。

#include <mc_rbdyn/RobotLoader.h>

std::string path = "/path/to/description";
std::string name = "name";
auto env = mc_rbdyn::RobotLoader::get_robot_module("env", path, name);

// オブジェクトによってロボットと浮遊ベースが読み込まれる
auto object = mc_rbdyn::RobotLoader::get_robot_module("object", path, name);
import mc_rbdyn

path = "/path/to/description"
name = "name"
env = mc_rbdyn.get_robot_module("env", path, name)

# オブジェクトによってロボットと浮遊ベースが読み込まれる
object = mc_rbdyn.get_robot_module("object", path, name)
["env", "/path/to/description", "name"]

// オブジェクトによってロボットと浮遊ベースが読み込まれる
["object", "/path/to/description", "name"]
[env, /path/to/description, name]

# オブジェクトによってロボットと浮遊ベースが読み込まれる
[object, /path/to/description, name]

ロボット記述パッケージを整理する

ロボット記述フォルダーがLOCATIONにあり、ロボットの名前がNAMEであるとき、mc_rtcは、データが以下のように整理されているはずです。

  • URDFが$LOCATION/urdf/$NAME.urdfにある
  • RSDFファイルが$LOCATION/rsdf/$NAME/フォルダーにある
  • 凸領域ファイルが$LOCATION/convex/$NAME/フォルダーにある。また、BODYで指定されたボディのBODY衝突凸領域が$BODY-ch.txtに記述されている

Furthermore:

  • RSDFフォルダーは空であってもよい(または存在しなくてもよい)
  • ボディに凸領域ファイルを必ずしも関連付ける必要はない
  • ボディに関連付けることができない凸領域ファイルは、自動的に無視される

jsonローダーを使用する

ロボットを読み込むには、以下のように呼び出しを行います。

#include <mc_rbdyn/RobotLoader.h>

std::string json_path = "/path/to/file.json";
auto rm_json = mc_rbdyn::RobotLoader::get_robot_module("json", json_path);

std::string yaml_path = "/path/to/file.yaml";
auto rm_yaml = mc_rbdyn::RobotLoader::get_robot_module("json", yaml_path);
import mc_rbdyn

json_path = "/path/to/file.json"
rm_json = mc_rbdyn.get_robot_module("json", json_path)

yaml_path = "/path/to/file.yaml"
rm_yaml = mc_rbdyn.get_robot_module("json", yaml_path)
["json", "/path/to/file.json"]

["json", "/path/to/file.yaml"]
[json, /path/to/file.json]

[json, /path/to/file.yaml]

JSON/YAMLファイルで必要とされるデータ

jsonモジュールは、envモジュールと同じようにデータが整理されていることを想定しています。ただし、ユーザーがデータを与えることで、それらの要件のいくつかは無視できます。また、力覚センサー、ボディセンサー、最小限の自己衝突メッシュセットなどのデータをモジュールに与えることができます。

jsonローダーで必要とされるデータの詳細については、JSON/YAMLのドキュメントを参照してください。

独自のRobotModuleを実装する

この方法では、ロボットのRobotModuleを定義するためのC++クラスを記述し、ユーザーが指定したいデータメンバーをそのクラスのデータメンバーに置き換えます。最小限のサンプルを以下に示します。

cmake_minimum_required(VERSION 3.1)

find_package(mc_rtc REQUIRED)

add_robot_simple(MyRobot)
# 以下のためのショートカット:
#
# add_robot(MyRobot MyRobot.h MyRobot.cpp)
#pragma once

#include <mc_rbdyn/RobotModule.h>
#include <mc_robots/api.h>

struct MC_ROBOTS_DLLAPI MyRobotModule : public mc_rbdyn::RobotModule
{
public:
  MyRobotModule(bool fixed);
};

extern "C"
{
  ROBOT_MODULE_API void MC_RTC_ROBOT_MODULE(std::vector<std::string> & names)
  {
    // このモジュールによってエクスポートされるロボットの名前
    names = {"MyRobot", "MyRobotFixed"};
  }
  ROBOT_MODULE_API void destroy(mc_rbdyn::RobotModule * ptr)
  {
    delete ptr;
  }
  ROBOT_MODULE_API mc_rbdyn::RobotModule * create(const std::string & name)
  {
    // 現時点ではサポートされているいずれかのロボットの名前を使用する必要がある
    if(name == "MyRobot") { return new MyRobot(false); }
    else { return new MyRobot(true); }
  }
}
#include "MyRobot.h"

#include <RBDyn/parsers/urdf.h>

// MY_PATHはCMakeなどで与えることができる
MyRobotModule::MyRobotModule(bool fixed) : mc_rbdyn::RobotModule(MY_PATH, "my_robot")
{
  init(rbd::parsers::from_urdf_file(urdf_path));

  std::vector<double> default_q = {-0.38, -0.01, 0., 0.72, -0.01, -0.33,  -0.38, 0.02, 0.,    0.72, -0.02, -0.33, 0.,
                                   0.13,  0.,    0., 0.,   0.,    -0.052, -0.17, 0.,   -0.52, 0.,   0.,    0.,    0.,
                                   0.,    0.,    0., 0.,   0.,    -0.052, 0.17,  0.,   -0.52, 0.,   0.,    0.,    0.,
                                   0.,    0.,    0., 0.,   0.,    0.,     0.,    0.,   0.,    0.,   0.};
  const auto & rjo = ref_joint_order();
  for(size_t i = 0; i < rjo.size(); ++i) { _stance[rjo[i]] = {default_q[i]}; }
  _default_attitude = {{1., 0., 0., 0., 0., 0., 0.8275}};
  _forceSensors.push_back(mc_rbdyn::ForceSensor("RightFootForceSensor", "R_ANKLE_P_S", sva::PTransformd::Identity()));
  _forceSensors.push_back(mc_rbdyn::ForceSensor("LeftFootForceSensor", "L_ANKLE_P_S", sva::PTransformd::Identity()));
  _forceSensors.push_back(mc_rbdyn::ForceSensor("RightHandForceSensor", "R_WRIST_Y_S", sva::PTransformd::Identity()));
  _forceSensors.push_back(mc_rbdyn::ForceSensor("LeftHandForceSensor", "L_WRIST_Y_S", sva::PTransformd::Identity()));

  _bodySensors.emplace_back("Accelerometer", "PELVIS_S", sva::PTransformd(Eigen::Vector3d(-0.0325, 0, 0.1095)));
  _bodySensors.emplace_back("FloatingBase", "PELVIS_S", sva::PTransformd::Identity());

  _minimalSelfCollisions = {
      {"WAIST_R_S", "L_SHOULDER_Y_S", 0.02, 0.001, 0.}, {"WAIST_R_S", "R_SHOULDER_Y_S", 0.02, 0.001, 0.},
      {"PELVIS_S", "R_ELBOW_P_S", 0.05, 0.001, 0.},     {"PELVIS_S", "L_ELBOW_P_S", 0.05, 0.001, 0.},
      {"R_WRIST_Y_S", "R_HIP_Y_S", 0.05, 0.025, 0.},    {"L_WRIST_Y_S", "L_HIP_Y_S", 0.05, 0.025, 0.}};
  _commonSelfCollisions = _minimalSelfCollisions;
  _grippers = {{"l_gripper", {"L_UTHUMB"}, true}, {"r_gripper", {"R_UTHUMB"}, false}};
}

指定可能なメンバーについては、mc_rbdyn::RobotModuleのドキュメントを参照してください。

さあ始めましょう

mc-rtc/new-robot-moduleテンプレートプロジェクトを使用すると、すぐに始められます。このテンプレートには、C++またはYAMLのRobotModule用の必要最小限の構造が記述されています。