/* EDA机器狗控制器 - MCP协议版本 */ #include #include #include #include #include "application.h" #include "board.h" #include "config.h" #include "eda_dog_movements.h" #include "mcp_server.h" #include "sdkconfig.h" #include "settings.h" #define TAG "EDARobotDogController" class EDARobotDogController { private: EDARobotDog dog_; TaskHandle_t action_task_handle_ = nullptr; QueueHandle_t action_queue_; bool is_action_in_progress_ = false; struct DogActionParams { int action_type; int steps; int speed; int direction; int height; }; enum ActionType { ACTION_WALK = 1, ACTION_TURN = 2, ACTION_SIT = 3, ACTION_STAND = 4, ACTION_STRETCH = 5, ACTION_SHAKE = 6, ACTION_LIFT_LEFT_FRONT = 7, ACTION_LIFT_LEFT_REAR = 8, ACTION_LIFT_RIGHT_FRONT = 9, ACTION_LIFT_RIGHT_REAR = 10, ACTION_HOME = 11 }; static void ActionTask(void *arg) { EDARobotDogController *controller = static_cast(arg); DogActionParams params; controller->dog_.AttachServos(); while (true) { if (xQueueReceive(controller->action_queue_, ¶ms, pdMS_TO_TICKS(1000)) == pdTRUE) { ESP_LOGI(TAG, "执行动作: %d", params.action_type); controller->is_action_in_progress_ = true; switch (params.action_type) { case ACTION_WALK: controller->dog_.Walk(params.steps, params.speed, params.direction); break; case ACTION_TURN: controller->dog_.Turn(params.steps, params.speed, params.direction); break; case ACTION_SIT: controller->dog_.Sit(params.speed); break; case ACTION_STAND: controller->dog_.Stand(params.speed); break; case ACTION_STRETCH: controller->dog_.Stretch(params.speed); break; case ACTION_SHAKE: controller->dog_.Shake(params.speed); break; case ACTION_LIFT_LEFT_FRONT: controller->dog_.LiftLeftFrontLeg(params.speed, params.height); break; case ACTION_LIFT_LEFT_REAR: controller->dog_.LiftLeftRearLeg(params.speed, params.height); break; case ACTION_LIFT_RIGHT_FRONT: controller->dog_.LiftRightFrontLeg(params.speed, params.height); break; case ACTION_LIFT_RIGHT_REAR: controller->dog_.LiftRightRearLeg(params.speed, params.height); break; case ACTION_HOME: controller->dog_.Home(); break; } if (params.action_type != ACTION_HOME && params.action_type != ACTION_SIT) { controller->dog_.Home(); } controller->is_action_in_progress_ = false; vTaskDelay(pdMS_TO_TICKS(20)); } } } void StartActionTaskIfNeeded() { if (action_task_handle_ == nullptr) { xTaskCreate(ActionTask, "dog_action", 1024 * 3, this, configMAX_PRIORITIES - 1, &action_task_handle_); } } void QueueAction(int action_type, int steps, int speed, int direction, int height) { ESP_LOGI(TAG, "动作控制: 类型=%d, 步数=%d, 速度=%d, 方向=%d, 高度=%d", action_type, steps, speed, direction, height); DogActionParams params = {action_type, steps, speed, direction, height}; xQueueSend(action_queue_, ¶ms, portMAX_DELAY); StartActionTaskIfNeeded(); } void LoadTrimsFromNVS() { Settings settings("dog_trims", false); int left_front_leg = settings.GetInt("left_front_leg", 0); int left_rear_leg = settings.GetInt("left_rear_leg", 0); int right_front_leg = settings.GetInt("right_front_leg", 0); int right_rear_leg = settings.GetInt("right_rear_leg", 0); ESP_LOGI(TAG, "从NVS加载微调设置: 左前腿=%d, 左后腿=%d, 右前腿=%d, 右后腿=%d", left_front_leg, left_rear_leg, right_front_leg, right_rear_leg); dog_.SetTrims(left_front_leg, left_rear_leg, right_front_leg, right_rear_leg); } public: EDARobotDogController() { dog_.Init(LEFT_FRONT_LEG_PIN, LEFT_REAR_LEG_PIN, RIGHT_FRONT_LEG_PIN, RIGHT_REAR_LEG_PIN); ESP_LOGI(TAG, "EDA机器狗初始化完成"); LoadTrimsFromNVS(); action_queue_ = xQueueCreate(10, sizeof(DogActionParams)); QueueAction(ACTION_HOME, 1, 1000, 0, 0); RegisterMcpTools(); } void RegisterMcpTools() { auto &mcp_server = McpServer::GetInstance(); ESP_LOGI(TAG, "开始注册MCP工具..."); // 基础移动动作 mcp_server.AddTool( "self.dog.walk", "行走。steps: 行走步数(1-100); speed: " "行走速度(500-2000,数值越小越快); " "direction: 行走方向(-1=后退, 1=前进)", PropertyList({Property("steps", kPropertyTypeInteger, 4, 1, 100), Property("speed", kPropertyTypeInteger, 1000, 500, 2000), Property("direction", kPropertyTypeInteger, 1, -1, 1)}), [this](const PropertyList &properties) -> ReturnValue { int steps = properties["steps"].value(); int speed = properties["speed"].value(); int direction = properties["direction"].value(); QueueAction(ACTION_WALK, steps, speed, direction, 0); return true; }); mcp_server.AddTool( "self.dog.turn", "转身。steps: 转身步数(1-100); speed: " "转身速度(500-2000,数值越小越快); " "direction: 转身方向(1=左转, -1=右转)", PropertyList({Property("steps", kPropertyTypeInteger, 4, 1, 100), Property("speed", kPropertyTypeInteger, 2000, 500, 2000), Property("direction", kPropertyTypeInteger, 1, -1, 1)}), [this](const PropertyList &properties) -> ReturnValue { int steps = properties["steps"].value(); int speed = properties["speed"].value(); int direction = properties["direction"].value(); QueueAction(ACTION_TURN, steps, speed, direction, 0); return true; }); // 姿态动作 mcp_server.AddTool("self.dog.sit", "坐下。speed: 坐下速度(500-2000,数值越小越快)", PropertyList({Property("speed", kPropertyTypeInteger, 1500, 500, 2000)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); QueueAction(ACTION_SIT, 1, speed, 0, 0); return true; }); mcp_server.AddTool("self.dog.stand", "站立。speed: 站立速度(500-2000,数值越小越快)", PropertyList({Property("speed", kPropertyTypeInteger, 1500, 500, 2000)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); QueueAction(ACTION_STAND, 1, speed, 0, 0); return true; }); mcp_server.AddTool("self.dog.stretch", "伸展。speed: 伸展速度(500-2000,数值越小越快)", PropertyList({Property("speed", kPropertyTypeInteger, 2000, 500, 2000)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); QueueAction(ACTION_STRETCH, 1, speed, 0, 0); return true; }); mcp_server.AddTool("self.dog.shake", "摇摆。speed: 摇摆速度(500-2000,数值越小越快)", PropertyList({Property("speed", kPropertyTypeInteger, 1000, 500, 2000)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); QueueAction(ACTION_SHAKE, 1, speed, 0, 0); return true; }); // 单腿抬起动作 mcp_server.AddTool( "self.dog.lift_left_front_leg", "抬起左前腿。speed: 动作速度(500-2000,数值越小越快); height: " "抬起高度(10-90度)", PropertyList({Property("speed", kPropertyTypeInteger, 1000, 500, 2000), Property("height", kPropertyTypeInteger, 45, 10, 90)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); int height = properties["height"].value(); QueueAction(ACTION_LIFT_LEFT_FRONT, 1, speed, 0, height); return true; }); mcp_server.AddTool( "self.dog.lift_left_rear_leg", "抬起左后腿。speed: 动作速度(500-2000,数值越小越快); height: " "抬起高度(10-90度)", PropertyList({Property("speed", kPropertyTypeInteger, 1000, 500, 2000), Property("height", kPropertyTypeInteger, 45, 10, 90)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); int height = properties["height"].value(); QueueAction(ACTION_LIFT_LEFT_REAR, 1, speed, 0, height); return true; }); mcp_server.AddTool( "self.dog.lift_right_front_leg", "抬起右前腿。speed: 动作速度(500-2000,数值越小越快); height: " "抬起高度(10-90度)", PropertyList({Property("speed", kPropertyTypeInteger, 1000, 500, 2000), Property("height", kPropertyTypeInteger, 45, 10, 90)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); int height = properties["height"].value(); QueueAction(ACTION_LIFT_RIGHT_FRONT, 1, speed, 0, height); return true; }); mcp_server.AddTool( "self.dog.lift_right_rear_leg", "抬起右后腿。speed: 动作速度(500-2000,数值越小越快); height: " "抬起高度(10-90度)", PropertyList({Property("speed", kPropertyTypeInteger, 1000, 500, 2000), Property("height", kPropertyTypeInteger, 45, 10, 90)}), [this](const PropertyList &properties) -> ReturnValue { int speed = properties["speed"].value(); int height = properties["height"].value(); QueueAction(ACTION_LIFT_RIGHT_REAR, 1, speed, 0, height); return true; }); // 系统工具 mcp_server.AddTool("self.dog.stop", "立即停止", PropertyList(), [this](const PropertyList &properties) -> ReturnValue { if (action_task_handle_ != nullptr) { vTaskDelete(action_task_handle_); action_task_handle_ = nullptr; } is_action_in_progress_ = false; xQueueReset(action_queue_); QueueAction(ACTION_HOME, 1, 1000, 0, 0); return true; }); mcp_server.AddTool( "self.dog.set_trim", "校准单个舵机位置。设置指定舵机的微调参数以调整机器狗的初始站立姿态,设" "置将永久保存。" "servo_type: " "舵机类型(left_front_leg/left_rear_leg/right_front_leg/" "right_rear_leg); " "trim_value: 微调值(-50到50度)", PropertyList( {Property("servo_type", kPropertyTypeString, "left_front_leg"), Property("trim_value", kPropertyTypeInteger, 0, -50, 50)}), [this](const PropertyList &properties) -> ReturnValue { std::string servo_type = properties["servo_type"].value(); int trim_value = properties["trim_value"].value(); ESP_LOGI(TAG, "设置舵机微调: %s = %d度", servo_type.c_str(), trim_value); // 获取当前所有微调值 Settings settings("dog_trims", true); int left_front_leg = settings.GetInt("left_front_leg", 0); int left_rear_leg = settings.GetInt("left_rear_leg", 0); int right_front_leg = settings.GetInt("right_front_leg", 0); int right_rear_leg = settings.GetInt("right_rear_leg", 0); // 更新指定舵机的微调值 if (servo_type == "left_front_leg") { left_front_leg = trim_value; settings.SetInt("left_front_leg", left_front_leg); } else if (servo_type == "left_rear_leg") { left_rear_leg = trim_value; settings.SetInt("left_rear_leg", left_rear_leg); } else if (servo_type == "right_front_leg") { right_front_leg = trim_value; settings.SetInt("right_front_leg", right_front_leg); } else if (servo_type == "right_rear_leg") { right_rear_leg = trim_value; settings.SetInt("right_rear_leg", right_rear_leg); } else { return "错误:无效的舵机类型,请使用: left_front_leg, " "left_rear_leg, right_front_leg, right_rear_leg"; } dog_.SetTrims(left_front_leg, left_rear_leg, right_front_leg, right_rear_leg); QueueAction(ACTION_HOME, 1, 500, 0, 0); return "舵机 " + servo_type + " 微调设置为 " + std::to_string(trim_value) + " 度,已永久保存"; }); mcp_server.AddTool( "self.dog.get_trims", "获取当前的舵机微调设置", PropertyList(), [this](const PropertyList &properties) -> ReturnValue { Settings settings("dog_trims", false); int left_front_leg = settings.GetInt("left_front_leg", 0); int left_rear_leg = settings.GetInt("left_rear_leg", 0); int right_front_leg = settings.GetInt("right_front_leg", 0); int right_rear_leg = settings.GetInt("right_rear_leg", 0); std::string result = "{\"left_front_leg\":" + std::to_string(left_front_leg) + ",\"left_rear_leg\":" + std::to_string(left_rear_leg) + ",\"right_front_leg\":" + std::to_string(right_front_leg) + ",\"right_rear_leg\":" + std::to_string(right_rear_leg) + "}"; ESP_LOGI(TAG, "获取微调设置: %s", result.c_str()); return result; }); mcp_server.AddTool("self.dog.get_status", "获取机器狗状态,返回 moving 或 idle", PropertyList(), [this](const PropertyList &properties) -> ReturnValue { return is_action_in_progress_ ? "moving" : "idle"; }); ESP_LOGI(TAG, "MCP工具注册完成"); } ~EDARobotDogController() { if (action_task_handle_ != nullptr) { vTaskDelete(action_task_handle_); action_task_handle_ = nullptr; } vQueueDelete(action_queue_); } }; static EDARobotDogController *g_dog_controller = nullptr; void InitializeEDARobotDogController() { if (g_dog_controller == nullptr) { g_dog_controller = new EDARobotDogController(); ESP_LOGI(TAG, "EDA机器狗控制器已初始化并注册MCP工具"); } }