Skip to content

Skill実装ガイド

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

基本概念

スキルの役割

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

ベースクラス選択

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

基本実装パターン

// シンプルスキル例
class SimpleMove : public SkillBase
{
public:
  explicit SimpleMove(uint8_t id) : SkillBase("SimpleMove", id) {}

  Status update() override {
    auto command = getCommand();
    command.setTargetPosition(target_position);
    return Status::RUNNING;
  }
};

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

class Kick : public SkillBaseWithState<KickState>
{
public:
  explicit Kick(uint8_t id) : SkillBaseWithState("Kick", id) {
    setCurrentState(KickState::APPROACH);
  }

  Status update() override {
    switch(getCurrentState()) {
      case KickState::APPROACH: return approachBall();
      case KickState::KICK: return executekick();
      case KickState::FINISH: return Status::SUCCESS;
    }
  }
};

APIリファレンス

基本メソッド

メソッド 戻り値 説明
getCommand() RobotCommandWrapper& ロボットコマンド取得
getWorld() WorldModelWrapper::SharedPtr ワールド状態取得
getID() uint8_t ロボットID取得
emplace<T>(args...) void パラメータ設定

Status列挙型

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

パラメータシステム

// パラメータ設定
skill.emplace<Point>("target", Point(1.0, 2.0));
skill.emplace<double>("max_velocity", 3.0);
skill.emplace<bool>("enable_collision_avoidance", true);

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

コンテキスト管理

// コンテキスト設定
context.goal_pose = Pose2D(3.0, 0.0, 0.0);
context.keep_control = true;

// 可視化
addCircle(center, radius, color);
addText(position, "Status: Running");

主要スキル一覧

攻撃系

  • Attacker: メイン攻撃ロボット(状態遷移型)
  • Kick: ボールキック実行
  • Receive: パス受け取り
  • GoOverBall: ボール通過

守備系

  • Goalie: ゴールキーパー専用
  • Marker: 敵ロボットマーク
  • Steal: ボール奪取

ユーティリティ

  • SimpleMove: 基本移動
  • Sleep: 待機状態
  • Teleop: 手動操作

統合手順

1. SimpleAI統合

// SimpleAIプランナーでの使用
auto skill = std::make_shared<YourSkill>(robot_id);
skill->emplace<Point>("target", target_position);
assigned_robots[robot_id] = skill;

2. セッション統合

# config/play_situation/YOUR_SITUATION.yaml
nodes:
  - name: your_skill_planner
    type: SkillPlannerBase  
    params:
      skill_name: "YourSkill"

3. 可視化統合

// スキル内での可視化
addCircle(target_pos, 0.1, "blue");
addText(robot_pos, skill_name + ": " + status_text);
addLine(robot_pos, target_pos, "green");

ベストプラクティス

パフォーマンス

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

品質保証

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

設計原則

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

トラブルシューティング

よくあるエラー

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

デバッグテクニック

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

// 可視化デバッグ
addText(getPosition(), fmt::format("{}: {}", getName(), getStatusString()));

関連ドキュメント