25#include "modules/common_msgs/planning_msgs/planning.pb.h"
26#include "modules/external_command/command_processor/command_processor_base/proto/command_processor_config.pb.h"
34namespace external_command {
40 message_reader_ = MessageReader::Instance();
44 std::string class_name =
45 abi::__cxa_demangle(
typeid(*this).name(),
nullptr,
nullptr, &status);
46 std::string special_config_path =
49 class_name,
"conf/special_config.pb.txt");
50 if (!cyber::common::LoadConfig<ActionCommandConfig>(special_config_path,
52 AERROR <<
"Cannot get special config of ActionCommandProcessor";
57 config.input_command_name(),
58 [
this](
const std::shared_ptr<ActionCommand>& command,
59 std::shared_ptr<CommandStatus>& status) {
60 this->OnCommand(command, status);
63 CHECK_GT(config.output_command_name().size(), 1);
64 auto message_writer = MessageWriter::Instance();
65 planning_action_writer_ =
67 config.output_command_name().Get(0));
68 control_action_writer_ =
70 config.output_command_name().Get(1));
72 CHECK_GT(config.input_command_status_name().size(), 2);
74 chassis_status_name_ = config.input_command_status_name().Get(0);
75 planning_status_name_ = config.input_command_status_name().Get(1);
76 planning_command_status_name_ = config.input_command_status_name().Get(2);
78 chassis_status_name_);
80 planning_status_name_);
82 planning_command_status_name_);
88 CHECK_NOTNULL(status);
89 if (
nullptr == last_command_) {
92 if (last_command_->command_id() != command_id) {
95 std::string module_name =
"UNKNOWN";
96 if (last_command_->has_header()) {
97 module_name = last_command_->header().module_name();
99 common::util::FillHeader(module_name, status);
100 status->set_command_id(command_id);
101 switch (last_command_->command()) {
108 status->set_message(
"Cannot execute the command!");
122 auto* latest_chassis_status =
124 chassis_status_name_);
125 if (
nullptr == latest_chassis_status) {
127 status->set_message(
"Cannot get chassis status!");
131 if (latest_chassis_status->speed_mps() >
159void ActionCommandProcessor::OnCommand(
160 const std::shared_ptr<ActionCommand>& command,
161 std::shared_ptr<CommandStatus>& status) {
162 std::string module_name =
"UNKNOWN";
163 if (command->has_header()) {
166 AINFO << std::setprecision(12) <<
"timestamp: " << timestamp <<
" "
167 <<
"request for " << command->header().timestamp_sec();
168 if (timestamp - command->header().timestamp_sec() > 2.0) {
169 AINFO <<
"request for " << command->header().module_name()
170 <<
" has been timeouted";
175 status->set_command_id(command->command_id());
176 switch (command->command()) {
179 planning::PadMessage planning_message;
180 common::util::FillHeader(module_name, &planning_message);
182 planning_action_writer_->Write(planning_message);
186 planning::PadMessage planning_message;
187 common::util::FillHeader(module_name, &planning_message);
189 planning_action_writer_->Write(planning_message);
193 planning::PadMessage planning_message;
194 common::util::FillHeader(module_name, &planning_message);
196 planning_action_writer_->Write(planning_message);
200 planning::PadMessage planning_message;
201 common::util::FillHeader(module_name, &planning_message);
203 planning_action_writer_->Write(planning_message);
207 planning::PadMessage planning_message;
208 common::util::FillHeader(module_name, &planning_message);
210 planning_action_writer_->Write(planning_message);
214 planning::PadMessage planning_message;
215 common::util::FillHeader(module_name, &planning_message);
217 planning_action_writer_->Write(planning_message);
222 planning::PadMessage planning_message;
223 common::util::FillHeader(module_name, &planning_message);
225 planning_action_writer_->Write(planning_message);
230 cyber::Async(&ActionCommandProcessor::SwitchToManualMode,
this,
237 cyber::Async(&ActionCommandProcessor::SwitchToAutoMode,
this,
242 planning::PadMessage planning_message;
243 common::util::FillHeader(module_name, &planning_message);
245 planning_action_writer_->Write(planning_message);
249 planning::PadMessage planning_message;
250 common::util::FillHeader(module_name, &planning_message);
252 planning_action_writer_->Write(planning_message);
256 control::PadMessage control_message;
257 common::util::FillHeader(module_name, &control_message);
259 control_action_writer_->Write(control_message);
264void ActionCommandProcessor::SwitchToAutoMode(
const std::string& module_name) {
265 last_mode_switch_status_.set_status(
268 auto* latest_chassis_status =
270 chassis_status_name_);
271 if (
nullptr == latest_chassis_status) {
272 UpdateModeSwitchStatus(
"Failed to get chassis data!",
true);
277 latest_chassis_status->driving_mode()) {
278 UpdateModeSwitchStatus(
"Chassis is already in auto mode.",
false);
284 UpdateModeSwitchStatus(
"Chassis cannot be switched to manual mode first!",
293void ActionCommandProcessor::SwitchToManualMode(
294 const std::string& module_name) {
295 last_mode_switch_status_.set_status(
301bool ActionCommandProcessor::SwitchMode(
304 const std::string& module_name) {
305 const std::string& mode_name =
306 canbus::Chassis::DrivingMode_Name(driving_mode);
308 auto* latest_chassis_status =
310 chassis_status_name_);
311 if (
nullptr == latest_chassis_status) {
312 UpdateModeSwitchStatus(
"Failed to get chassis data!",
true);
316 if (driving_mode == latest_chassis_status->driving_mode()) {
317 UpdateModeSwitchStatus(
"Chassis is already in " + mode_name,
false);
320 control::PadMessage control_message;
321 common::util::FillHeader(module_name, &control_message);
322 static constexpr int kMaxTries = 3;
323 static constexpr auto kTryInterval = std::chrono::milliseconds(500);
324 control_message.set_action(driving_action);
325 bool is_switch_success =
false;
326 for (
int i = 0; i < kMaxTries; ++i) {
328 control_action_writer_->Write(control_message);
329 std::this_thread::sleep_for(kTryInterval);
331 latest_chassis_status =
333 chassis_status_name_);
334 if (
nullptr == latest_chassis_status) {
335 UpdateModeSwitchStatus(
"Failed to get chassis data!",
true);
338 if (latest_chassis_status->driving_mode() == driving_mode) {
339 is_switch_success =
true;
343 if (!is_switch_success) {
344 UpdateModeSwitchStatus(
"Chassis cannot be switched to " + mode_name,
true);
350void ActionCommandProcessor::CheckScenarioFinished(
351 const std::string& scenario_name, CommandStatus* status)
const {
355 status->set_message(
"Cannot get planning scenario status!");
356 auto* latest_planning_status =
358 planning_status_name_);
359 if (
nullptr == latest_planning_status) {
361 status->set_message(
"Cannot get planning status!");
364 if (!latest_planning_status->has_debug() ||
365 latest_planning_status->debug().has_planning_data()) {
369 if (!debug.has_scenario()) {
372 const auto& scenario = debug.
scenario();
373 if (!scenario.has_scenario_plugin_type()) {
376 auto* latest_planning_command_status =
377 message_reader_->
GetMessage<CommandStatus>(planning_command_status_name_);
378 if (
nullptr == latest_planning_command_status) {
380 status->set_message(
"Cannot get planning command status!");
383 status->set_message(
"");
384 const auto& scenario_type = scenario.scenario_plugin_type();
385 if (scenario_type == scenario_name &&
386 latest_planning_command_status->status() ==
394void ActionCommandProcessor::CheckModeSwitchFinished(
396 CommandStatus* status)
const {
397 auto* latest_chassis_status =
399 chassis_status_name_);
400 if (
nullptr == latest_chassis_status) {
402 status->set_message(
"Cannot get chassis status!");
405 if (latest_chassis_status->has_driving_mode() &&
406 latest_chassis_status->driving_mode() == drive_mode) {
410 status->CopyFrom(last_mode_switch_status_);
413void ActionCommandProcessor::UpdateModeSwitchStatus(
const std::string& message,
416 last_mode_switch_status_.set_status(
419 last_mode_switch_status_.set_status(
422 last_mode_switch_status_.set_message(message);
static double NowInSeconds()
gets the current time in second.
std::string GetPluginConfPath(const std::string &class_name, const std::string &conf_name)
get plugin configuration file location
static PluginManager * Instance()
get singleton instance of PluginManager
bool Init(const std::shared_ptr< cyber::Node > &node) override
bool GetCommandStatus(int64_t command_id, CommandStatus *status) const override
Get the command status.
virtual bool Init(const std::shared_ptr< cyber::Node > &node)
const CommandProcessorConfig & GetProcessorConfig() const
void RegisterMessage(const std::string &channel_name)
Register the message reader with the given channel name.
const T * GetMessage(const std::string &channel_name) const
Get the message with the channel name.
Some string util functions.
required string pull_over_scenario_name
required string stop_scenario_name
required double minimun_non_zero_speed
optional apollo::common::Header header
optional apollo::planning_internal::Debug debug
optional PlanningData planning_data
optional ScenarioDebug scenario