【7】ExternalCommand

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"
c/s
call
/apollo/planning/pad
/apollo/control/pad
/apollo/planning/command
ExternalCommandProcessComponent
external_command_demo
ActionCommandProcessor
planning模块
control模块
LaneFollowCommandProcessor
FreeSpaceCommandProcessor _不开源
PathFollowCommandProcessor_不开源
other...
用户交互输入命令
other input
service 名Request类型Response类型描述
/apollo/external_command/actionapollo::external_command::ActionCommandapollo::external_command::CommandStatus流程干预命令,如暂停,启动,切换手动模式等
/apollo/external_command/chassisapollo::external_command::ChassisCommandapollo::external_command::CommandStatus自定义底盘命令(园区)
/apollo/external_command/free_spaceapollo::external_command::FreeSpaceCommandapollo::external_command::CommandStatus指定位姿停车命令(园区)
/apollo/external_command/lane_followapollo::external_command::LaneFollowCommandapollo::external_command::CommandStatus沿道路点对点行驶命令
/apollo/external_command/path_followapollo::external_command::PathFollowCommandapollo::external_command::CommandStatus指定线路行驶命令(园区)
/apollo/external_command/speedapollo::external_command::SpeedCommandapollo::external_command::CommandStatus更改速度命令(园区)
/apollo/external_command/valet_parkingapollo::external_command::ValetParkingCommandapollo::external_command::CommandStatus指定停车位泊车命令

输出

输入外部命令经过预处理,被转换成内部命令发送给planning,control或者canbus模块。被转换成的内部命令以cyber topic的形式发送,有如下几种:

Channel 名类型
描述
/apollo/planning/commandapollo::planning::PlanningCommand具有导航动作的外部命令转换成的内部命令,发送给planning模块
/apollo/routing_responseapollo::routing::RoutingResponse在高精地图上沿车道线点对点行驶的外部命令,预处理时生成的routing线路,用于HMI显示时使用
/apollo/planning/padapollo::planning::PadMessage外部命令ActionCommand转换成的内部命令,发送给planning模块
/apollo/control/padapollo::control::PadMessage外部命令ActionCommand转换成的内部命令,发送给control模块
/apollo/canbus/chassis_controlapollo::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_overFollow the current lane.
stopStop driving smoothly in emergency case.
startStart driving after paused.
clearClear the input planning command to cancel planning.
manualSwitch to manual drive mode.
autoSwitch to auto drive mode.
vinVarify vin code of vehicle.
enter_missionEnter mission model
exit_missionExit mission model

插件ActionCommandProcessor

modules/external_command/command_processor/action_command_processor

插件的输出为外部操作指令执行后对应发布的channel信息(/apollo/planning/pad 或 /apollo/control/pad)和更新planning模块发布的命令执行状态(CommandStatus):

Channel 名称类型
描述
/apollo/planning/padapollo::planning::PadMessage改变planning场景行为的指令
/apollo/control/padapollo::control::PadMessage改变底盘驾驶模式的指令
/apollo/planning/command_statusapollo::external_command::CommandStatus更新planning模块发布的针对外部命令的执行状态

配置

文件路径类型/结构说明
modules/external_command/command_processor/action_command_processor/conf/config.pb.txtapollo::external_command::CommandProcessorConfig配置文件,外部操作命令处理器输入输出的channel或service名称等信息
modules/external_command/command_processor/action_command_processor/conf/special_config.pb.txtapollo::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;
    
    ... 
     }
}
  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Visual Studio Code中配置Revit二次开发环境,你需要以下步骤: 1. 安装Revit软件:确保你已经安装了Revit软件,并且可以正常运行。 2. 安装Visual Studio Code:前往Visual Studio Code官网(https://code.visualstudio.com/)下载并安装最新版本的Visual Studio Code。 3. 安装Revit插件:在Visual Studio Code中,点击左侧的扩展图标,搜索并安装"Revit"插件。这个插件提供了Revit API的语法高亮、代码补全等功能。 4. 创建Revit项目:在Visual Studio Code中,通过点击"文件"->"新建文件夹",选择一个适当的位置并创建一个新的文件夹作为你的Revit项目。 5. 配置项目:在Visual Studio Code中,点击"文件"->"打开文件夹",选择上一步创建的文件夹。然后,在项目文件夹中创建一个名为".vscode"的隐藏文件夹,并在其中创建一个名为"launch.json"的文件。 6. 配置launch.json:在launch.json文件中,添加以下内容: ```json { "version": "0.2.0", "configurations": [ { "name": "Revit", "type": "clr", "request": "launch", "preLaunchTask": "build", "program": "${env:ProgramFiles}/Autodesk/Revit 20XX/Revit.exe", "args": [ "/language", "en-US", "/command", "pyRevitDevTools.ExternalCommand" ] } ] } ``` 请确保将`20XX`替换为你所使用的Revit版本的年份。 7. 创建任务:在Visual Studio Code中,点击"终端"->"运行任务"->"任务配置文件"->"新建任务配置文件"。在打开的tasks.json文件中,添加以下内容: ```json { "label": "build", "command": "pyRevit build" } ``` 8. 启动Revit插件:在Visual Studio Code中,点击"调试"->"开始调试",选择"Revit"配置。这将启动Revit软件,并加载Revit插件。 现在,你已经完成了Revit二次开发环境的配置,可以开始编写和调试你的Revit插件了。请记住,在编写代码之前,请先阅读Revit API的文档以了解API的用法和限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值