Apollo 11.0
自动驾驶开放平台
simulation_world_service.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 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
19#include <unordered_set>
20
21#include "absl/strings/str_split.h"
22#include "google/protobuf/util/json_util.h"
23
24#include "modules/common_msgs/basic_msgs/geometry.pb.h"
25#include "modules/common_msgs/basic_msgs/vehicle_signal.pb.h"
26#include "modules/common_msgs/chassis_msgs/chassis.pb.h"
27#include "modules/common_msgs/dreamview_msgs/simulation_world.pb.h"
28
29#include "cyber/common/file.h"
30#include "cyber/time/clock.h"
38
39namespace apollo {
40namespace dreamview {
41
54using apollo::common::util::FillHeader;
75using apollo::planning::DecisionResult;
76using apollo::planning::StopReasonCode;
88
89using Json = nlohmann::json;
90using ::google::protobuf::util::MessageToJsonString;
91
92// Angle threshold is about 5.72 degree.
93static constexpr double kAngleThreshold = 0.1;
94
95namespace {
96// Adapt to 1.0 records
97std::map<int, std::string> ScenarioType = {
98 {0, "LANE_FOLLOW"}, // Default scenario
99 {2, "BARE_INTERSECTION_UNPROTECTED"},
100 {3, "STOP_SIGN_PROTECTED"},
101 {4, "TRAFFIC_LIGHT_PROTECTED"},
102 {5, "TRAFFIC_LIGHT_PROTECTED"},
103 {6, "TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN"},
104 {7, "TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN"},
105 {8, "YIELD_SIGN"},
106 {9, "PULL_OVER"},
107 {10, "VALET_PARKING"},
108 {11, "EMERGENCY_PULL_OVER"},
109 {12, "EMERGENCY_STOP"},
110 {13, "NARROW_STREET_U_TURN"},
111 {14, "PARK_AND_GO"},
112 {15, "LEARNING_MODEL_SAMPLE"},
113 {16, "DEADEND_TURNAROUND"}};
114
115std::map<int, std::string> StageType = {
116 {0, "NO_STAGE"},
117 {1, "LANE_FOLLOW_DEFAULT_STAGE"},
118 {200, "BARE_INTERSECTION_UNPROTECTED_APPROACH"},
119 {201, "BARE_INTERSECTION_UNPROTECTED_INTERSECTION_CRUISE"},
120 {300, "STOP_SIGN_UNPROTECTED_PRE_STOP"},
121 {301, "STOP_SIGN_UNPROTECTED_STOP"},
122 {302, "STOP_SIGN_UNPROTECTED_CREEP"},
123 {303, "STOP_SIGN_UNPROTECTED_INTERSECTION_CRUISE"},
124 {400, "TRAFFIC_LIGHT_PROTECTED_APPROACH"},
125 {401, "TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE"},
126 {410, "TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN_APPROACH"},
127 {411, "TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN_CREEP"},
128 {412, "TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN_INTERSECTION_CRUISE"},
129 {420, "TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN_STOP"},
130 {421, "TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN_CREEP"},
131 {422, "TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN_INTERSECTION_CRUISE"},
132 {500, "PULL_OVER_APPROACH"},
133 {501, "PULL_OVER_RETRY_APPROACH_PARKING"},
134 {502, "PULL_OVER_RETRY_PARKING"},
135 {600, "EMERGENCY_PULL_OVER_SLOW_DOWN"},
136 {601, "EMERGENCY_PULL_OVER_APPROACH"},
137 {602, "EMERGENCY_PULL_OVER_STANDBY"},
138 {610, "EMERGENCY_STOP_APPROACH"},
139 {611, "EMERGENCY_STOP_STANDBY"},
140 {700, "VALET_PARKING_APPROACHING_PARKING_SPOT"},
141 {701, "VALET_PARKING_PARKING"},
142 {1100, "DEADEND_TURNAROUND_APPROACHING_TURNING_POINT"},
143 {1101, "DEADEND_TURNAROUND_TURNING"},
144 {800, "PARK_AND_GO_CHECK"},
145 {801, "PARK_AND_GO_CRUISE"},
146 {802, "PARK_AND_GO_ADJUST"},
147 {803, "PARK_AND_GO_PRE_CRUISE"},
148 {900, "YIELD_SIGN_APPROACH"},
149 {901, "YIELD_SIGN_CREEP"},
150 {1000, "LEARNING_MODEL_RUN"}};
151
152double CalculateAcceleration(
153 const Point3D &acceleration, const Point3D &velocity,
154 const apollo::canbus::Chassis_GearPosition &gear_location) {
155 // Calculates the dot product of acceleration and velocity. The sign
156 // of this projection indicates whether this is acceleration or
157 // deceleration.
158 double projection =
159 acceleration.x() * velocity.x() + acceleration.y() * velocity.y();
160
161 // Calculates the magnitude of the acceleration. Negate the value if
162 // it is indeed a deceleration.
163 double magnitude = std::hypot(acceleration.x(), acceleration.y());
164 if (std::signbit(projection)) {
165 magnitude = -magnitude;
166 }
167
168 // Negate the value if gear is reverse
169 if (gear_location == Chassis::GEAR_REVERSE) {
170 magnitude = -magnitude;
171 }
172
173 return magnitude;
174}
175
176Object::DisengageType DeduceDisengageType(const Chassis &chassis) {
177 if (chassis.error_code() != Chassis::NO_ERROR) {
179 }
180
181 switch (chassis.driving_mode()) {
192 default:
194 }
195}
196
197void SetObstacleType(const PerceptionObstacle::Type obstacle_type,
198 const PerceptionObstacle::SubType obstacle_subtype,
199 Object *world_object) {
200 if (world_object == nullptr) {
201 return;
202 }
203
204 switch (obstacle_type) {
206 world_object->set_type(Object_Type_UNKNOWN);
207 break;
209 world_object->set_type(Object_Type_UNKNOWN_MOVABLE);
210 break;
212 world_object->set_type(Object_Type_UNKNOWN_UNMOVABLE);
213 break;
215 world_object->set_type(Object_Type_PEDESTRIAN);
216 break;
218 world_object->set_type(Object_Type_BICYCLE);
219 break;
221 world_object->set_type(Object_Type_VEHICLE);
222 break;
223 default:
224 world_object->set_type(Object_Type_VIRTUAL);
225 }
226
227 world_object->set_sub_type(obstacle_subtype);
228}
229
230void SetStopReason(const StopReasonCode &reason_code, Decision *decision) {
231 switch (reason_code) {
232 case StopReasonCode::STOP_REASON_HEAD_VEHICLE:
233 decision->set_stopreason(Decision::STOP_REASON_HEAD_VEHICLE);
234 break;
235 case StopReasonCode::STOP_REASON_DESTINATION:
236 decision->set_stopreason(Decision::STOP_REASON_DESTINATION);
237 break;
238 case StopReasonCode::STOP_REASON_PEDESTRIAN:
239 decision->set_stopreason(Decision::STOP_REASON_PEDESTRIAN);
240 break;
241 case StopReasonCode::STOP_REASON_OBSTACLE:
242 decision->set_stopreason(Decision::STOP_REASON_OBSTACLE);
243 break;
244 case StopReasonCode::STOP_REASON_SIGNAL:
245 decision->set_stopreason(Decision::STOP_REASON_SIGNAL);
246 break;
247 case StopReasonCode::STOP_REASON_STOP_SIGN:
248 decision->set_stopreason(Decision::STOP_REASON_STOP_SIGN);
249 break;
250 case StopReasonCode::STOP_REASON_YIELD_SIGN:
251 decision->set_stopreason(Decision::STOP_REASON_YIELD_SIGN);
252 break;
253 case StopReasonCode::STOP_REASON_CLEAR_ZONE:
254 decision->set_stopreason(Decision::STOP_REASON_CLEAR_ZONE);
255 break;
256 case StopReasonCode::STOP_REASON_CROSSWALK:
257 decision->set_stopreason(Decision::STOP_REASON_CROSSWALK);
258 break;
259 case StopReasonCode::STOP_REASON_PULL_OVER:
260 decision->set_stopreason(Decision::STOP_REASON_PULL_OVER);
261 break;
262 default:
263 AWARN << "Unrecognizable stop reason code:" << reason_code;
264 }
265}
266
267void UpdateTurnSignal(const apollo::common::VehicleSignal &signal,
268 Object *auto_driving_car) {
270 auto_driving_car->set_current_signal("LEFT");
271 } else if (signal.turn_signal() ==
273 auto_driving_car->set_current_signal("RIGHT");
274 } else if (signal.emergency_light()) {
275 auto_driving_car->set_current_signal("EMERGENCY");
276 } else {
277 auto_driving_car->set_current_signal("");
278 }
279}
280
281void DownsampleCurve(Curve *curve) {
282 if (curve->segment().empty()) {
283 return;
284 }
285
286 auto *line_segment = curve->mutable_segment(0)->mutable_line_segment();
287 std::vector<PointENU> points(line_segment->point().begin(),
288 line_segment->point().end());
289 line_segment->clear_point();
290
291 // Downsample points by angle then by distance.
292 std::vector<size_t> sampled_indices =
293 DownsampleByAngle(points, kAngleThreshold);
294 for (const size_t index : sampled_indices) {
295 *line_segment->add_point() = points[index];
296 }
297}
298
299inline double SecToMs(const double sec) { return sec * 1000.0; }
300
301} // namespace
302
304bool SimulationWorldService::to_clear_ = false;
305SimulationWorldService::SimulationWorldService(const MapService *map_service,
306 bool routing_from_file)
307 : node_(cyber::CreateNode("simulation_world")),
308 map_service_(map_service),
309 monitor_logger_buffer_(MonitorMessageItem::SIMULATOR),
310 ready_to_push_(false) {
311 InitReaders();
312 InitWriters();
313
314 if (routing_from_file) {
315 ReadPlanningCommandFromFile(FLAGS_routing_response_file);
316 }
317
318 // Populate vehicle parameters.
319 Object *auto_driving_car = world_.mutable_auto_driving_car();
320 const auto &vehicle_param = VehicleConfigHelper::GetConfig().vehicle_param();
321 auto_driving_car->set_height(vehicle_param.height());
322 auto_driving_car->set_width(vehicle_param.width());
323 auto_driving_car->set_length(vehicle_param.length());
324}
325
326void SimulationWorldService::InitReaders() {
327 planning_command_reader_ =
328 node_->CreateReader<PlanningCommand>(FLAGS_planning_command);
329 chassis_reader_ = node_->CreateReader<Chassis>(FLAGS_chassis_topic);
330 gps_reader_ = node_->CreateReader<Gps>(FLAGS_gps_topic);
331 localization_reader_ =
332 node_->CreateReader<LocalizationEstimate>(FLAGS_localization_topic);
333 perception_obstacle_reader_ =
334 node_->CreateReader<PerceptionObstacles>(FLAGS_perception_obstacle_topic);
335 perception_traffic_light_reader_ = node_->CreateReader<TrafficLightDetection>(
336 FLAGS_traffic_light_detection_topic);
337 prediction_obstacle_reader_ =
338 node_->CreateReader<PredictionObstacles>(FLAGS_prediction_topic);
339 planning_reader_ =
340 node_->CreateReader<ADCTrajectory>(FLAGS_planning_trajectory_topic);
341 control_command_reader_ =
342 node_->CreateReader<ControlCommand>(FLAGS_control_command_topic);
343 navigation_reader_ =
344 node_->CreateReader<NavigationInfo>(FLAGS_navigation_topic);
345 relative_map_reader_ = node_->CreateReader<MapMsg>(FLAGS_relative_map_topic);
346 storytelling_reader_ = node_->CreateReader<Stories>(FLAGS_storytelling_topic);
347 audio_detection_reader_ =
348 node_->CreateReader<AudioDetection>(FLAGS_audio_detection_topic);
349
350 audio_event_reader_ = node_->CreateReader<AudioEvent>(
351 FLAGS_audio_event_topic,
352 [this](const std::shared_ptr<AudioEvent> &audio_event) {
353 this->PublishMonitorMessage(
354 MonitorMessageItem::WARN,
355 apollo::audio::AudioType_Name(audio_event->audio_type()));
356 });
357 drive_event_reader_ = node_->CreateReader<DriveEvent>(
358 FLAGS_drive_event_topic,
359 [this](const std::shared_ptr<DriveEvent> &drive_event) {
360 this->PublishMonitorMessage(MonitorMessageItem::WARN,
361 drive_event->event());
362 });
363 cyber::ReaderConfig monitor_message_reader_config;
364 monitor_message_reader_config.channel_name = FLAGS_monitor_topic;
365 monitor_message_reader_config.pending_queue_size =
366 FLAGS_monitor_msg_pending_queue_size;
367 monitor_reader_ = node_->CreateReader<MonitorMessage>(
368 monitor_message_reader_config,
369 [this](const std::shared_ptr<MonitorMessage> &monitor_message) {
370 std::unique_lock<std::mutex> lock(monitor_msgs_mutex_);
371 monitor_msgs_.push_back(monitor_message);
372 });
373 task_reader_ = node_->CreateReader<Task>(FLAGS_task_topic);
374}
375
376void SimulationWorldService::InitWriters() {
377 navigation_writer_ =
378 node_->CreateWriter<NavigationInfo>(FLAGS_navigation_topic);
379 lane_follow_command_client_ =
380 node_->CreateClient<LaneFollowCommand, CommandStatus>(
381 FLAGS_lane_follow_command_topic);
382 valet_parking_command_client_ =
383 node_->CreateClient<ValetParkingCommand, CommandStatus>(
384 FLAGS_valet_parking_command_topic);
385 action_command_client_ =
386 node_->CreateClient<ActionCommand, CommandStatus>(
387 FLAGS_action_command_topic);
388 routing_response_writer_ =
389 node_->CreateWriter<RoutingResponse>("/apollo/routing_response");
390 task_writer_ = node_->CreateWriter<Task>(FLAGS_task_topic);
391}
392
393void SimulationWorldService::Update() {
394 if (to_clear_) {
395 // Clears received data.
396 node_->ClearData();
397
398 // Clears simulation world except for the car information.
399 auto car = world_.auto_driving_car();
400 world_.Clear();
401 *world_.mutable_auto_driving_car() = car;
402
403 {
404 boost::unique_lock<boost::shared_mutex> writer_lock(route_paths_mutex_);
405 route_paths_.clear();
406 }
407
408 to_clear_ = false;
409 }
410
411 node_->Observe();
412
413 UpdateMonitorMessages();
414
415 UpdateVehicleParam();
416
417 UpdateWithLatestObserved(planning_command_reader_.get(), false);
418 UpdateWithLatestObserved(chassis_reader_.get());
419 UpdateWithLatestObserved(gps_reader_.get());
420 UpdateWithLatestObserved(localization_reader_.get());
421
422 // Clear objects received from last frame and populate with the new objects.
423 // TODO(siyangy, unacao): For now we are assembling the simulation_world with
424 // latest received perception, prediction and planning message. However, they
425 // may not always be perfectly aligned and belong to the same frame.
426 obj_map_.clear();
427 world_.clear_object();
428 world_.clear_sensor_measurements();
429 UpdateWithLatestObserved(audio_detection_reader_.get());
430 UpdateWithLatestObserved(storytelling_reader_.get());
431 UpdateWithLatestObserved(perception_obstacle_reader_.get());
432 UpdateWithLatestObserved(perception_traffic_light_reader_.get(), false);
433 UpdateWithLatestObserved(prediction_obstacle_reader_.get());
434 UpdateWithLatestObserved(planning_reader_.get());
435 UpdateWithLatestObserved(control_command_reader_.get());
436 UpdateWithLatestObserved(navigation_reader_.get(), FLAGS_use_navigation_mode);
437 UpdateWithLatestObserved(relative_map_reader_.get(),
438 FLAGS_use_navigation_mode);
439
440 for (const auto &kv : obj_map_) {
441 *world_.add_object() = kv.second;
442 }
443
444 UpdateDelays();
445 UpdateLatencies();
446
447 world_.set_sequence_num(world_.sequence_num() + 1);
448 world_.set_timestamp(Clock::Now().ToSecond() * 1000);
449}
450
451void SimulationWorldService::UpdateDelays() {
452 auto *delays = world_.mutable_delay();
453 delays->set_chassis(SecToMs(chassis_reader_->GetDelaySec()));
454 delays->set_localization(SecToMs(localization_reader_->GetDelaySec()));
455 delays->set_perception_obstacle(
456 SecToMs(perception_obstacle_reader_->GetDelaySec()));
457 delays->set_planning(SecToMs(planning_reader_->GetDelaySec()));
458 delays->set_prediction(SecToMs(prediction_obstacle_reader_->GetDelaySec()));
459 delays->set_traffic_light(
460 SecToMs(perception_traffic_light_reader_->GetDelaySec()));
461 delays->set_control(SecToMs(control_command_reader_->GetDelaySec()));
462}
463
464void SimulationWorldService::UpdateLatencies() {
465 UpdateLatency("chassis", chassis_reader_.get());
466 UpdateLatency("localization", localization_reader_.get());
467 UpdateLatency("perception", perception_obstacle_reader_.get());
468 UpdateLatency("planning", planning_reader_.get());
469 UpdateLatency("prediction", prediction_obstacle_reader_.get());
470 UpdateLatency("control", control_command_reader_.get());
471}
472
473void SimulationWorldService::GetWireFormatString(
474 double radius, std::string *sim_world_with_planning_data) {
475 PopulateMapInfo(radius);
476
477 world_.SerializeToString(sim_world_with_planning_data);
478}
479
480Json SimulationWorldService::GetUpdateAsJson(double radius) const {
481 std::string sim_world_json_string;
482 MessageToJsonString(world_, &sim_world_json_string);
483
484 Json update;
485 update["type"] = "SimWorldUpdate";
486 update["timestamp"] = Clock::Now().ToSecond() * 1000;
487 update["world"] = sim_world_json_string;
488
489 return update;
490}
491
492void SimulationWorldService::GetMapElementIds(double radius,
493 MapElementIds *ids) const {
494 // Gather required map element ids based on current location.
496 const auto &adc = world_.auto_driving_car();
497 point.set_x(adc.position_x());
498 point.set_y(adc.position_y());
499 map_service_->CollectMapElementIds(point, radius, ids);
500}
501
502void SimulationWorldService::PopulateMapInfo(double radius) {
503 world_.clear_map_element_ids();
504 GetMapElementIds(radius, world_.mutable_map_element_ids());
505 world_.set_map_hash(map_service_->CalculateMapHash(world_.map_element_ids()));
506 world_.set_map_radius(radius);
507}
508
509const Map &SimulationWorldService::GetRelativeMap() const {
510 return relative_map_;
511}
512
513template <>
514void SimulationWorldService::UpdateSimulationWorld(
515 const LocalizationEstimate &localization) {
516 Object *auto_driving_car = world_.mutable_auto_driving_car();
517 const auto &pose = localization.pose();
518
519 // Updates position with the input localization message.
520 auto_driving_car->set_position_x(pose.position().x() +
521 map_service_->GetXOffset());
522 auto_driving_car->set_position_y(pose.position().y() +
523 map_service_->GetYOffset());
524 auto_driving_car->set_heading(pose.heading());
525
526 // Updates acceleration with the input localization message.
527 auto_driving_car->set_speed_acceleration(CalculateAcceleration(
528 pose.linear_acceleration(), pose.linear_velocity(), gear_location_));
529
530 // Updates the timestamp with the timestamp inside the localization
531 // message header. It is done on both the SimulationWorld object
532 // itself and its auto_driving_car() field.
533 auto_driving_car->set_timestamp_sec(localization.header().timestamp_sec());
534 ready_to_push_.store(true);
535}
536
537template <>
538void SimulationWorldService::UpdateSimulationWorld(const Gps &gps) {
539 if (gps.header().module_name() == "ShadowLocalization") {
540 Object *shadow_localization_position = world_.mutable_shadow_localization();
541 const auto &pose = gps.localization();
542 shadow_localization_position->set_position_x(pose.position().x() +
543 map_service_->GetXOffset());
544 shadow_localization_position->set_position_y(pose.position().y() +
545 map_service_->GetYOffset());
546 shadow_localization_position->set_heading(pose.heading());
547 } else {
548 Object *gps_position = world_.mutable_gps();
549 gps_position->set_timestamp_sec(gps.header().timestamp_sec());
550
551 const auto &pose = gps.localization();
552 gps_position->set_position_x(pose.position().x() +
553 map_service_->GetXOffset());
554 gps_position->set_position_y(pose.position().y() +
555 map_service_->GetYOffset());
556
558 pose.orientation().qw(), pose.orientation().qx(),
559 pose.orientation().qy(), pose.orientation().qz());
560 gps_position->set_heading(heading);
561 }
562}
563
564template <>
565void SimulationWorldService::UpdateSimulationWorld(const Chassis &chassis) {
566 const auto &vehicle_param = VehicleConfigHelper::GetConfig().vehicle_param();
567 Object *auto_driving_car = world_.mutable_auto_driving_car();
568
569 double speed = chassis.speed_mps();
570 gear_location_ = chassis.gear_location();
571 if (gear_location_ == Chassis::GEAR_REVERSE) {
572 speed = -speed;
573 }
574 auto_driving_car->set_speed(speed);
575 auto_driving_car->set_throttle_percentage(chassis.throttle_percentage());
576 auto_driving_car->set_brake_percentage(chassis.brake_percentage());
577
578 // In case of out-of-range percentages, reduces it to zero.
579 double angle_percentage = chassis.steering_percentage();
580 if (angle_percentage > 100 || angle_percentage < -100) {
581 angle_percentage = 0;
582 }
583 auto_driving_car->set_steering_percentage(angle_percentage);
584
585 double steering_angle =
586 angle_percentage / 100.0 * vehicle_param.max_steer_angle();
587 auto_driving_car->set_steering_angle(steering_angle);
588
589 double kappa = std::tan(steering_angle / vehicle_param.steer_ratio()) /
590 vehicle_param.wheel_base();
591 auto_driving_car->set_kappa(kappa);
592
593 UpdateTurnSignal(chassis.signal(), auto_driving_car);
594
595 auto_driving_car->set_disengage_type(DeduceDisengageType(chassis));
596
597 auto_driving_car->set_battery_percentage(chassis.battery_soc_percentage());
598 auto_driving_car->set_gear_location(chassis.gear_location());
599}
600
601template <>
602void SimulationWorldService::UpdateSimulationWorld(const Stories &stories) {
603 world_.clear_stories();
604 auto *world_stories = world_.mutable_stories();
605
606 const google::protobuf::Descriptor *descriptor = stories.GetDescriptor();
607 const google::protobuf::Reflection *reflection = stories.GetReflection();
608 const int field_count = descriptor->field_count();
609 for (int i = 0; i < field_count; ++i) {
610 const google::protobuf::FieldDescriptor *field = descriptor->field(i);
611 if (field->name() != "header") {
612 (*world_stories)[field->name()] = reflection->HasField(stories, field);
613 }
614 }
615}
616
617template <>
618void SimulationWorldService::UpdateSimulationWorld(
619 const AudioDetection &audio_detection) {
620 world_.set_is_siren_on(audio_detection.is_siren());
621}
622
623Object &SimulationWorldService::CreateWorldObjectIfAbsent(
624 const PerceptionObstacle &obstacle) {
625 const std::string id = std::to_string(obstacle.id());
626 // Create a new world object and put it into object map if the id does not
627 // exist in the map yet.
628 if (!apollo::common::util::ContainsKey(obj_map_, id)) {
629 Object &world_obj = obj_map_[id];
630 SetObstacleInfo(obstacle, &world_obj);
631 SetObstaclePolygon(obstacle, &world_obj);
632 SetObstacleType(obstacle.type(), obstacle.sub_type(), &world_obj);
633 SetObstacleSensorMeasurements(obstacle, &world_obj);
634 SetObstacleSource(obstacle, &world_obj);
635 }
636 return obj_map_[id];
637}
638
639void SimulationWorldService::CreateWorldObjectFromSensorMeasurement(
640 const SensorMeasurement &sensor, Object *world_object) {
641 world_object->set_id(std::to_string(sensor.id()));
642 world_object->set_position_x(sensor.position().x());
643 world_object->set_position_y(sensor.position().y());
644 world_object->set_heading(sensor.theta());
645 world_object->set_length(sensor.length());
646 world_object->set_width(sensor.width());
647 world_object->set_height(sensor.height());
648 SetObstacleType(sensor.type(), sensor.sub_type(), world_object);
649}
650
651void SimulationWorldService::SetObstacleInfo(const PerceptionObstacle &obstacle,
652 Object *world_object) {
653 if (world_object == nullptr) {
654 return;
655 }
656
657 world_object->set_id(std::to_string(obstacle.id()));
658 world_object->set_position_x(obstacle.position().x() +
659 map_service_->GetXOffset());
660 world_object->set_position_y(obstacle.position().y() +
661 map_service_->GetYOffset());
662 world_object->set_heading(obstacle.theta());
663 world_object->set_length(obstacle.length());
664 world_object->set_width(obstacle.width());
665 world_object->set_height(obstacle.height());
666 world_object->set_speed(
667 std::hypot(obstacle.velocity().x(), obstacle.velocity().y()));
668 world_object->set_speed_heading(
669 std::atan2(obstacle.velocity().y(), obstacle.velocity().x()));
670 world_object->set_timestamp_sec(obstacle.timestamp());
671 world_object->set_confidence(obstacle.has_confidence() ? obstacle.confidence()
672 : 1);
673}
674
675void SimulationWorldService::SetObstaclePolygon(
676 const PerceptionObstacle &obstacle, Object *world_object) {
677 if (world_object == nullptr) {
678 return;
679 }
680
682 std::unordered_set<std::pair<double, double>, PairHash> seen_points;
683 world_object->clear_polygon_point();
684 for (const auto &point : obstacle.polygon_point()) {
685 // Filter out duplicate xy pairs.
686 std::pair<double, double> xy_pair = {point.x(), point.y()};
687 if (seen_points.count(xy_pair) == 0) {
688 PolygonPoint *poly_pt = world_object->add_polygon_point();
689 poly_pt->set_x(point.x() + map_service_->GetXOffset());
690 poly_pt->set_y(point.y() + map_service_->GetYOffset());
691 seen_points.insert(xy_pair);
692 }
693 }
694}
695
696void SimulationWorldService::SetObstacleSensorMeasurements(
697 const PerceptionObstacle &obstacle, Object *world_object) {
698 if (world_object == nullptr) {
699 return;
700 }
701 for (const auto &sensor : obstacle.measurements()) {
702 Object *obj = (*(world_.mutable_sensor_measurements()))[sensor.sensor_id()]
703 .add_sensor_measurement();
704 CreateWorldObjectFromSensorMeasurement(sensor, obj);
705 }
706}
707
708void SimulationWorldService::SetObstacleSource(
710 Object *world_object) {
711 if (world_object == nullptr || !obstacle.has_source()) {
712 return;
713 }
714 const PerceptionObstacle::Source obstacle_source = obstacle.source();
715 world_object->set_source(obstacle_source);
716 world_object->clear_v2x_info();
717 if (obstacle_source == PerceptionObstacle::V2X && obstacle.has_v2x_info()) {
718 world_object->mutable_v2x_info()->CopyFrom(obstacle.v2x_info());
719 }
720 return;
721}
722
723template <>
724void SimulationWorldService::UpdateSimulationWorld(
725 const PerceptionObstacles &obstacles) {
726 for (const auto &obstacle : obstacles.perception_obstacle()) {
727 auto &world_obj = CreateWorldObjectIfAbsent(obstacle);
728 if (obstacles.has_cipv_info() &&
729 (obstacles.cipv_info().cipv_id() == obstacle.id())) {
730 world_obj.set_type(Object_Type_CIPV);
731 }
732 }
733
734 if (obstacles.has_lane_marker()) {
735 world_.mutable_lane_marker()->CopyFrom(obstacles.lane_marker());
736 }
737}
738
739template <>
740void SimulationWorldService::UpdateSimulationWorld(
741 const TrafficLightDetection &traffic_light_detection) {
742 world_.clear_perceived_signal();
743 for (const auto &traffic_light : traffic_light_detection.traffic_light()) {
744 Object *signal = world_.add_perceived_signal();
745 signal->set_id(traffic_light.id());
746 signal->set_current_signal(TrafficLight_Color_Name(traffic_light.color()));
747 }
748}
749
750void SimulationWorldService::UpdatePlanningTrajectory(
751 const ADCTrajectory &trajectory) {
752 // Collect trajectory
753 world_.clear_planning_trajectory();
754 const double base_time = trajectory.header().timestamp_sec();
755 for (const TrajectoryPoint &point : trajectory.trajectory_point()) {
756 Object *trajectory_point = world_.add_planning_trajectory();
757 trajectory_point->set_timestamp_sec(point.relative_time() + base_time);
758 trajectory_point->set_position_x(point.path_point().x() +
759 map_service_->GetXOffset());
760 trajectory_point->set_position_y(point.path_point().y() +
761 map_service_->GetYOffset());
762 trajectory_point->set_speed(point.v());
763 trajectory_point->set_speed_acceleration(point.a());
764 trajectory_point->set_kappa(point.path_point().kappa());
765 trajectory_point->set_dkappa(point.path_point().dkappa());
766 trajectory_point->set_heading(point.path_point().theta());
767 }
768
769 // Update engage advice.
770 // This is a temporary solution, the advice will come from monitor later
771 if (trajectory.has_engage_advice()) {
772 world_.set_engage_advice(
773 EngageAdvice_Advice_Name(trajectory.engage_advice().advice()));
774 }
775}
776
777std::string formatDoubleToString(const double data) {
778 std::stringstream ss;
779 ss << std::fixed << std::setprecision(2) << data;
780 return ss.str();
781}
782
783void SimulationWorldService::UpdateRSSInfo(const ADCTrajectory &trajectory) {
784 if (trajectory.has_rss_info()) {
785 if (trajectory.rss_info().is_rss_safe()) {
786 if (!world_.is_rss_safe()) {
787 this->PublishMonitorMessage(MonitorMessageItem::INFO, "RSS safe.");
788 world_.set_is_rss_safe(true);
789 }
790 } else {
791 const double next_real_dist = trajectory.rss_info().cur_dist_lon();
792 const double next_rss_safe_dist =
793 trajectory.rss_info().rss_safe_dist_lon();
794 // Not update RSS message if data keeps same.
795 if (std::fabs(current_real_dist_ - next_real_dist) <
796 common::math::kMathEpsilon &&
797 std::fabs(current_rss_safe_dist_ - next_rss_safe_dist) <
798 common::math::kMathEpsilon) {
799 return;
800 }
801 this->PublishMonitorMessage(
802 MonitorMessageItem::ERROR,
803 "RSS unsafe: \ncurrent distance: " +
804 formatDoubleToString(trajectory.rss_info().cur_dist_lon()) +
805 "\nsafe distance: " +
806 formatDoubleToString(trajectory.rss_info().rss_safe_dist_lon()));
807 world_.set_is_rss_safe(false);
808 current_real_dist_ = next_real_dist;
809 current_rss_safe_dist_ = next_rss_safe_dist;
810 }
811 }
812}
813
814void SimulationWorldService::UpdateMainStopDecision(
815 const apollo::planning::MainDecision &main_decision,
816 double update_timestamp_sec, Object *world_main_decision) {
818 double stop_heading = 0.0;
819 auto decision = world_main_decision->add_decision();
820 decision->set_type(Decision::STOP);
821 if (main_decision.has_not_ready()) {
822 // The car is not ready!
823 // Use the current ADC pose since it is better not to self-drive.
824 stop_pt.set_x(world_.auto_driving_car().position_x());
825 stop_pt.set_y(world_.auto_driving_car().position_y());
826 stop_heading = world_.auto_driving_car().heading();
827 decision->set_stopreason(Decision::STOP_REASON_NOT_READY);
828 } else if (main_decision.has_estop()) {
829 // Emergency stop.
830 // Use the current ADC pose since it is better to stop immediately.
831 stop_pt.set_x(world_.auto_driving_car().position_x());
832 stop_pt.set_y(world_.auto_driving_car().position_y());
833 stop_heading = world_.auto_driving_car().heading();
834 decision->set_stopreason(Decision::STOP_REASON_EMERGENCY);
835 world_.mutable_auto_driving_car()->set_current_signal("EMERGENCY");
836 } else {
837 // Normal stop.
838 const apollo::planning::MainStop &stop = main_decision.stop();
839 stop_pt.set_x(stop.stop_point().x() + map_service_->GetXOffset());
840 stop_pt.set_y(stop.stop_point().y() + map_service_->GetYOffset());
841 stop_heading = stop.stop_heading();
842 if (stop.has_reason_code()) {
843 SetStopReason(stop.reason_code(), decision);
844 }
845 }
846
847 decision->set_position_x(stop_pt.x());
848 decision->set_position_y(stop_pt.y());
849 decision->set_heading(stop_heading);
850}
851
852bool SimulationWorldService::LocateMarker(
853 const apollo::planning::ObjectDecisionType &decision,
854 Decision *world_decision) {
855 apollo::common::PointENU fence_point;
856 double heading;
857 if (decision.has_stop() && decision.stop().has_stop_point()) {
858 world_decision->set_type(Decision_Type_STOP);
859 fence_point = decision.stop().stop_point();
860 heading = decision.stop().stop_heading();
861 } else if (decision.has_follow() && decision.follow().has_fence_point()) {
862 world_decision->set_type(Decision_Type_FOLLOW);
863 fence_point = decision.follow().fence_point();
864 heading = decision.follow().fence_heading();
865 } else if (decision.has_yield() && decision.yield().has_fence_point()) {
866 world_decision->set_type(Decision_Type_YIELD);
867 fence_point = decision.yield().fence_point();
868 heading = decision.yield().fence_heading();
869 } else if (decision.has_overtake() && decision.overtake().has_fence_point()) {
870 world_decision->set_type(Decision_Type_OVERTAKE);
871 fence_point = decision.overtake().fence_point();
872 heading = decision.overtake().fence_heading();
873 } else {
874 return false;
875 }
876
877 world_decision->set_position_x(fence_point.x() + map_service_->GetXOffset());
878 world_decision->set_position_y(fence_point.y() + map_service_->GetYOffset());
879 world_decision->set_heading(heading);
880 return true;
881}
882
883void SimulationWorldService::FindNudgeRegion(
884 const apollo::planning::ObjectDecisionType &decision,
885 const Object &world_obj, Decision *world_decision) {
886 std::vector<apollo::common::math::Vec2d> points;
887 for (auto &polygon_pt : world_obj.polygon_point()) {
888 points.emplace_back(polygon_pt.x(), polygon_pt.y());
889 }
890 const apollo::common::math::Polygon2d obj_polygon(points);
891 const apollo::common::math::Polygon2d &nudge_polygon =
892 obj_polygon.ExpandByDistance(std::fabs(decision.nudge().distance_l()));
893 const std::vector<apollo::common::math::Vec2d> &nudge_points =
894 nudge_polygon.points();
895 for (auto &nudge_pt : nudge_points) {
896 PolygonPoint *poly_pt = world_decision->add_polygon_point();
897 poly_pt->set_x(nudge_pt.x());
898 poly_pt->set_y(nudge_pt.y());
899 }
900 world_decision->set_type(Decision_Type_NUDGE);
901}
902
903void SimulationWorldService::UpdateDecision(const DecisionResult &decision_res,
904 double header_time) {
905 // Update turn signal.
906 UpdateTurnSignal(decision_res.vehicle_signal(),
907 world_.mutable_auto_driving_car());
908
909 const auto &main_decision = decision_res.main_decision();
910
911 // Update speed limit.
912 if (main_decision.target_lane_size() > 0) {
913 world_.set_speed_limit(main_decision.target_lane(0).speed_limit());
914 }
915
916 // Update relevant main stop with reason and change lane.
917 world_.clear_main_decision();
918 Object *world_main_decision = world_.mutable_main_decision();
919 if (main_decision.has_not_ready() || main_decision.has_estop() ||
920 main_decision.has_stop()) {
921 UpdateMainStopDecision(main_decision, header_time, world_main_decision);
922 }
923 if (main_decision.has_stop()) {
924 UpdateMainChangeLaneDecision(main_decision.stop(), world_main_decision);
925 } else if (main_decision.has_cruise()) {
926 UpdateMainChangeLaneDecision(main_decision.cruise(), world_main_decision);
927 }
928 if (world_main_decision->decision_size() > 0) {
929 // set default position
930 const auto &adc = world_.auto_driving_car();
931 world_main_decision->set_position_x(adc.position_x());
932 world_main_decision->set_position_y(adc.position_y());
933 world_main_decision->set_heading(adc.heading());
934 world_main_decision->set_timestamp_sec(header_time);
935 }
936
937 // Update obstacle decision.
938 for (const auto &obj_decision : decision_res.object_decision().decision()) {
939 if (obj_decision.has_perception_id()) {
940 int id = obj_decision.perception_id();
941 Object &world_obj = obj_map_[std::to_string(id)];
942 if (!world_obj.has_type()) {
943 world_obj.set_type(Object_Type_VIRTUAL);
944 ADEBUG << id << " is not a current perception object";
945 }
946
947 for (const auto &decision : obj_decision.object_decision()) {
948 Decision *world_decision = world_obj.add_decision();
949 world_decision->set_type(Decision_Type_IGNORE);
950 if (decision.has_stop() || decision.has_follow() ||
951 decision.has_yield() || decision.has_overtake()) {
952 if (!LocateMarker(decision, world_decision)) {
953 AWARN << "No decision marker position found for object id=" << id;
954 continue;
955 }
956 if (decision.has_stop()) {
957 // flag yielded obstacles
958 for (auto obstacle_id : decision.stop().wait_for_obstacle()) {
959 const std::vector<std::string> id_segments =
960 absl::StrSplit(obstacle_id, '_');
961 if (id_segments.size() > 0) {
962 obj_map_[id_segments[0]].set_yielded_obstacle(true);
963 }
964 }
965 }
966 } else if (decision.has_nudge()) {
967 if (world_obj.polygon_point().empty()) {
968 if (world_obj.type() == Object_Type_VIRTUAL) {
969 AWARN << "No current perception object with id=" << id
970 << " for nudge decision";
971 } else {
972 AWARN << "No polygon points found for object id=" << id;
973 }
974 continue;
975 }
976 FindNudgeRegion(decision, world_obj, world_decision);
977 }
978 }
979
980 world_obj.set_timestamp_sec(
981 std::max(world_obj.timestamp_sec(), header_time));
982 }
983 }
984}
985
986void SimulationWorldService::DownsamplePath(const common::Path &path,
987 common::Path *downsampled_path) {
988 auto sampled_indices = DownsampleByAngle(path.path_point(), kAngleThreshold);
989
990 downsampled_path->set_name(path.name());
991 for (const size_t index : sampled_indices) {
992 *downsampled_path->add_path_point() =
993 path.path_point(static_cast<int>(index));
994 }
995}
996
997void SimulationWorldService::UpdatePlanningData(const PlanningData &data) {
998 auto *planning_data = world_.mutable_planning_data();
999
1000 size_t max_interval = 10;
1001
1002 // Update scenario
1003 if (data.has_scenario()) {
1004 planning_data->mutable_scenario()->CopyFrom(data.scenario());
1005
1006 // Adapt to 1.0 records
1007 if (!data.scenario().has_scenario_plugin_type()) {
1008 planning_data->mutable_scenario()->set_scenario_plugin_type(
1009 ScenarioType[planning_data->scenario().scenario_type()]);
1010 planning_data->mutable_scenario()->set_stage_plugin_type(
1011 StageType[planning_data->scenario().stage_type()]);
1012 }
1013 }
1014
1015 // Update init point
1016 if (data.has_init_point()) {
1017 auto &planning_path_point = data.init_point().path_point();
1018 auto *world_obj_path_point =
1019 planning_data->mutable_init_point()->mutable_path_point();
1020 world_obj_path_point->set_x(planning_path_point.x() +
1021 map_service_->GetXOffset());
1022 world_obj_path_point->set_y(planning_path_point.y() +
1023 map_service_->GetYOffset());
1024 world_obj_path_point->set_theta(planning_path_point.theta());
1025 }
1026
1027 // Update Chart
1028 planning_data->mutable_chart()->CopyFrom(data.chart());
1029
1030 // Update SL Frame
1031 planning_data->mutable_sl_frame()->CopyFrom(data.sl_frame());
1032
1033 // Update DP path
1034 if (data.has_dp_poly_graph()) {
1035 planning_data->mutable_dp_poly_graph()->CopyFrom(data.dp_poly_graph());
1036 }
1037
1038 // Update ST Graph
1039 planning_data->clear_st_graph();
1040 for (auto &graph : data.st_graph()) {
1041 auto *st_graph = planning_data->add_st_graph();
1042 st_graph->set_name(graph.name());
1043 st_graph->mutable_boundary()->CopyFrom(graph.boundary());
1044 if (graph.has_kernel_cruise_ref()) {
1045 st_graph->mutable_kernel_cruise_ref()->CopyFrom(
1046 graph.kernel_cruise_ref());
1047 }
1048 if (graph.has_kernel_follow_ref()) {
1049 st_graph->mutable_kernel_follow_ref()->CopyFrom(
1050 graph.kernel_follow_ref());
1051 }
1052 if (graph.has_speed_constraint()) {
1053 st_graph->mutable_speed_constraint()->CopyFrom(graph.speed_constraint());
1054 }
1055
1056 // downsample speed_profile and speed_limit
1057 // The x-axis range is always [-10, 200], downsample to ~200 points but skip
1058 // max 10 points
1059 size_t profile_downsample_interval =
1060 std::max(1, (graph.speed_profile_size() / 200));
1061 profile_downsample_interval =
1062 std::min(profile_downsample_interval, max_interval);
1063 DownsampleSpeedPointsByInterval(graph.speed_profile(),
1064 profile_downsample_interval,
1065 st_graph->mutable_speed_profile());
1066
1067 size_t limit_downsample_interval =
1068 std::max(1, (graph.speed_limit_size() / 200));
1069 limit_downsample_interval =
1070 std::min(limit_downsample_interval, max_interval);
1071 DownsampleSpeedPointsByInterval(graph.speed_limit(),
1072 limit_downsample_interval,
1073 st_graph->mutable_speed_limit());
1074 }
1075
1076 // Update Speed Plan
1077 planning_data->clear_speed_plan();
1078 for (auto &plan : data.speed_plan()) {
1079 if (plan.speed_point_size() > 0) {
1080 auto *downsampled_plan = planning_data->add_speed_plan();
1081 downsampled_plan->set_name(plan.name());
1082
1083 // Downsample the speed plan for frontend display.
1084 // The x-axis range is always [-2, 10], downsample to ~80 points
1085 size_t interval = std::max(1, (plan.speed_point_size() / 80));
1086 interval = std::min(interval, max_interval);
1087 DownsampleSpeedPointsByInterval(plan.speed_point(), interval,
1088 downsampled_plan->mutable_speed_point());
1089 }
1090 }
1091
1092 // Update path
1093 planning_data->clear_path();
1094 for (auto &path : data.path()) {
1095 DownsamplePath(path, planning_data->add_path());
1096 }
1097
1098 // Update pull over status
1099 planning_data->clear_pull_over();
1100 if (data.has_pull_over()) {
1101 planning_data->mutable_pull_over()->CopyFrom(data.pull_over());
1102 }
1103
1104 // Update planning signal
1105 world_.clear_traffic_signal();
1106 if (data.has_signal_light() && data.signal_light().signal_size() > 0) {
1107 TrafficLight::Color current_signal = TrafficLight::UNKNOWN;
1108 int green_light_count = 0;
1109
1110 for (auto &signal : data.signal_light().signal()) {
1111 switch (signal.color()) {
1112 case TrafficLight::RED:
1113 case TrafficLight::YELLOW:
1114 case TrafficLight::BLACK:
1115 current_signal = signal.color();
1116 break;
1117 case TrafficLight::GREEN:
1118 green_light_count++;
1119 break;
1120 default:
1121 break;
1122 }
1123 }
1124
1125 if (green_light_count == data.signal_light().signal_size()) {
1126 current_signal = TrafficLight::GREEN;
1127 }
1128
1129 world_.mutable_traffic_signal()->set_current_signal(
1130 TrafficLight_Color_Name(current_signal));
1131 }
1132}
1133
1134template <>
1135void SimulationWorldService::UpdateSimulationWorld(
1136 const ADCTrajectory &trajectory) {
1137 const double header_time = trajectory.header().timestamp_sec();
1138
1139 UpdatePlanningTrajectory(trajectory);
1140
1141 UpdateRSSInfo(trajectory);
1142
1143 UpdateDecision(trajectory.decision(), header_time);
1144
1145 UpdatePlanningData(trajectory.debug().planning_data());
1146
1147 Latency latency;
1148 latency.set_timestamp_sec(header_time);
1149 latency.set_total_time_ms(trajectory.latency_stats().total_time_ms());
1150 (*world_.mutable_latency())["planning"] = latency;
1151}
1152
1153void SimulationWorldService::CreatePredictionTrajectory(
1154 const PredictionObstacle &obstacle, Object *world_object) {
1155 for (const auto &traj : obstacle.trajectory()) {
1156 Prediction *prediction = world_object->add_prediction();
1157 prediction->set_probability(traj.probability());
1158
1159 std::vector<PathPoint> points;
1160 for (const auto &point : traj.trajectory_point()) {
1161 points.push_back(point.path_point());
1162 }
1163 auto sampled_indices = DownsampleByAngle(points, kAngleThreshold);
1164
1165 for (auto index : sampled_indices) {
1166 const auto &point = points[index];
1167 PolygonPoint *world_point = prediction->add_predicted_trajectory();
1168 world_point->set_x(point.x() + map_service_->GetXOffset());
1169 world_point->set_y(point.y() + map_service_->GetYOffset());
1170
1171 const TrajectoryPoint &traj_point = traj.trajectory_point(index);
1172 if (traj_point.has_gaussian_info()) {
1173 const apollo::common::GaussianInfo &gaussian =
1174 traj_point.gaussian_info();
1175
1176 auto *ellipse = world_point->mutable_gaussian_info();
1177 ellipse->set_ellipse_a(gaussian.ellipse_a());
1178 ellipse->set_ellipse_b(gaussian.ellipse_b());
1179 ellipse->set_theta_a(gaussian.theta_a());
1180 }
1181 }
1182 }
1183}
1184
1185template <>
1186void SimulationWorldService::UpdateSimulationWorld(
1187 const PredictionObstacles &obstacles) {
1188 for (const auto &obstacle : obstacles.prediction_obstacle()) {
1189 // Note: There's a perfect one-to-one mapping between the perception
1190 // obstacles and prediction obstacles within the same frame. Creating a new
1191 // world object here is only possible when we happen to be processing a
1192 // perception and prediction message from two frames.
1193 auto &world_obj = CreateWorldObjectIfAbsent(obstacle.perception_obstacle());
1194
1195 // Add prediction trajectory to the object.
1196 CreatePredictionTrajectory(obstacle, &world_obj);
1197
1198 // Add prediction priority
1199 if (obstacle.has_priority()) {
1200 world_obj.mutable_obstacle_priority()->CopyFrom(obstacle.priority());
1201 }
1202
1203 // Add prediction interactive tag
1204 if (obstacle.has_interactive_tag()) {
1205 world_obj.mutable_interactive_tag()->CopyFrom(obstacle.interactive_tag());
1206 }
1207
1208 world_obj.set_timestamp_sec(
1209 std::max(obstacle.timestamp(), world_obj.timestamp_sec()));
1210 }
1211}
1212
1213template <>
1214void SimulationWorldService::UpdateSimulationWorld(
1215 const PlanningCommand &planning_command) {
1216 auto routing_response = planning_command.lane_follow_command();
1217 {
1218 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1219 if (world_.has_routing_time() &&
1220 world_.routing_time() == planning_command.header().timestamp_sec()) {
1221 // This routing response has been processed.
1222 return;
1223 }
1224 }
1225
1226 std::vector<Path> paths;
1227 if (!map_service_->GetPathsFromRouting(routing_response, &paths)) {
1228 return;
1229 }
1230
1231 world_.clear_route_path();
1232
1233 std::vector<RoutePath> route_paths;
1234 for (const Path &path : paths) {
1235 // Downsample the path points for frontend display.
1236 auto sampled_indices =
1237 DownsampleByAngle(path.path_points(), kAngleThreshold);
1238
1239 route_paths.emplace_back();
1240 RoutePath *route_path = &route_paths.back();
1241 for (const size_t index : sampled_indices) {
1242 const auto &path_point = path.path_points()[index];
1243 PolygonPoint *route_point = route_path->add_point();
1244 route_point->set_x(path_point.x() + map_service_->GetXOffset());
1245 route_point->set_y(path_point.y() + map_service_->GetYOffset());
1246 }
1247
1248 // Populate route path
1249 if (FLAGS_sim_world_with_routing_path) {
1250 auto *new_path = world_.add_route_path();
1251 *new_path = *route_path;
1252 }
1253 }
1254 {
1255 boost::unique_lock<boost::shared_mutex> writer_lock(route_paths_mutex_);
1256 std::swap(route_paths, route_paths_);
1257 world_.set_routing_time(planning_command.header().timestamp_sec());
1258 }
1259}
1260
1261Json SimulationWorldService::GetRoutePathAsJson() const {
1262 Json response;
1263 response["routePath"] = Json::array();
1264 std::vector<RoutePath> route_paths;
1265 {
1266 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1267 response["routingTime"] = world_.routing_time();
1268 route_paths = route_paths_;
1269 }
1270 for (const auto &route_path : route_paths) {
1271 Json path;
1272 path["point"] = Json::array();
1273 for (const auto &route_point : route_path.point()) {
1274 path["point"].push_back({{"x", route_point.x()},
1275 {"y", route_point.y()},
1276 {"z", route_point.z()}});
1277 }
1278 response["routePath"].push_back(path);
1279 }
1280 return response;
1281}
1282
1283void SimulationWorldService::ReadPlanningCommandFromFile(
1284 const std::string &planning_command_file) {
1285 auto planning_command = std::make_shared<PlanningCommand>();
1286 if (!GetProtoFromFile(planning_command_file, planning_command.get())) {
1287 AWARN << "Unable to read planning command from file: "
1288 << planning_command_file;
1289 return;
1290 }
1291 AINFO << "Loaded planning command from " << planning_command_file;
1292
1293 sleep(1); // Wait to make sure the connection has been established before
1294 // publishing.
1295
1296 auto planning_command_writer =
1297 node_->CreateWriter<PlanningCommand>(FLAGS_planning_command);
1298 planning_command_writer->Write(planning_command);
1299 AINFO << "Published PlanningCommand read from file.";
1300}
1301
1302template <>
1303void SimulationWorldService::UpdateSimulationWorld(
1304 const ControlCommand &control_command) {
1305 auto *control_data = world_.mutable_control_data();
1306 const double header_time = control_command.header().timestamp_sec();
1307 control_data->set_timestamp_sec(header_time);
1308
1309 Latency latency;
1310 latency.set_timestamp_sec(header_time);
1311 latency.set_total_time_ms(control_command.latency_stats().total_time_ms());
1312 (*world_.mutable_latency())["control"] = latency;
1313
1314 if (control_command.has_debug()) {
1315 auto &debug = control_command.debug();
1316 if (debug.has_simple_lon_debug() && debug.has_simple_lat_debug()) {
1317 auto &simple_lon = debug.simple_lon_debug();
1318 if (simple_lon.has_station_error()) {
1319 control_data->set_station_error(simple_lon.station_error());
1320 }
1321 auto &simple_lat = debug.simple_lat_debug();
1322 if (simple_lat.has_heading_error()) {
1323 control_data->set_heading_error(simple_lat.heading_error());
1324 }
1325 if (simple_lat.has_lateral_error()) {
1326 control_data->set_lateral_error(simple_lat.lateral_error());
1327 }
1328 if (simple_lat.has_current_target_point()) {
1329 control_data->mutable_current_target_point()->CopyFrom(
1330 simple_lat.current_target_point());
1331 }
1332 } else if (debug.has_simple_mpc_debug()) {
1333 auto &simple_mpc = debug.simple_mpc_debug();
1334 if (simple_mpc.has_station_error()) {
1335 control_data->set_station_error(simple_mpc.station_error());
1336 }
1337 if (simple_mpc.has_heading_error()) {
1338 control_data->set_heading_error(simple_mpc.heading_error());
1339 }
1340 if (simple_mpc.has_lateral_error()) {
1341 control_data->set_lateral_error(simple_mpc.lateral_error());
1342 }
1343 }
1344 }
1345}
1346
1347template <>
1348void SimulationWorldService::UpdateSimulationWorld(
1349 const NavigationInfo &navigation_info) {
1350 world_.clear_navigation_path();
1351 for (auto &navigation_path : navigation_info.navigation_path()) {
1352 if (navigation_path.has_path()) {
1353 DownsamplePath(navigation_path.path(), world_.add_navigation_path());
1354 }
1355 }
1356}
1357
1358template <>
1359void SimulationWorldService::UpdateSimulationWorld(const MapMsg &map_msg) {
1360 if (map_msg.has_hdmap()) {
1361 relative_map_.CopyFrom(map_msg.hdmap());
1362 for (int i = 0; i < relative_map_.lane_size(); ++i) {
1363 auto *lane = relative_map_.mutable_lane(i);
1364 lane->clear_left_sample();
1365 lane->clear_right_sample();
1366 lane->clear_left_road_sample();
1367 lane->clear_right_road_sample();
1368
1369 DownsampleCurve(lane->mutable_central_curve());
1370 DownsampleCurve(lane->mutable_left_boundary()->mutable_curve());
1371 DownsampleCurve(lane->mutable_right_boundary()->mutable_curve());
1372 }
1373 }
1374}
1375
1376template <>
1377void SimulationWorldService::UpdateSimulationWorld(
1378 const MonitorMessage &monitor_msg) {
1379 const int updated_size = std::min(monitor_msg.item_size(),
1380 SimulationWorldService::kMaxMonitorItems);
1381 // Save the latest messages at the end of the history.
1382 for (int idx = 0; idx < updated_size; ++idx) {
1383 auto *notification = world_.add_notification();
1384 notification->mutable_item()->CopyFrom(monitor_msg.item(idx));
1385 notification->set_timestamp_sec(monitor_msg.header().timestamp_sec());
1386 }
1387
1388 int remove_size =
1389 world_.notification_size() - SimulationWorldService::kMaxMonitorItems;
1390 if (remove_size > 0) {
1391 auto *notifications = world_.mutable_notification();
1392 notifications->erase(notifications->begin(),
1393 notifications->begin() + remove_size);
1394 }
1395}
1396
1397void SimulationWorldService::UpdateMonitorMessages() {
1398 std::list<std::shared_ptr<MonitorMessage>> monitor_msgs;
1399 {
1400 std::unique_lock<std::mutex> lock(monitor_msgs_mutex_);
1401 monitor_msgs = monitor_msgs_;
1402 monitor_msgs_.clear();
1403 }
1404
1405 for (const auto &monitor_msg : monitor_msgs) {
1406 UpdateSimulationWorld(*monitor_msg);
1407 }
1408}
1409
1410void SimulationWorldService::DumpMessages() {
1411 DumpMessageFromReader(chassis_reader_.get());
1412 DumpMessageFromReader(prediction_obstacle_reader_.get());
1413 DumpMessageFromReader(planning_command_reader_.get());
1414 DumpMessageFromReader(localization_reader_.get());
1415 DumpMessageFromReader(planning_reader_.get());
1416 DumpMessageFromReader(control_command_reader_.get());
1417 DumpMessageFromReader(perception_obstacle_reader_.get());
1418 DumpMessageFromReader(perception_traffic_light_reader_.get());
1419 DumpMessageFromReader(relative_map_reader_.get());
1420 DumpMessageFromReader(navigation_reader_.get());
1421 DumpMessageFromReader(task_reader_.get());
1422}
1423
1424void SimulationWorldService::PublishNavigationInfo(
1425 const std::shared_ptr<NavigationInfo> &navigation_info) {
1426 FillHeader(FLAGS_dreamview_module_name, navigation_info.get());
1427 navigation_writer_->Write(navigation_info);
1428}
1429
1430void SimulationWorldService::PublishLaneFollowCommand(
1431 const std::shared_ptr<LaneFollowCommand> &lane_follow_command) {
1432 FillHeader(FLAGS_dreamview_module_name, lane_follow_command.get());
1433 lane_follow_command_client_->SendRequest(lane_follow_command);
1434}
1435
1436void SimulationWorldService::PublishValetParkingCommand(
1437 const std::shared_ptr<ValetParkingCommand> &valet_parking_command) {
1438 FillHeader(FLAGS_dreamview_module_name, valet_parking_command.get());
1439 valet_parking_command_client_->SendRequest(valet_parking_command);
1440}
1441
1442void SimulationWorldService::PublishActionCommand(
1443 const std::shared_ptr<ActionCommand> &action_command) {
1444 FillHeader(FLAGS_dreamview_module_name, action_command.get());
1445 action_command_client_->SendRequest(action_command);
1446}
1447
1448void SimulationWorldService::PublishTask(const std::shared_ptr<Task> &task) {
1449 FillHeader(FLAGS_dreamview_module_name, task.get());
1450 task_writer_->Write(task);
1451}
1452
1453void SimulationWorldService::PublishMonitorMessage(
1455 const std::string &msg) {
1456 monitor_logger_buffer_.AddMonitorMsgItem(log_level, msg);
1457 monitor_logger_buffer_.Publish();
1458}
1459
1460void SimulationWorldService::UpdateVehicleParam() {
1461 auto &vehicle_param = VehicleConfigHelper::GetConfig().vehicle_param();
1462 world_.mutable_vehicle_param()->CopyFrom(vehicle_param);
1463}
1464
1465} // namespace dreamview
1466} // namespace apollo
@Brief This is a helper class that can load vehicle configurations.
The class of polygon in 2-D.
Definition polygon2d.h:42
Polygon2d ExpandByDistance(const double distance) const
Expand this polygon by a distance.
Definition polygon2d.cc:604
const std::vector< Vec2d > & points() const
Get the vertices of the polygon.
Definition polygon2d.h:65
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
void set_x(const double x)
Setter for x component
Definition vec2d.h:60
double y() const
Getter for y component
Definition vec2d.h:57
double x() const
Getter for x component
Definition vec2d.h:54
void set_y(const double y)
Setter for y component
Definition vec2d.h:63
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static Time Now()
PRECISION >= 1000000 means the precision is at least 1us.
Definition clock.cc:40
double ToSecond() const
convert time to second.
Definition time.cc:77
SimulationWorldService(const MapService *map_service, bool routing_from_file=false)
Constructor of SimulationWorldService.
#define ADEBUG
Definition log.h:41
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
Some map util functions.
Some util functions.
nlohmann::json Json
double QuaternionToHeading(const double qw, const double qx, const double qy, const double qz)
Definition quaternion.h:56
std::vector< size_t > DownsampleByAngle(const Points &points, const double angle_threshold)
Downsample the points on the path according to the angle.
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::unique_ptr< Node > CreateNode(const std::string &node_name, const std::string &name_space)
Definition cyber.cc:33
std::string formatDoubleToString(const double data)
class register implement
Definition arena_queue.h:37
Contains a number of helper functions related to quaternions.
optional GearPosition gear_location
optional apollo::common::VehicleSignal signal
optional float steering_percentage
Definition chassis.proto:88
optional float speed_mps
Definition chassis.proto:70
optional float brake_percentage
Definition chassis.proto:82
optional int32 battery_soc_percentage
optional float throttle_percentage
Definition chassis.proto:79
optional double timestamp_sec
Definition header.proto:9
optional string module_name
Definition header.proto:12
optional apollo::common::Header header
optional apollo::common::Header header
optional LatencyStats latency_stats
optional SimpleLongitudinalDebug simple_lon_debug
optional apollo::common::Header header
Definition gps.proto:9
optional apollo::localization::Pose localization
Definition gps.proto:12
optional apollo::localization::Pose pose
optional apollo::common::Header header
optional apollo::common::EngageAdvice engage_advice
optional LatencyStats latency_stats
optional apollo::common::Header header
optional apollo::planning::DecisionResult decision
optional apollo::planning_internal::Debug debug
optional apollo::common::Header header
optional apollo::routing::RoutingResponse lane_follow_command
optional ObstacleInteractiveTag interactive_tag
optional apollo::perception::PerceptionObstacle perception_obstacle
optional apollo::hdmap::Map hdmap
repeated NavigationPath navigation_path