文章目录
- 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 model
  ENTER_MISSION = 53;
  // Exit mission model
  EXIT_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;
    
    ... 
     }
}
                















![[Information Sciences 2023]用于假新闻检测的相似性感知多模态提示学习](https://img-blog.csdnimg.cn/direct/0149dc1e13d84f81b8943b0fdd492d9c.png)


