文章目录
- ExternalCommandProcessComponent(服务端)
- 输入
- 输出
- external_command_demo(客户端)
- 插件ActionCommandProcessor
ExternalCommandProcessComponent(服务端)
输入
用户业务模块发送的命令为apollo::external_command::ExternalCommandProcessComponent的输入,用户输入命令通过 apollo::cyber::Client客户端 调用。
在每个命令对应的CommandProcessor中创建处理命令的apollo::cyber::Service,service的Response一般都是当前命令处理的状态。
通过cat /apollo/modules/external_command/process_component/conf/config.pb.txt
可以看到conf配置文件中包含7个服务端处理器。
output_command_status_name: "/apollo/external_command/command_status"
processor: "apollo::external_command::LaneFollowCommandProcessor"
processor: "apollo::external_command::ValetParkingCommandProcessor"
processor: "apollo::external_command::ActionCommandProcessor"
processor: "apollo::external_command::ChassisCommandProcessor"
processor: "apollo::external_command::FreeSpaceCommandProcessor"
processor: "apollo::external_command::PathFollowCommandProcessor"
processor: "apollo::external_command::SpeedCommandProcessor"
service 名 | Request类型 | Response类型 | 描述 |
---|---|---|---|
/apollo/external_command/action | apollo::external_command::ActionCommand | apollo::external_command::CommandStatus | 流程干预命令,如暂停,启动,切换手动模式等 |
/apollo/external_command/chassis | apollo::external_command::ChassisCommand | apollo::external_command::CommandStatus | 自定义底盘命令(园区) |
/apollo/external_command/free_space | apollo::external_command::FreeSpaceCommand | apollo::external_command::CommandStatus | 指定位姿停车命令(园区) |
/apollo/external_command/lane_follow | apollo::external_command::LaneFollowCommand | apollo::external_command::CommandStatus | 沿道路点对点行驶命令 |
/apollo/external_command/path_follow | apollo::external_command::PathFollowCommand | apollo::external_command::CommandStatus | 指定线路行驶命令(园区) |
/apollo/external_command/speed | apollo::external_command::SpeedCommand | apollo::external_command::CommandStatus | 更改速度命令(园区) |
/apollo/external_command/valet_parking | apollo::external_command::ValetParkingCommand | apollo::external_command::CommandStatus | 指定停车位泊车命令 |
输出
输入外部命令经过预处理,被转换成内部命令发送给planning,control或者canbus模块。被转换成的内部命令以cyber topic的形式发送,有如下几种:
Channel 名 | 类型 | 描述 |
---|---|---|
/apollo/planning/command | apollo::planning::PlanningCommand | 具有导航动作的外部命令转换成的内部命令,发送给planning模块 |
/apollo/routing_response | apollo::routing::RoutingResponse | 在高精地图上沿车道线点对点行驶的外部命令,预处理时生成的routing线路,用于HMI显示时使用 |
/apollo/planning/pad | apollo::planning::PadMessage | 外部命令ActionCommand转换成的内部命令,发送给planning模块 |
/apollo/control/pad | apollo::control::PadMessage | 外部命令ActionCommand转换成的内部命令,发送给control模块 |
/apollo/canbus/chassis_control | apollo::external_command::ChassisCommand | 外部命令ChassisCommand转换成的内部命令,发送给canbus模块 |
通过代码可以此处ExternalCommandProcessComponent
根据conf初始化创建了7个service,配合external_command_demo
客户端来使用.
namespace apollo {
namespace external_command {bool ExternalCommandProcessComponent::Init() {// Load the external command processors according to the config.ProcessComponentConfig config;if (!GetProtoConfig(&config)) {AERROR << "Unable to load ExternalCommandProcessComponent conf file: "<< ConfigFilePath();return false;}const auto& plugin_manager = cyber::plugin_manager::PluginManager::Instance();for (const auto& processor_class_name : config.processor()) {command_processors_.emplace_back(plugin_manager->CreateInstance<CommandProcessorBase>(processor_class_name));command_processors_.back()->Init(node_);}command_status_service_ =node_->CreateService<CommandStatusRequest, CommandStatus>(config.output_command_status_name(),[this](const std::shared_ptr<CommandStatusRequest>& request,std::shared_ptr<CommandStatus>& response) {bool is_get_status = false;// Get the command status from command processors.for (const auto& processor : command_processors_) {if (processor->GetCommandStatus(request->command_id(),response.get())) {is_get_status = true;break;}}if (!is_get_status) {response->set_status(CommandStatusType::UNKNOWN);response->set_message("Cannot get the status of command.");}});AINFO << "ExternalCommandProcessComponent init finished.";return true;
}} // namespace external_command
} // namespace apollo
external_command_demo(客户端)
syntax = "proto2";package apollo.external_command;import "modules/common_msgs/basic_msgs/header.proto";enum ActionCommandType {// Follow the current lane.FOLLOW = 1;// Change to the laft lane.CHANGE_LEFT = 2;// Change to the right lane.CHANGE_RIGHT = 3;// Pull over and stop driving.PULL_OVER = 4;// Stop driving smoothly in emergency case.STOP = 5;// Start driving after paused.START = 6;// Clear the input planning command to cancel planning.CLEAR_PLANNING = 7;// Switch to manual drive mode.SWITCH_TO_MANUAL = 50;// Switch to auto drive mode.SWITCH_TO_AUTO = 51;// Varify vin code of vehicle.VIN_REQ = 52;// Enter mission modelENTER_MISSION = 53;// Exit mission modelEXIT_MISSION = 54;
}message ActionCommand {optional apollo.common.Header header = 1;// Unique identification for command.optional int64 command_id = 2 [default = -1];// The action command.required ActionCommandType command = 3;
}
类型 | 描述 |
---|---|
pull_over | Follow the current lane. |
stop | Stop driving smoothly in emergency case. |
start | Start driving after paused. |
clear | Clear the input planning command to cancel planning. |
manual | Switch to manual drive mode. |
auto | Switch to auto drive mode. |
vin | Varify vin code of vehicle. |
enter_mission | Enter mission model |
exit_mission | Exit mission model |
插件ActionCommandProcessor
modules/external_command/command_processor/action_command_processor
插件的输出为外部操作指令执行后对应发布的channel信息(/apollo/planning/pad 或 /apollo/control/pad)和更新planning模块发布的命令执行状态(CommandStatus):
Channel 名称 | 类型 | 描述 |
---|---|---|
/apollo/planning/pad | apollo::planning::PadMessage | 改变planning场景行为的指令 |
/apollo/control/pad | apollo::control::PadMessage | 改变底盘驾驶模式的指令 |
/apollo/planning/command_status | apollo::external_command::CommandStatus | 更新planning模块发布的针对外部命令的执行状态 |
配置
文件路径 | 类型/结构 | 说明 |
---|---|---|
modules/external_command/command_processor/action_command_processor/conf/config.pb.txt | apollo::external_command::CommandProcessorConfig | 配置文件,外部操作命令处理器输入输出的channel或service名称等信息 |
modules/external_command/command_processor/action_command_processor/conf/special_config.pb.txt | apollo::external_command::ActionCommandConfig | 配置文件,外部操作命令处理器模块的配置 |
apollo/modules/external_command/command_processor/action_command_processor/action_command_processor.cc
bool ActionCommandProcessor::Init(const std::shared_ptr<cyber::Node>& node) {...// Create service for input command.command_service_ = node->CreateService<ActionCommand, CommandStatus>(config.input_command_name(),[this](const std::shared_ptr<ActionCommand>& command,std::shared_ptr<CommandStatus>& status) {this->OnCommand(command, status);});// Create writers for output command.CHECK_GT(config.output_command_name().size(), 1);auto message_writer = MessageWriter::Instance();planning_action_writer_ =message_writer->RegisterMessage<apollo::planning::PadMessage>(config.output_command_name().Get(0));control_action_writer_ =message_writer->RegisterMessage<apollo::control::PadMessage>(config.output_command_name().Get(1));// Create reader for input command status.
...return true;
}
void ActionCommandProcessor::OnCommand(const std::shared_ptr<ActionCommand>& command,std::shared_ptr<CommandStatus>& status) {...//switch (command->command()) {// Send "FOLLOW" message to planning.case external_command::ActionCommandType::FOLLOW: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::FOLLOW);planning_action_writer_->Write(planning_message);} break;// Send "CHANGE_LEFT" message to planning.case external_command::ActionCommandType::CHANGE_LEFT: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::CHANGE_LEFT);planning_action_writer_->Write(planning_message);} break;// Send "CHANGE_RIGHT" message to planning.case external_command::ActionCommandType::CHANGE_RIGHT: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::CHANGE_RIGHT);planning_action_writer_->Write(planning_message);} break;// Send "PULL_OVER" message to planning.case external_command::ActionCommandType::PULL_OVER: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::PULL_OVER);planning_action_writer_->Write(planning_message);} break;// Send "STOP" message to planning.case external_command::ActionCommandType::STOP: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::STOP);planning_action_writer_->Write(planning_message);} break;// Send "CLEAR_PLANNING" message to planning.case external_command::ActionCommandType::CLEAR_PLANNING: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::CLEAR_PLANNING);planning_action_writer_->Write(planning_message);status->set_status(CommandStatusType::FINISHED);} break;// Send "START" message to planning.case external_command::ActionCommandType::START: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::RESUME_CRUISE);planning_action_writer_->Write(planning_message);} break;// Send "SWITCH_TO_MANUAL" message to control.case external_command::ActionCommandType::SWITCH_TO_MANUAL: {// Use async function to wait for the chassis to be in manual mode.cyber::Async(&ActionCommandProcessor::SwitchToManualMode, this,module_name);} break;// Send "SWITCH_TO_AUTO" message to control.case external_command::ActionCommandType::SWITCH_TO_AUTO: {// Chassis need be switched to manual mode before switch to auto mode.// Use async function to wait for the chassis to be in auto mode.cyber::Async(&ActionCommandProcessor::SwitchToAutoMode, this,module_name);} break;// Send "ENTER_MISSION" message to planning.case external_command::ActionCommandType::ENTER_MISSION: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::ENTER_MISSION);planning_action_writer_->Write(planning_message);} break;// Send "EXIT_MISSION" message to planning.case external_command::ActionCommandType::EXIT_MISSION: {planning::PadMessage planning_message;common::util::FillHeader(module_name, &planning_message);planning_message.set_action(planning::PadMessage::EXIT_MISSION);planning_action_writer_->Write(planning_message);} break;... }
}