【7】ExternalCommand

news2025/1/15 6:48:04

文章目录

  • ExternalCommandProcessComponent(服务端)
    • 输入
    • 输出
  • external_command_demo(客户端)
  • 插件ActionCommandProcessor

c/s
call
/apollo/planning/pad
/apollo/control/pad
ExternalCommandProcessComponent
external_command_demo
ActionCommandProcessor
planning模块
control模块
other...
用户交互输入命令
other input

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/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;
    
    ... 
     }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1886106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode 插件开发经验小结

理解 vscode&#xff0c;我们首先要谈的是 Electron。 Electron 的核心技术主要包括以下几个方面&#xff1a; Chromium: Electron 使用了 Chromium 浏览器作为其渲染引擎。Chromium 是 Google Chrome 的开源版本&#xff0c;负责处理和渲染应用程序的用户界面&#xff0c;包括…

maketrans()方法——创建字符映射的转换表

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 maketrans()方法用于创建字符映射的转换表&#xff0c;对于接受两个参数的最简单的调用方式&#xff0c;第一个参数是字符串&#xff0c;表…

【Kubernetes】加入节点Node及问题

命令 分别再node节点机器上&#xff0c;执行如下命令&#xff1a; kubeadm join [master机器ip:端口] --token [master机器初始化生成的token] --discovery-token-ca-cent-hash [master机器初始化生成的hash]问题 由于清屏没有记住token和hash的时候&#xff1a; 1&#xff…

外贸企业选择什么网络?

随着全球化的深入发展&#xff0c;越来越多的国内企业将市场拓展到海外。为了确保外贸业务的顺利进行&#xff0c;企业需要建立一个稳定、安全且高速的网络。那么&#xff0c;外贸企业应该选择哪种网络呢&#xff1f;本文将为您详细介绍。 外贸企业应选择什么网络&#xff1f; …

axios的底层ajax,XMLHttpRequest原理解释及使用方法

定义 ajax全称asychronous JavaScript and XML 意思是异步的 JavaScript和xml&#xff0c; 也就是通过javascript创建XMLHttpRequest &#xff08;xhr&#xff09;对象与服务器进行通信 步骤 创建实例对象&#xff0c;初始请求方法和url&#xff0c;设置监听器监听请求完成…

【Rust入门教程】安装Rust

文章目录 前言Rust简介Rust的安装更新与卸载rust更新卸载 总结 前言 在当今的编程世界中&#xff0c;Rust语言以其独特的安全性和高效性吸引了大量开发者的关注。Rust是一种系统编程语言&#xff0c;专注于速度、内存安全和并行性。它具有现代化的特性&#xff0c;同时提供了低…

超简洁Django个人博客系统(适合初学者)

一、环境介绍 Django4.2.13Markdown3.3.4PyMySQL1.1.1Python3.8PyCharm 2023.1.2 (Professional Edition) 二、功能简介 用户登录 通过在pycharm终端执行以下命令创建超级管理员。python manage.py create createsuperuser 创建完成后再通过新建的超级管理员账号进行登录 …

The First项目报告:NvirWorld与区块链游戏的未来

根据官方公告&#xff0c;The Fisrt现货区将于2024年7月2日16:00上架NVIR/USDT交易对&#xff0c;NVIR是NvirWorld平台的原生代币。作为一个去中心化解决方案&#xff0c;NvirWorld为开发者提供了一个简化且适应性强的环境&#xff0c;旨在通过优化的扩展解决方案来降低交易成本…

windows USB设备驱动开发-开发USB 设备端驱动

USB 设备是通过单个端口连接到计算机的外设&#xff0c;例如鼠标设备和键盘。 USB 客户端驱动程序是计算机上安装的软件&#xff0c;该软件与硬件通信以使设备正常运行。 如果设备属于 Microsoft 支持的设备类&#xff0c;Windows 会为该设备加载 Microsoft 提供的 USB 驱动程序…

如何离线安装ctags

首先下载一个ctags源码包&#xff0c;ctags-master.zip&#xff0c;拷贝到ubuntu20中&#xff0c; #unzip ctags-master.zip 找到README文件&#xff0c;找到install的描述&#xff1a; 运行ctags解压后的目录下的autogen.sh 发现缺少autoreconf, autoconf, automake 等一些…

问题集锦1

01.inner中使用JwtTokenUtil.getUserCode() 前端调用上传&#xff08;java&#xff09;&#xff0c;上传使用加购 Overridepublic Boolean insertShoppingCart(InsertShoppingCartParamsDto dto) {// 通过userCode,itemCode和supplierCode来判断当前加购人添加到购物车的商品是…

iminuit,一个神奇的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个神奇的 Python 库 - iminuit。 Github地址&#xff1a;https://github.com/scikit-hep/iminuit 在科学计算和数据分析领域&#xff0c;参数估计和最优化是非常重要的任务。…

【Windows】Visual Studio Installer下载缓慢解决办法

【Windows】Visual Studio Installer下载缓慢解决办法 1.背景2.分析3.结果 1.背景 使用visual studio在线安装包进行IDE安装&#xff0c;发现下载几乎停滞&#xff0c;网速几乎为零。 经过排查并不是因为实际网络带宽导致。 这里涉及DNS知识&#xff1b; DNS&#xff08;Dom…

Python学习速成必备知识,(20道练习题)!

基础题练习 1、打印出1-100之间的所有偶数&#xff1a; for num in range(1, 101):if num % 2 0:print(num) 2、打印出用户输入的字符串的长度&#xff1a; string input("请输入一个字符串&#xff1a;")print("字符串的长度为&#xff1a;", len(str…

【第二周】基础语法学习

目录 前言初始化项目文件介绍基本介绍JSWXMLWXSS 常见组件基础组件视图容器match-mediamovable-area/viewpage-containerscroll-viewswiper 表单组件自定义组件 模板语法数据绑定单向数据绑定双向数据绑定 列表渲染条件渲染模板引用 事件系统事件类型事件绑定阻止冒泡互斥事件事…

8617 阶乘数字和

这是一个关于计算阶乘结果所有位上的数字之和的问题。我们可以通过以下步骤来解决这个问题&#xff1a; 1. 首先&#xff0c;我们需要一个函数来计算阶乘。由于n的范围可以达到50&#xff0c;阶乘的结果可能非常大&#xff0c;所以我们需要使用一个可以处理大整数的数据类型&a…

[Information Sciences 2023]用于假新闻检测的相似性感知多模态提示学习

推荐的一个视频&#xff1a;p-tuning P-tunning直接使用连续空间搜索 做法就是直接将在自然语言中存在的词直接替换成可以直接训练的输入向量。本身的Pretrained LLMs 可以Fine-Tuning也可以不做。 这篇论文也解释了为什么很少在其他领域结合知识图谱的原因&#xff1a;就是因…

理解MySQL核心技术:触发器功能特点与应用案例解析

触发器&#xff08;Trigger&#xff09;是MySQL中一个重要的功能&#xff0c;它能够在特定的数据表操作发生时自动执行预定义的SQL语句&#xff0c;从而实现在数据库层面的自动化操作和数据维护。在这篇文章中&#xff0c;我们将进一步了解MySQL触发器的相关知识&#xff0c;包…

渲染100农场如何渲染全景图?渲染100邀请码1a12

全景图的制作需要渲染&#xff0c;以国内知名的渲染农场—渲染100为例&#xff0c;我来说下操作过程。 1、进入渲染100官网&#xff0c;点击右上角注册按钮完成注册&#xff0c;记得邀请码一栏填1a12&#xff0c;有30元礼包和2张免费渲染券。 渲染100官网&#xff1a;http://…