mc_rtc::Configuration 設定mc_rtcには、以下の3つの方法でロボットを組み込むことができます。
env/objectローダーを使用するjsonローダーを使用するRobotModuleの実装を記述するenv/objectローダー:jsonローダー:RobotModule: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は、データが以下のように整理されているはずです。
$LOCATION/urdf/$NAME.urdf にある$LOCATION/rsdf/$NAME/ フォルダーにある(任意)$LOCATION/convex/$NAME/ フォルダーにある(任意)たとえば、ボディ名が BODY の場合、対応する凸包ファイル名は:
BODY-ch.txt
mc_rtcでは、すべてのローダー方式(env、JSON、C++)において、URDFまたはSRDF内に定義されたメッシュから 衝突用凸包を自動生成できます。
生成された凸包は、ユーザー環境ごとのローカル共有ディレクトリに保存されます。
このパスは local_share_directory() 関数により構築され、プラットフォームによって異なります。
%APPDATA%/mc_rtc/<robot_name>/$HOME/.local/share/mc_rtc/<robot_name>/BODY-ch.txtBODY_0-ch.txt, BODY_1-ch.txt のように番号付きで生成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モジュールは、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_rbdyn::RobotModule::connect および mc_rbdyn::RobotModule::ConnectionParameters を参照してください。主に使用する関数は以下の通りです:RobotModule RobotModule::connect(const mc_rbdyn::RobotModule & other,
const std::string & this_body,
const std::string & other_body,
const std::string & prefix,
const ConnectionParameters & params) const#include <mc_rbdyn/RobotLoader.h>
#include <mc_rbdyn/RobotModule.h>
// 「box」のビジュアル記述から「robot_support」ロボットを定義する
auto boxYaml =
R"(
name: robot_support
origin:
translation: [0, 0, 0]
rotation: [0, 0, 0]
material:
color:
r: 1.0
g: 0.0
b: 0.0
a: 1.0
geometry:
box:
size: [0.7, 1.2, 1.2]
inertia:
mass: 50
fixed: true
)";
auto boxConfig = mc_rtc::Configuration::fromYAMLData(boxYaml);
// 上記のビジュアル記述から「robot_support」ロボットモジュールを作成する
auto supportRm = mc_rbdyn::robotModuleFromVisual("robot_support", boxConfig);
// 既存のロボットモジュールからパンダロボットモジュールをロードする
auto pandaRm = mc_rbdyn::RobotLoader::get_robot_module("PandaDefault");
// PandaDefaultモジュールの「world」リンクのベースとrobot_supportリンクの間の変換
auto box_to_robot = sva::PTransformd(Eigen::Vector3d{0., 0., -1.2});
// 既存の「PandaDefault」モジュールを「box」モジュールに接続して新しいロボットモジュールをロードする
auto pandaOnBoxRm = supportRm->connect(
*pandaRm, // この他のロボットモジュール(パンダ)に接続する
"robot_support", // 自分のモジュールの参照リンク
"world", // 他のロボットモジュール(パンダ)のこのリンクに接続する
"", // リンク名に追加するオプションのプレフィックス
mc_rbdyn::RobotModule::ConnectionParameters{}.name(robot_name).X_other_connection(box_to_robot) // 接続パラメータ
);
// ctlはmc_control::MCControllerであり、ロボットをコントローラに追加する
auto robot = ctl.loadRobot(*pandaOnBoxRm);mc-rtc/new-robot-moduleテンプレートプロジェクトを使用すると、すぐに始められます。このテンプレートには、C++またはYAMLのRobotModule用の必要最小限の構造が記述されています。