Apollo 10.0
自动驾驶开放平台
external_command_wrapper_demo.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18#include <poll.h>
19
20#include <cctype>
21#include <algorithm>
22
23#include "modules/external_command/external_command_demo/proto/sweeper_custom_command.pb.h"
24
25#include "cyber/common/file.h"
27#include "cyber/time/clock.h"
28
30
32 : command_id_(0), module_name_("demo") {}
33
35 action_command_client_ = std::make_shared<apollo::common::ClientWrapper<
37 node_, "/apollo/external_command/action");
38 chassis_command_client_ = std::make_shared<apollo::common::ClientWrapper<
40 node_, "/apollo/external_command/chassis");
41 free_space_command_client_ = std::make_shared<apollo::common::ClientWrapper<
43 node_, "/apollo/external_command/free_space");
44 zone_cover_command_client_ = std::make_shared<apollo::common::ClientWrapper<
46 node_, "/apollo/external_command/zone_cover");
47 lane_follow_command_client_ = std::make_shared<apollo::common::ClientWrapper<
49 node_, "/apollo/external_command/lane_follow");
50 path_follow_command_client_ = std::make_shared<apollo::common::ClientWrapper<
52 node_, "/apollo/external_command/path_follow");
53 speed_command_client_ = std::make_shared<apollo::common::ClientWrapper<
55 node_, "/apollo/external_command/speed");
56 valet_parking_command_client_ =
57 std::make_shared<apollo::common::ClientWrapper<
59 node_, "/apollo/external_command/valet_parking");
60 status_client_ = std::make_shared<apollo::common::ClientWrapper<
62 node_, "/apollo/external_command/command_status");
64 "modules/external_command/external_command_demo/conf/"
65 "demo_config.pb.txt",
66 &demo_config_);
67 return true;
68}
69
71 int8_t revent = 0; // short
72 struct pollfd fd = {STDIN_FILENO, POLLIN, revent};
73 switch (poll(&fd, 1, 100)) {
74 case -1:
75 std::cout << "Failed to read keyboard" << std::endl;
76 return false;
77 case 0:
78 return true;
79 default:
80 char data[50];
81 std::cin.getline(data, 50);
82 std::string input_command_string = data;
83 if (input_command_string == "pull_over") {
84 // Pull over.
85 SendActionCommand(
87 } else if (input_command_string == "stop") {
88 // Stop planning.
90 } else if (input_command_string == "start") {
91 // Start planning.
93 } else if (input_command_string == "clear") {
94 // Start planning.
95 SendActionCommand(
97 } else if (input_command_string == "manual") {
98 // Switch manual mode.
99 SendActionCommand(
101 } else if (input_command_string == "auto") {
102 // Switch auto mode.
103 SendActionCommand(
105 } else if (input_command_string == "vin") {
106 // Send vin validation.
108 } else if (input_command_string == "enter_mission") {
109 // Enter mission model.
110 SendActionCommand(
112 } else if (input_command_string == "exit_mission") {
113 // Exit mission model.
114 SendActionCommand(
116 } else if (input_command_string == "chassis") {
117 SendVehicleSignalCommand();
118 } else if (input_command_string == "custom_chassis") {
119 SendCustomChassisCommand();
120 } else if (input_command_string.find("set_speed") != std::string::npos) {
121 auto index = input_command_string.find("set_speed");
122 std::string speed_value_string = input_command_string.substr(
123 index + std::string("set_speed").length(),
124 input_command_string.length());
125 if (!speed_value_string.empty()) {
126 double speed_value = std::atof(speed_value_string.c_str());
127 SendSpeedCommand(speed_value);
128 } else {
129 AWARN << "Input format is invalid, please input format like: "
130 "set_speed 1.5";
131 }
132 } else if (input_command_string == "increase_speed") {
133 double speed_factor = 1.2;
134 SendSpeedFactorCommand(speed_factor);
135 } else if (input_command_string == "decrease_speed") {
136 double speed_factor = 0.8;
137 SendSpeedFactorCommand(speed_factor);
138 } else if (input_command_string == "restore_speed") {
139 RestoreSpeed();
140 } else if (input_command_string == "lane") {
141 // Modify way point as needed.
143 way_point.set_x(0.0);
144 way_point.set_y(0.0);
145 way_point.set_heading(0.0);
146 std::vector<apollo::external_command::Pose> way_points;
147 way_points.emplace_back(way_point);
149 end_pose.set_x(10.0);
150 end_pose.set_y(0.0);
151 end_pose.set_heading(0.0);
152 SendLaneFollowCommand(way_points, end_pose,
153 demo_config_.target_speed());
154 } else if (input_command_string == "path_loc") {
155 SendPathFollowCommandWithLocationRecord(
157 } else if (input_command_string == "path_path") {
158 SendPathFollowCommandWithPathRecord(
160 } else if (input_command_string == "valet_parking") {
161 std::string parking_spot_id = "451089045";
162 SendValetParkingCommand(parking_spot_id, demo_config_.target_speed());
163 } else if (input_command_string.find("command_status") !=
164 std::string::npos) {
165 // Input command with format: command_status=XX, where XX is the
166 // command_id
167 const size_t start_pos = std::string("command_status=").length();
168 const size_t end_pos = input_command_string.length();
169 if (end_pos <= start_pos) {
170 std::cout
171 << "Please check command status with format: command_status=XX!"
172 << std::endl;
173 break;
174 }
175 std::string command_id_string =
176 input_command_string.substr(start_pos, end_pos);
177 command_id_string.erase(
178 std::remove_if(command_id_string.begin(), command_id_string.end(),
179 ::isspace),
180 command_id_string.end());
181 uint64_t id = std::atoi(command_id_string.c_str());
182 CheckCommandStatus(id);
183 } else if (input_command_string == "free1") {
185 end_pose.set_x(demo_config_.end_pose_x());
186 end_pose.set_y(demo_config_.end_pose_y());
187 end_pose.set_heading(demo_config_.end_pose_heading());
188 std::vector<apollo::external_command::Point> way_points;
193 point1.set_x(demo_config_.point1_x());
194 point1.set_y(demo_config_.point1_y());
195 point2.set_x(demo_config_.point2_x());
196 point2.set_y(demo_config_.point2_y());
197 point3.set_x(demo_config_.point3_x());
198 point3.set_y(demo_config_.point3_y());
199 point4.set_x(demo_config_.point4_x());
200 point4.set_y(demo_config_.point4_y());
201 way_points.emplace_back(point1);
202 way_points.emplace_back(point2);
203 way_points.emplace_back(point3);
204 way_points.emplace_back(point4);
205
206 SendFreespaceCommand(way_points, end_pose);
207 } else if (input_command_string == "zone_cover") {
208 std::string overlap_id = demo_config_.overlap_id();
209 SendZoneCoverCommand(overlap_id);
210 } else {
211 std::cout << "Invalid input!" << input_command_string << std::endl;
212 }
213 }
214 return true;
215}
216
217void ExternalCommandWrapperDemo::SendActionCommand(
219 auto command = std::make_shared<apollo::external_command::ActionCommand>();
220 FillCommandHeader(command);
221 command->set_command(action_command_type);
222 std::cout << "Sending action command: " << command->DebugString()
223 << std::endl;
224 auto response = action_command_client_->SendRequest(command);
225 if (nullptr == response) {
226 std::cout << "Command sending failed, please check the service is on!\n"
227 << std::endl;
228 } else {
229 std::cout << "******Finish sending command.******\n" << std::endl;
230 }
231}
232
233void ExternalCommandWrapperDemo::SendVehicleSignalCommand() {
234 // Send left turn signal.
235 auto command = std::make_shared<apollo::external_command::ChassisCommand>();
236 FillCommandHeader(command);
237 command->mutable_basic_signal()->set_turn_signal(
239 std::cout << "Sending chassis command: " << command->DebugString()
240 << std::endl;
241 auto response = chassis_command_client_->SendRequest(command);
242 if (nullptr == response) {
243 std::cout << "Command sending failed, please check the service is on!\n"
244 << std::endl;
245 } else {
246 std::cout << "******Finish sending command.******\n" << std::endl;
247 }
248}
249
250void ExternalCommandWrapperDemo::SendCustomChassisCommand() {
251 // Send left turn signal.
252 auto command = std::make_shared<apollo::external_command::ChassisCommand>();
253 FillCommandHeader(command);
254 // Set custom command.
255 auto custom_operation = command->mutable_custom_operation();
256 // Set custom command values.
258 sweeper_command.set_is_turn_on_brush(true);
259 sweeper_command.set_sweeping_speed(2.0);
260 custom_operation->PackFrom(sweeper_command);
261 std::cout << "Sending custom chassis command: " << command->DebugString()
262 << std::endl;
263 auto response = chassis_command_client_->SendRequest(command);
264 if (nullptr == response) {
265 std::cout << "Command sending failed, please check the service is on!\n"
266 << std::endl;
267 } else {
268 std::cout << "******Finish sending command.******\n" << std::endl;
269 }
270}
271
272void ExternalCommandWrapperDemo::SendPathFollowCommandWithPathRecord(
273 const std::string& record_path) {
274 // Read planning data from record file and use the planning path points
275 // as the path of PathFollowCommand.
276 apollo::planning::ADCTrajectory record_planning_data;
277 // Get the path points from record planning data.
278 std::shared_ptr<apollo::external_command::PathFollowCommand>
279 path_follow_command =
280 std::make_shared<apollo::external_command::PathFollowCommand>();
281 std::vector<apollo::external_command::Point> left_boundary_points,
282 right_boundary_points;
283
284 std::vector<std::string> record_files =
285 apollo::cyber::common::ListSubPaths(record_path, DT_REG);
286 std::sort(record_files.begin(), record_files.end());
287 std::string dir_prefix = record_path + '/';
288 for (const auto file_name : record_files) {
289 ReadPathFromPathRecord(dir_prefix + file_name,
290 path_follow_command->mutable_way_point(),
291 left_boundary_points, right_boundary_points);
292 }
293 // Set header and command id of PathFollowCommand.
294 FillCommandHeader(path_follow_command);
295 // Set path boundary of path.
296 if (left_boundary_points.size() == right_boundary_points.size() &&
297 right_boundary_points.size() == path_follow_command->way_point().size() &&
298 right_boundary_points.size() > 2) {
299 std::cout << "Get the left and right boundary Point!\n";
300 auto path_boundary = path_follow_command->mutable_path_boundary();
301 for (auto& left_boundary_point : left_boundary_points) {
302 auto left_boundary = path_boundary->add_left_boundary();
303 left_boundary->set_x(left_boundary_point.x());
304 left_boundary->set_y(left_boundary_point.y());
305 }
306 for (auto& right_boundary_point : right_boundary_points) {
307 auto right_boundary = path_boundary->add_right_boundary();
308 right_boundary->set_x(right_boundary_point.x());
309 right_boundary->set_y(right_boundary_point.y());
310 }
311 std::cout << "left_boundary size: " << path_boundary->left_boundary().size()
312 << ", right_boundary size"
313 << path_boundary->right_boundary().size()
314 << "reference size: " << path_follow_command->way_point().size();
315
316 } else {
317 std::cout << "Set the left and right boundary with width of config!\n";
318 auto path_boundary = path_follow_command->mutable_boundary_with_width();
319 path_boundary->set_left_path_width(demo_config_.left_path_width());
320 path_boundary->set_right_path_width(demo_config_.right_path_width());
321 }
322 // Set target speed.
323 path_follow_command->set_target_speed(demo_config_.target_speed());
324 auto response = path_follow_command_client_->SendRequest(path_follow_command);
325 if (nullptr == response) {
326 std::cout << "Command sending failed, please check the service is on!\n"
327 << std::endl;
328 } else {
329 std::cout << "******Finish sending command.******\n" << std::endl;
330 }
331}
332
333void ExternalCommandWrapperDemo::SendPathFollowCommandWithLocationRecord(
334 const std::string& record_dir) {
335 // Read planning data from record file and use the planning path points
336 // as the path of PathFollowCommand.
337 std::shared_ptr<apollo::external_command::PathFollowCommand>
338 path_follow_command =
339 std::make_shared<apollo::external_command::PathFollowCommand>();
340 std::vector<std::string> record_files =
341 apollo::cyber::common::ListSubPaths(record_dir, DT_REG);
342 std::sort(record_files.begin(), record_files.end());
343 std::string dir_prefix = record_dir + '/';
344 for (const auto file_name : record_files) {
345 ReadPathFromLocationRecord(dir_prefix + file_name,
346 path_follow_command->mutable_way_point());
347 }
348
349 // Set header and command id of PathFollowCommand.
350 FillCommandHeader(path_follow_command);
351 // Set path boundary of path.
352 auto path_boundary = path_follow_command->mutable_boundary_with_width();
353 path_boundary->set_left_path_width(demo_config_.left_path_width());
354 path_boundary->set_right_path_width(demo_config_.right_path_width());
355 // Set target speed.
356 path_follow_command->set_target_speed(demo_config_.target_speed());
357 auto response = path_follow_command_client_->SendRequest(path_follow_command);
358 if (nullptr == response) {
359 std::cout << "Command sending failed, please check the service is on!\n"
360 << std::endl;
361 } else {
362 std::cout << "******Finish sending command.******\n" << std::endl;
363 }
364}
365
366void ExternalCommandWrapperDemo::SendSpeedCommand(double speed) {
367 auto command = std::make_shared<apollo::external_command::SpeedCommand>();
368 FillCommandHeader(command);
369 command->set_target_speed(speed);
370 std::cout << "Sending speed command: " << command->DebugString() << std::endl;
371 auto response = speed_command_client_->SendRequest(command);
372 if (nullptr == response) {
373 std::cout << "Command sending failed, please check the service is on!\n"
374 << std::endl;
375 } else {
376 std::cout << "******Finish sending command.******\n" << std::endl;
377 }
378}
379
380void ExternalCommandWrapperDemo::SendSpeedFactorCommand(double speed_factor) {
381 auto command = std::make_shared<apollo::external_command::SpeedCommand>();
382 FillCommandHeader(command);
383 command->set_target_speed_factor(speed_factor);
384 std::cout << "Sending speed factor command: " << command->DebugString()
385 << std::endl;
386 auto response = speed_command_client_->SendRequest(command);
387 if (nullptr == response) {
388 std::cout << "Command sending failed, please check the service is on!\n"
389 << std::endl;
390 } else {
391 std::cout << "******Finish sending command.******\n" << std::endl;
392 }
393}
394
395void ExternalCommandWrapperDemo::RestoreSpeed() {
396 auto command = std::make_shared<apollo::external_command::SpeedCommand>();
397 FillCommandHeader(command);
398 command->set_is_restore_target_speed(true);
399 std::cout << "Restore speed: " << command->DebugString() << std::endl;
400 auto response = speed_command_client_->SendRequest(command);
401 if (nullptr == response) {
402 std::cout << "Command sending failed, please check the service is on!\n"
403 << std::endl;
404 } else {
405 std::cout << "******Finish sending command.******\n" << std::endl;
406 }
407}
408
409void ExternalCommandWrapperDemo::SendLaneFollowCommand(
410 const std::vector<apollo::external_command::Pose>& way_points,
411 const apollo::external_command::Pose& end, double target_speed) {
412 auto command =
413 std::make_shared<apollo::external_command::LaneFollowCommand>();
414 FillCommandHeader(command);
415 // Copy way_points
416 for (const auto& point : way_points) {
417 auto way_point = command->add_way_point();
418 way_point->CopyFrom(point);
419 }
420 // Copy end point
421 command->mutable_end_pose()->CopyFrom(end);
422 if (target_speed > 0.0) {
423 command->set_target_speed(target_speed);
424 }
425 std::cout << "Sending lane follow command: " << command->DebugString()
426 << std::endl;
427 auto response = lane_follow_command_client_->SendRequest(command);
428 if (nullptr == response) {
429 std::cout << "Command sending failed, please check the service is on!\n"
430 << std::endl;
431 } else {
432 std::cout << "******Finish sending command.******\n" << std::endl;
433 }
434}
435
436void ExternalCommandWrapperDemo::SendFreespaceCommand(
437 const std::vector<apollo::external_command::Point>& way_points,
439 auto command = std::make_shared<apollo::external_command::FreeSpaceCommand>();
440 FillCommandHeader(command);
441 // Copy way_points
442 auto roi_point = command->mutable_drivable_roi();
443 for (const auto& point : way_points) {
444 roi_point->add_point()->CopyFrom(point);
445 }
446 // Copy end point
447 command->mutable_parking_spot_pose()->CopyFrom(end);
448 std::cout << "Sending lane follow command: " << command->DebugString()
449 << std::endl;
450 auto response = free_space_command_client_->SendRequest(command);
451 if (nullptr == response) {
452 std::cout << "Command sending failed, please check the service is on!\n"
453 << std::endl;
454 } else {
455 std::cout << "******Finish sending command.******\n" << std::endl;
456 }
457}
458
459void ExternalCommandWrapperDemo::SendValetParkingCommand(
460 const std::string& parking_spot_id, double target_speed) {
461 auto command =
462 std::make_shared<apollo::external_command::ValetParkingCommand>();
463 FillCommandHeader(command);
464 command->set_parking_spot_id(parking_spot_id);
465 if (target_speed > 0.0) {
466 command->set_target_speed(target_speed);
467 }
468 std::cout << "Sending valet parking command: " << command->DebugString()
469 << std::endl;
470 auto response = valet_parking_command_client_->SendRequest(command);
471 if (nullptr == response) {
472 std::cout << "Command sending failed, please check the service is on!\n"
473 << std::endl;
474 } else {
475 std::cout << "******Finish sending command.******\n" << std::endl;
476 }
477}
478
479void ExternalCommandWrapperDemo::ReadPathFromPathRecord(
480 const std::string& record_file,
481 google::protobuf::RepeatedPtrField<apollo::external_command::Point>*
482 waypoints,
483 std::vector<apollo::external_command::Point>& left_boundary_points,
484 std::vector<apollo::external_command::Point>& right_boundary_points) {
485 std::cout << "ReadPathFromPathRecord: " << record_file << std::endl;
486 apollo::cyber::record::RecordReader reader(record_file);
487 if (!reader.IsValid()) {
488 std::cout << "Fail to open " << record_file << std::endl;
489 return;
490 }
491
492 apollo::planning::ADCTrajectory planning_trajectory;
494 double start_time = apollo::cyber::Clock::NowInSeconds();
495 double last_point_x = 0.0;
496 double last_point_y = 0.0;
497 // waypoints->Clear();
498 // left_boundary_points.clear();
499 // right_boundary_points.clear();
500 while (reader.ReadMessage(&message)) {
501 if (message.channel_name == "/apollo/planning") {
502 if (planning_trajectory.ParseFromString(message.content)) {
503 const auto& location_pose = planning_trajectory.location_pose();
504 if ((abs(last_point_x - location_pose.vehice_location().x()) >
505 demo_config_.min_distance_error() ||
506 abs(last_point_y - location_pose.vehice_location().y()) >
507 demo_config_.min_distance_error())) {
508 if (location_pose.has_left_lane_boundary_point() &&
509 location_pose.has_right_lane_boundary_point()) {
510 apollo::external_command::Point left_boundary_point,
511 right_boundary_point;
512 left_boundary_point.set_x(
513 location_pose.left_lane_boundary_point().x());
514 left_boundary_point.set_y(
515 location_pose.left_lane_boundary_point().y());
516 right_boundary_point.set_x(
517 location_pose.right_lane_boundary_point().x());
518 right_boundary_point.set_y(
519 location_pose.right_lane_boundary_point().y());
520 left_boundary_points.emplace_back(left_boundary_point);
521 right_boundary_points.emplace_back(right_boundary_point);
522 }
523
524 auto output_point = waypoints->Add();
525 output_point->set_x(location_pose.vehice_location().x());
526 output_point->set_y(location_pose.vehice_location().y());
527 last_point_x = location_pose.vehice_location().x();
528 last_point_y = location_pose.vehice_location().y();
529 }
530 }
531
532 } else {
533 std::cout << "Stop Parse message";
534 }
535 }
536 std::cout << "waypoints size: " << waypoints->size() << "\n";
537 std::cout << "Parse /apollo/planning message Time =: "
538 << (apollo::cyber::Clock::NowInSeconds() - start_time) * 1000
539 << "\n";
540}
541
542void ExternalCommandWrapperDemo::CheckCommandStatus(const uint64_t command_id) {
543 auto command =
544 std::make_shared<apollo::external_command::CommandStatusRequest>();
545 FillCommandHeader(command);
546 command->set_command_id(command_id);
547 std::cout << "Sending check command: " << command->DebugString() << std::endl;
548 auto response = status_client_->SendRequest(command);
549 if (nullptr == response) {
550 std::cout << "Check status failed!\n" << std::endl;
551 } else {
552 std::cout << response->DebugString();
553 std::cout << "******Finish checking command.******\n" << std::endl;
554 }
555}
556
557void ExternalCommandWrapperDemo::ReadPathFromLocationRecord(
558 const std::string& record_file,
559 google::protobuf::RepeatedPtrField<apollo::external_command::Point>*
560 waypoints) const {
561 std::cout << "ReadPathFromLocationRecord: " << record_file << std::endl;
562 apollo::cyber::record::RecordReader reader(record_file);
563 if (!reader.IsValid()) {
564 std::cout << "Fail to open " << record_file << std::endl;
565 return;
566 }
569 double last_x = 0.0;
570 double last_y = 0.0;
571 bool is_last_poistion_set = false;
572 while (reader.ReadMessage(&message)) {
573 if (message.channel_name == "/apollo/localization/pose") {
574 if (localization.ParseFromString(message.content)) {
575 const auto& position = localization.pose().position();
576 if (!is_last_poistion_set) {
577 last_x = position.x();
578 last_y = position.y();
579 is_last_poistion_set = true;
580 continue;
581 }
582 // Save the location to path with min_distance.
583 if (abs(last_x - position.x()) > demo_config_.min_distance_error() ||
584 abs(last_y - position.y()) > demo_config_.min_distance_error()) {
585 auto output_point = waypoints->Add();
586 output_point->set_x(position.x());
587 output_point->set_y(position.y());
588 last_x = position.x();
589 last_y = position.y();
590 }
591 }
592 }
593 }
594}
595
596void ExternalCommandWrapperDemo::SendZoneCoverCommand(
597 const std::string overlap_id) {
598 auto command = std::make_shared<apollo::external_command::ZoneCoverCommand>();
599 FillCommandHeader(command);
600 // Copy way_points
601 command->set_overlap_id(overlap_id);
602 std::cout << "Sending lane follow command: " << command->DebugString()
603 << std::endl;
604 auto response = zone_cover_command_client_->SendRequest(command);
605 if (nullptr == response) {
606 std::cout << "Command sending failed, please check the service is on!\n"
607 << std::endl;
608 } else {
609 std::cout << "******Finish sending command.******\n" << std::endl;
610 }
611}
bool Proc() override
The Proc logic of the component, which called by the CyberRT frame.
Wrapper of cyber::Client which sends a topic with service name when SendRequst is invoked.
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
std::shared_ptr< Node > node_
#define AWARN
Definition log.h:43
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
std::vector< std::string > ListSubPaths(const std::string &directory_path, const unsigned char d_type)
List sub-paths.
Definition file.cc:353
Basic data struct of record message.
std::string content
The content of the message.
std::string channel_name
The channel name of the message.
optional apollo::localization::Pose pose
optional apollo::common::PointENU position
Definition pose.proto:26
optional LocationPose location_pose