Skip to content

Skill実装ガイド

Skillは単一ロボットの行動を表す基本単位です。

基本概念

スキルの役割

  • 入力: world_model(ワールド状態)
  • 出力: ロボットコマンド + 可視化情報
  • 実装場所: crane_robot_skillsパッケージ

ベースクラス選択

ベースクラス 用途 実装要件
SkillBase シンプルな行動制御 update()メソッドのみ
SkillBaseWithState<T> 複雑な状態遷移 addStateFunction() + addTransition()

基本実装パターン

シンプルスキル例

// シンプルスキル例
class SimpleMove : public SkillBase
{
public:
  // コンストラクタ: ワールドモデルも受け取る必要がある
  explicit SimpleMove(uint8_t id, const std::shared_ptr<WorldModelWrapper> & wm)
    : SkillBase("SimpleMove", id, wm) {}

  Status update() override {
    // commander()経由でコマンド操作
    commander()->setTargetPosition(getParameter<Point>("target"));
    return Status::RUNNING;
  }
};

状態付きスキル例

// 状態付きスキル例  
enum class KickState { ENTRY_POINT, APPROACH, KICK, FINISH };

class Kick : public SkillBaseWithState<KickState>
{
public:
  explicit Kick(uint8_t id, const std::shared_ptr<WorldModelWrapper> & wm)
    : SkillBaseWithState("Kick", id, wm) {

    // 状態ごとの処理定義
    addStateFunction(KickState::ENTRY_POINT, [this]() {
       visualizer->drawDebugLabel(robot()->pose.pos, "Kick::ENTRY_POINT");
       return Status::RUNNING;
    });

    // 遷移定義
    addTransition(KickState::ENTRY_POINT, KickState::APPROACH, [this]() {
       return true; // 遷移条件
    });

    addStateFunction(KickState::APPROACH, [this]() {
      return approachBall();
    });

    // ...
  }
};

APIリファレンス

基本メソッド

メソッド 戻り値 説明
commander() PositionCommandWrapper::SharedPtr ロボットコマンド操作用ラッパー
world_model() WorldModelWrapper::SharedPtr ワールド状態取得
getID() uint8_t ロボットID取得
robot() RobotInfo::SharedPtr 自身のロボット情報取得
setParameter(key, value) void パラメータ設定
getParameter<T>(key) T パラメータ取得

Status列挙型

意味 用途
SUCCESS 成功完了 目標達成時
FAILURE 失敗終了 エラー発生時
RUNNING 実行中 継続実行時

パラメータシステム

// パラメータ設定
skill.setParameter("target", Point(1.0, 2.0));
skill.setParameter("max_velocity", 3.0);
skill.setParameter("enable_collision_avoidance", true);

// パラメータ取得
auto target = getParameter<Point>("target");
auto velocity = getParameter<double>("max_velocity");

可視化

crane::VisualizerMessageBuilderを使用します。SkillBaseが自動的にインスタンスを管理します。

// VisualizerMessageBuilderを使用
visualizer->drawCircle(center, radius, "blue");
visualizer->drawDebugLabel(robot()->pose.pos, "Status: Running");
visualizer->arrow(start, end, "white");

主要スキル一覧

攻撃系

  • Attacker: メイン攻撃ロボット
  • SubAttacker: 攻撃サポート
  • Kick: ボールキック実行
  • Receive: パス受け取り
  • PenaltyKick: ペナルティキック実行

守備系

  • Goalie: ゴールキーパー専用
  • SecondThreatDefender: 守備
  • Marker: 敵ロボットマーク

ユーティリティ・その他

  • Idle: 待機
  • Teleop: 手動操作
  • Sleep: 待機状態
  • BallNearbyPositioner: ボール近傍位置合わせ
  • GoalKick: ゴールキック
  • SimpleKickoff: キックオフ
  • CenterStopKick: センターサークルでの停止・キック
  • EmplaceRobot: 指定位置へのロボット配置
  • SingleBallPlacement: ボールプレースメント
  • BallCalibrationDataCollector: ボールモデル学習用データ収集

統合手順

1. SimpleAIタクティックでの使用

// SimpleAIタクティックでの使用
auto skill = std::make_shared<YourSkill>(robot_id, world_model);
skill->setParameter("target", target_position);
// 実行
skill->run();
// コマンド取得
auto cmd = skill->getRobotCommand();

2. セッション統合

統一設定ファイルに追加:

# config/unified_session_config.yaml
situations:
  YOUR_SITUATION:
    sessions:
      - name: your_skill_tactic
        capacity: 1

ベストプラクティス

パフォーマンス

  • ヘッダー最小化: 実装はcppファイルに記述
  • 早期リターン: 条件チェックを先頭で実行
  • メモリ効率: 不要な計算は避ける

品質保証

  • エラーハンドリング: 異常状態での適切なSTATUS返却
  • テスタビリティ: 単体テストを意識した設計
  • 可視化: デバッグ情報の適切な出力

設計原則

  • 単一責任: 1つのスキル = 1つの行動
  • 状態管理: 複雑な場合は状態遷移を明確化
  • 再利用性: 他のスキルから呼び出し可能な設計

トラブルシューティング

よくあるエラー

エラー 原因 解決方法
コンパイルエラー ヘッダーの循環依存 前方宣言を使用
実行時エラー パラメータ未設定 getParameterにデフォルト値設定
動作不良 状態遷移ミス ログ出力で状態確認

デバッグテクニック

// ログ出力
RCLCPP_INFO(logger_, "Skill %s: State=%d, Target=(%.2f,%.2f)",
           name.c_str(), static_cast<int>(getCurrentState()),
           target.x(), target.y());

// 可視化デバッグ
visualizer->drawDebugLabel(robot()->pose.pos, fmt::format("{}: {}", name, state_string));

関連ドキュメント