Apollo 10.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
304
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) {
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) {
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
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 UpdateWithLatestObserved(planning_command_reader_.get(), false);
416 UpdateWithLatestObserved(chassis_reader_.get());
417 UpdateWithLatestObserved(gps_reader_.get());
418 UpdateWithLatestObserved(localization_reader_.get());
419
420 // Clear objects received from last frame and populate with the new objects.
421 // TODO(siyangy, unacao): For now we are assembling the simulation_world with
422 // latest received perception, prediction and planning message. However, they
423 // may not always be perfectly aligned and belong to the same frame.
424 obj_map_.clear();
425 world_.clear_object();
426 world_.clear_sensor_measurements();
427 UpdateWithLatestObserved(audio_detection_reader_.get());
428 UpdateWithLatestObserved(storytelling_reader_.get());
429 UpdateWithLatestObserved(perception_obstacle_reader_.get());
430 UpdateWithLatestObserved(perception_traffic_light_reader_.get(), false);
431 UpdateWithLatestObserved(prediction_obstacle_reader_.get());
432 UpdateWithLatestObserved(planning_reader_.get());
433 UpdateWithLatestObserved(control_command_reader_.get());
434 UpdateWithLatestObserved(navigation_reader_.get(), FLAGS_use_navigation_mode);
435 UpdateWithLatestObserved(relative_map_reader_.get(),
436 FLAGS_use_navigation_mode);
437
438 for (const auto &kv : obj_map_) {
439 *world_.add_object() = kv.second;
440 }
441
442 UpdateDelays();
443 UpdateLatencies();
444
445 world_.set_sequence_num(world_.sequence_num() + 1);
446 world_.set_timestamp(Clock::Now().ToSecond() * 1000);
447}
448
449void SimulationWorldService::UpdateDelays() {
450 auto *delays = world_.mutable_delay();
451 delays->set_chassis(SecToMs(chassis_reader_->GetDelaySec()));
452 delays->set_localization(SecToMs(localization_reader_->GetDelaySec()));
453 delays->set_perception_obstacle(
454 SecToMs(perception_obstacle_reader_->GetDelaySec()));
455 delays->set_planning(SecToMs(planning_reader_->GetDelaySec()));
456 delays->set_prediction(SecToMs(prediction_obstacle_reader_->GetDelaySec()));
457 delays->set_traffic_light(
458 SecToMs(perception_traffic_light_reader_->GetDelaySec()));
459 delays->set_control(SecToMs(control_command_reader_->GetDelaySec()));
460}
461
462void SimulationWorldService::UpdateLatencies() {
463 UpdateLatency("chassis", chassis_reader_.get());
464 UpdateLatency("localization", localization_reader_.get());
465 UpdateLatency("perception", perception_obstacle_reader_.get());
466 UpdateLatency("planning", planning_reader_.get());
467 UpdateLatency("prediction", prediction_obstacle_reader_.get());
468 UpdateLatency("control", control_command_reader_.get());
469}
470
472 double radius, std::string *sim_world,
473 std::string *sim_world_with_planning_data) {
474 PopulateMapInfo(radius);
475
476 world_.SerializeToString(sim_world_with_planning_data);
477
478 world_.clear_planning_data();
479 world_.SerializeToString(sim_world);
480}
481
483 std::string sim_world_json_string;
484 MessageToJsonString(world_, &sim_world_json_string);
485
486 Json update;
487 update["type"] = "SimWorldUpdate";
488 update["timestamp"] = Clock::Now().ToSecond() * 1000;
489 update["world"] = sim_world_json_string;
490
491 return update;
492}
493
495 MapElementIds *ids) const {
496 // Gather required map element ids based on current location.
498 const auto &adc = world_.auto_driving_car();
499 point.set_x(adc.position_x());
500 point.set_y(adc.position_y());
501 map_service_->CollectMapElementIds(point, radius, ids);
502}
503
504void SimulationWorldService::PopulateMapInfo(double radius) {
505 world_.clear_map_element_ids();
506 GetMapElementIds(radius, world_.mutable_map_element_ids());
507 world_.set_map_hash(map_service_->CalculateMapHash(world_.map_element_ids()));
508 world_.set_map_radius(radius);
509}
510
512 return relative_map_;
513}
514
515template <>
516void SimulationWorldService::UpdateSimulationWorld(
517 const LocalizationEstimate &localization) {
518 Object *auto_driving_car = world_.mutable_auto_driving_car();
519 const auto &pose = localization.pose();
520
521 // Updates position with the input localization message.
522 auto_driving_car->set_position_x(pose.position().x() +
523 map_service_->GetXOffset());
524 auto_driving_car->set_position_y(pose.position().y() +
525 map_service_->GetYOffset());
526 auto_driving_car->set_heading(pose.heading());
527
528 // Updates acceleration with the input localization message.
529 auto_driving_car->set_speed_acceleration(CalculateAcceleration(
530 pose.linear_acceleration(), pose.linear_velocity(), gear_location_));
531
532 // Updates the timestamp with the timestamp inside the localization
533 // message header. It is done on both the SimulationWorld object
534 // itself and its auto_driving_car() field.
535 auto_driving_car->set_timestamp_sec(localization.header().timestamp_sec());
536 ready_to_push_.store(true);
537}
538
539template <>
540void SimulationWorldService::UpdateSimulationWorld(const Gps &gps) {
541 if (gps.header().module_name() == "ShadowLocalization") {
542 Object *shadow_localization_position = world_.mutable_shadow_localization();
543 const auto &pose = gps.localization();
544 shadow_localization_position->set_position_x(pose.position().x() +
545 map_service_->GetXOffset());
546 shadow_localization_position->set_position_y(pose.position().y() +
547 map_service_->GetYOffset());
548 shadow_localization_position->set_heading(pose.heading());
549 } else {
550 Object *gps_position = world_.mutable_gps();
551 gps_position->set_timestamp_sec(gps.header().timestamp_sec());
552
553 const auto &pose = gps.localization();
554 gps_position->set_position_x(pose.position().x() +
555 map_service_->GetXOffset());
556 gps_position->set_position_y(pose.position().y() +
557 map_service_->GetYOffset());
558
560 pose.orientation().qw(), pose.orientation().qx(),
561 pose.orientation().qy(), pose.orientation().qz());
562 gps_position->set_heading(heading);
563 }
564}
565
566template <>
567void SimulationWorldService::UpdateSimulationWorld(const Chassis &chassis) {
568 const auto &vehicle_param = VehicleConfigHelper::GetConfig().vehicle_param();
569 Object *auto_driving_car = world_.mutable_auto_driving_car();
570
571 double speed = chassis.speed_mps();
572 gear_location_ = chassis.gear_location();
573 if (gear_location_ == Chassis::GEAR_REVERSE) {
574 speed = -speed;
575 }
576 auto_driving_car->set_speed(speed);
577 auto_driving_car->set_throttle_percentage(chassis.throttle_percentage());
578 auto_driving_car->set_brake_percentage(chassis.brake_percentage());
579
580 // In case of out-of-range percentages, reduces it to zero.
581 double angle_percentage = chassis.steering_percentage();
582 if (angle_percentage > 100 || angle_percentage < -100) {
583 angle_percentage = 0;
584 }
585 auto_driving_car->set_steering_percentage(angle_percentage);
586
587 double steering_angle =
588 angle_percentage / 100.0 * vehicle_param.max_steer_angle();
589 auto_driving_car->set_steering_angle(steering_angle);
590
591 double kappa = std::tan(steering_angle / vehicle_param.steer_ratio()) /
592 vehicle_param.wheel_base();
593 auto_driving_car->set_kappa(kappa);
594
595 UpdateTurnSignal(chassis.signal(), auto_driving_car);
596
597 auto_driving_car->set_disengage_type(DeduceDisengageType(chassis));
598
599 auto_driving_car->set_battery_percentage(chassis.battery_soc_percentage());
600 auto_driving_car->set_gear_location(chassis.gear_location());
601}
602
603template <>
604void SimulationWorldService::UpdateSimulationWorld(const Stories &stories) {
605 world_.clear_stories();
606 auto *world_stories = world_.mutable_stories();
607
608 const google::protobuf::Descriptor *descriptor = stories.GetDescriptor();
609 const google::protobuf::Reflection *reflection = stories.GetReflection();
610 const int field_count = descriptor->field_count();
611 for (int i = 0; i < field_count; ++i) {
612 const google::protobuf::FieldDescriptor *field = descriptor->field(i);
613 if (field->name() != "header") {
614 (*world_stories)[field->name()] = reflection->HasField(stories, field);
615 }
616 }
617}
618
619template <>
620void SimulationWorldService::UpdateSimulationWorld(
621 const AudioDetection &audio_detection) {
622 world_.set_is_siren_on(audio_detection.is_siren());
623}
624
625Object &SimulationWorldService::CreateWorldObjectIfAbsent(
626 const PerceptionObstacle &obstacle) {
627 const std::string id = std::to_string(obstacle.id());
628 // Create a new world object and put it into object map if the id does not
629 // exist in the map yet.
630 if (!apollo::common::util::ContainsKey(obj_map_, id)) {
631 Object &world_obj = obj_map_[id];
632 SetObstacleInfo(obstacle, &world_obj);
633 SetObstaclePolygon(obstacle, &world_obj);
634 SetObstacleType(obstacle.type(), obstacle.sub_type(), &world_obj);
635 SetObstacleSensorMeasurements(obstacle, &world_obj);
636 SetObstacleSource(obstacle, &world_obj);
637 }
638 return obj_map_[id];
639}
640
641void SimulationWorldService::CreateWorldObjectFromSensorMeasurement(
642 const SensorMeasurement &sensor, Object *world_object) {
643 world_object->set_id(std::to_string(sensor.id()));
644 world_object->set_position_x(sensor.position().x());
645 world_object->set_position_y(sensor.position().y());
646 world_object->set_heading(sensor.theta());
647 world_object->set_length(sensor.length());
648 world_object->set_width(sensor.width());
649 world_object->set_height(sensor.height());
650 SetObstacleType(sensor.type(), sensor.sub_type(), world_object);
651}
652
653void SimulationWorldService::SetObstacleInfo(const PerceptionObstacle &obstacle,
654 Object *world_object) {
655 if (world_object == nullptr) {
656 return;
657 }
658
659 world_object->set_id(std::to_string(obstacle.id()));
660 world_object->set_position_x(obstacle.position().x() +
661 map_service_->GetXOffset());
662 world_object->set_position_y(obstacle.position().y() +
663 map_service_->GetYOffset());
664 world_object->set_heading(obstacle.theta());
665 world_object->set_length(obstacle.length());
666 world_object->set_width(obstacle.width());
667 world_object->set_height(obstacle.height());
668 world_object->set_speed(
669 std::hypot(obstacle.velocity().x(), obstacle.velocity().y()));
670 world_object->set_speed_heading(
671 std::atan2(obstacle.velocity().y(), obstacle.velocity().x()));
672 world_object->set_timestamp_sec(obstacle.timestamp());
673 world_object->set_confidence(obstacle.has_confidence() ? obstacle.confidence()
674 : 1);
675}
676
677void SimulationWorldService::SetObstaclePolygon(
678 const PerceptionObstacle &obstacle, Object *world_object) {
679 if (world_object == nullptr) {
680 return;
681 }
682
684 std::unordered_set<std::pair<double, double>, PairHash> seen_points;
685 world_object->clear_polygon_point();
686 for (const auto &point : obstacle.polygon_point()) {
687 // Filter out duplicate xy pairs.
688 std::pair<double, double> xy_pair = {point.x(), point.y()};
689 if (seen_points.count(xy_pair) == 0) {
690 PolygonPoint *poly_pt = world_object->add_polygon_point();
691 poly_pt->set_x(point.x() + map_service_->GetXOffset());
692 poly_pt->set_y(point.y() + map_service_->GetYOffset());
693 seen_points.insert(xy_pair);
694 }
695 }
696}
697
698void SimulationWorldService::SetObstacleSensorMeasurements(
699 const PerceptionObstacle &obstacle, Object *world_object) {
700 if (world_object == nullptr) {
701 return;
702 }
703 for (const auto &sensor : obstacle.measurements()) {
704 Object *obj = (*(world_.mutable_sensor_measurements()))[sensor.sensor_id()]
705 .add_sensor_measurement();
706 CreateWorldObjectFromSensorMeasurement(sensor, obj);
707 }
708}
709
710void SimulationWorldService::SetObstacleSource(
712 Object *world_object) {
713 if (world_object == nullptr || !obstacle.has_source()) {
714 return;
715 }
716 const PerceptionObstacle::Source obstacle_source = obstacle.source();
717 world_object->set_source(obstacle_source);
718 world_object->clear_v2x_info();
719 if (obstacle_source == PerceptionObstacle::V2X && obstacle.has_v2x_info()) {
720 world_object->mutable_v2x_info()->CopyFrom(obstacle.v2x_info());
721 }
722 return;
723}
724
725template <>
726void SimulationWorldService::UpdateSimulationWorld(
727 const PerceptionObstacles &obstacles) {
728 for (const auto &obstacle : obstacles.perception_obstacle()) {
729 auto &world_obj = CreateWorldObjectIfAbsent(obstacle);
730 if (obstacles.has_cipv_info() &&
731 (obstacles.cipv_info().cipv_id() == obstacle.id())) {
732 world_obj.set_type(Object_Type_CIPV);
733 }
734 }
735
736 if (obstacles.has_lane_marker()) {
737 world_.mutable_lane_marker()->CopyFrom(obstacles.lane_marker());
738 }
739}
740
741template <>
742void SimulationWorldService::UpdateSimulationWorld(
743 const TrafficLightDetection &traffic_light_detection) {
744 world_.clear_perceived_signal();
745 for (const auto &traffic_light : traffic_light_detection.traffic_light()) {
746 Object *signal = world_.add_perceived_signal();
747 signal->set_id(traffic_light.id());
748 signal->set_current_signal(TrafficLight_Color_Name(traffic_light.color()));
749 }
750}
751
752void SimulationWorldService::UpdatePlanningTrajectory(
753 const ADCTrajectory &trajectory) {
754 // Collect trajectory
755 world_.clear_planning_trajectory();
756 const double base_time = trajectory.header().timestamp_sec();
757 for (const TrajectoryPoint &point : trajectory.trajectory_point()) {
758 Object *trajectory_point = world_.add_planning_trajectory();
759 trajectory_point->set_timestamp_sec(point.relative_time() + base_time);
760 trajectory_point->set_position_x(point.path_point().x() +
761 map_service_->GetXOffset());
762 trajectory_point->set_position_y(point.path_point().y() +
763 map_service_->GetYOffset());
764 trajectory_point->set_speed(point.v());
765 trajectory_point->set_speed_acceleration(point.a());
766 trajectory_point->set_kappa(point.path_point().kappa());
767 trajectory_point->set_dkappa(point.path_point().dkappa());
768 trajectory_point->set_heading(point.path_point().theta());
769 }
770
771 // Update engage advice.
772 // This is a temporary solution, the advice will come from monitor later
773 if (trajectory.has_engage_advice()) {
774 world_.set_engage_advice(
775 EngageAdvice_Advice_Name(trajectory.engage_advice().advice()));
776 }
777}
778
779std::string formatDoubleToString(const double data) {
780 std::stringstream ss;
781 ss << std::fixed << std::setprecision(2) << data;
782 return ss.str();
783}
784
785void SimulationWorldService::UpdateRSSInfo(const ADCTrajectory &trajectory) {
786 if (trajectory.has_rss_info()) {
787 if (trajectory.rss_info().is_rss_safe()) {
788 if (!world_.is_rss_safe()) {
790 world_.set_is_rss_safe(true);
791 }
792 } else {
793 const double next_real_dist = trajectory.rss_info().cur_dist_lon();
794 const double next_rss_safe_dist =
795 trajectory.rss_info().rss_safe_dist_lon();
796 // Not update RSS message if data keeps same.
797 if (std::fabs(current_real_dist_ - next_real_dist) <
799 std::fabs(current_rss_safe_dist_ - next_rss_safe_dist) <
801 return;
802 }
805 "RSS unsafe: \ncurrent distance: " +
806 formatDoubleToString(trajectory.rss_info().cur_dist_lon()) +
807 "\nsafe distance: " +
808 formatDoubleToString(trajectory.rss_info().rss_safe_dist_lon()));
809 world_.set_is_rss_safe(false);
810 current_real_dist_ = next_real_dist;
811 current_rss_safe_dist_ = next_rss_safe_dist;
812 }
813 }
814}
815
816void SimulationWorldService::UpdateMainStopDecision(
817 const apollo::planning::MainDecision &main_decision,
818 double update_timestamp_sec, Object *world_main_decision) {
820 double stop_heading = 0.0;
821 auto decision = world_main_decision->add_decision();
822 decision->set_type(Decision::STOP);
823 if (main_decision.has_not_ready()) {
824 // The car is not ready!
825 // Use the current ADC pose since it is better not to self-drive.
826 stop_pt.set_x(world_.auto_driving_car().position_x());
827 stop_pt.set_y(world_.auto_driving_car().position_y());
828 stop_heading = world_.auto_driving_car().heading();
829 decision->set_stopreason(Decision::STOP_REASON_NOT_READY);
830 } else if (main_decision.has_estop()) {
831 // Emergency stop.
832 // Use the current ADC pose since it is better to stop immediately.
833 stop_pt.set_x(world_.auto_driving_car().position_x());
834 stop_pt.set_y(world_.auto_driving_car().position_y());
835 stop_heading = world_.auto_driving_car().heading();
836 decision->set_stopreason(Decision::STOP_REASON_EMERGENCY);
837 world_.mutable_auto_driving_car()->set_current_signal("EMERGENCY");
838 } else {
839 // Normal stop.
840 const apollo::planning::MainStop &stop = main_decision.stop();
841 stop_pt.set_x(stop.stop_point().x() + map_service_->GetXOffset());
842 stop_pt.set_y(stop.stop_point().y() + map_service_->GetYOffset());
843 stop_heading = stop.stop_heading();
844 if (stop.has_reason_code()) {
845 SetStopReason(stop.reason_code(), decision);
846 }
847 }
848
849 decision->set_position_x(stop_pt.x());
850 decision->set_position_y(stop_pt.y());
851 decision->set_heading(stop_heading);
852}
853
854bool SimulationWorldService::LocateMarker(
855 const apollo::planning::ObjectDecisionType &decision,
856 Decision *world_decision) {
857 apollo::common::PointENU fence_point;
858 double heading;
859 if (decision.has_stop() && decision.stop().has_stop_point()) {
860 world_decision->set_type(Decision_Type_STOP);
861 fence_point = decision.stop().stop_point();
862 heading = decision.stop().stop_heading();
863 } else if (decision.has_follow() && decision.follow().has_fence_point()) {
864 world_decision->set_type(Decision_Type_FOLLOW);
865 fence_point = decision.follow().fence_point();
866 heading = decision.follow().fence_heading();
867 } else if (decision.has_yield() && decision.yield().has_fence_point()) {
868 world_decision->set_type(Decision_Type_YIELD);
869 fence_point = decision.yield().fence_point();
870 heading = decision.yield().fence_heading();
871 } else if (decision.has_overtake() && decision.overtake().has_fence_point()) {
872 world_decision->set_type(Decision_Type_OVERTAKE);
873 fence_point = decision.overtake().fence_point();
874 heading = decision.overtake().fence_heading();
875 } else {
876 return false;
877 }
878
879 world_decision->set_position_x(fence_point.x() + map_service_->GetXOffset());
880 world_decision->set_position_y(fence_point.y() + map_service_->GetYOffset());
881 world_decision->set_heading(heading);
882 return true;
883}
884
885void SimulationWorldService::FindNudgeRegion(
886 const apollo::planning::ObjectDecisionType &decision,
887 const Object &world_obj, Decision *world_decision) {
888 std::vector<apollo::common::math::Vec2d> points;
889 for (auto &polygon_pt : world_obj.polygon_point()) {
890 points.emplace_back(polygon_pt.x(), polygon_pt.y());
891 }
892 const apollo::common::math::Polygon2d obj_polygon(points);
893 const apollo::common::math::Polygon2d &nudge_polygon =
894 obj_polygon.ExpandByDistance(std::fabs(decision.nudge().distance_l()));
895 const std::vector<apollo::common::math::Vec2d> &nudge_points =
896 nudge_polygon.points();
897 for (auto &nudge_pt : nudge_points) {
898 PolygonPoint *poly_pt = world_decision->add_polygon_point();
899 poly_pt->set_x(nudge_pt.x());
900 poly_pt->set_y(nudge_pt.y());
901 }
902 world_decision->set_type(Decision_Type_NUDGE);
903}
904
905void SimulationWorldService::UpdateDecision(const DecisionResult &decision_res,
906 double header_time) {
907 // Update turn signal.
908 UpdateTurnSignal(decision_res.vehicle_signal(),
909 world_.mutable_auto_driving_car());
910
911 const auto &main_decision = decision_res.main_decision();
912
913 // Update speed limit.
914 if (main_decision.target_lane_size() > 0) {
915 world_.set_speed_limit(main_decision.target_lane(0).speed_limit());
916 }
917
918 // Update relevant main stop with reason and change lane.
919 world_.clear_main_decision();
920 Object *world_main_decision = world_.mutable_main_decision();
921 if (main_decision.has_not_ready() || main_decision.has_estop() ||
922 main_decision.has_stop()) {
923 UpdateMainStopDecision(main_decision, header_time, world_main_decision);
924 }
925 if (main_decision.has_stop()) {
926 UpdateMainChangeLaneDecision(main_decision.stop(), world_main_decision);
927 } else if (main_decision.has_cruise()) {
928 UpdateMainChangeLaneDecision(main_decision.cruise(), world_main_decision);
929 }
930 if (world_main_decision->decision_size() > 0) {
931 // set default position
932 const auto &adc = world_.auto_driving_car();
933 world_main_decision->set_position_x(adc.position_x());
934 world_main_decision->set_position_y(adc.position_y());
935 world_main_decision->set_heading(adc.heading());
936 world_main_decision->set_timestamp_sec(header_time);
937 }
938
939 // Update obstacle decision.
940 for (const auto &obj_decision : decision_res.object_decision().decision()) {
941 if (obj_decision.has_perception_id()) {
942 int id = obj_decision.perception_id();
943 Object &world_obj = obj_map_[std::to_string(id)];
944 if (!world_obj.has_type()) {
945 world_obj.set_type(Object_Type_VIRTUAL);
946 ADEBUG << id << " is not a current perception object";
947 }
948
949 for (const auto &decision : obj_decision.object_decision()) {
950 Decision *world_decision = world_obj.add_decision();
951 world_decision->set_type(Decision_Type_IGNORE);
952 if (decision.has_stop() || decision.has_follow() ||
953 decision.has_yield() || decision.has_overtake()) {
954 if (!LocateMarker(decision, world_decision)) {
955 AWARN << "No decision marker position found for object id=" << id;
956 continue;
957 }
958 if (decision.has_stop()) {
959 // flag yielded obstacles
960 for (auto obstacle_id : decision.stop().wait_for_obstacle()) {
961 const std::vector<std::string> id_segments =
962 absl::StrSplit(obstacle_id, '_');
963 if (id_segments.size() > 0) {
964 obj_map_[id_segments[0]].set_yielded_obstacle(true);
965 }
966 }
967 }
968 } else if (decision.has_nudge()) {
969 if (world_obj.polygon_point().empty()) {
970 if (world_obj.type() == Object_Type_VIRTUAL) {
971 AWARN << "No current perception object with id=" << id
972 << " for nudge decision";
973 } else {
974 AWARN << "No polygon points found for object id=" << id;
975 }
976 continue;
977 }
978 FindNudgeRegion(decision, world_obj, world_decision);
979 }
980 }
981
982 world_obj.set_timestamp_sec(
983 std::max(world_obj.timestamp_sec(), header_time));
984 }
985 }
986}
987
988void SimulationWorldService::DownsamplePath(const common::Path &path,
989 common::Path *downsampled_path) {
990 auto sampled_indices = DownsampleByAngle(path.path_point(), kAngleThreshold);
991
992 downsampled_path->set_name(path.name());
993 for (const size_t index : sampled_indices) {
994 *downsampled_path->add_path_point() =
995 path.path_point(static_cast<int>(index));
996 }
997}
998
999void SimulationWorldService::UpdatePlanningData(const PlanningData &data) {
1000 auto *planning_data = world_.mutable_planning_data();
1001
1002 size_t max_interval = 10;
1003
1004 // Update scenario
1005 if (data.has_scenario()) {
1006 planning_data->mutable_scenario()->CopyFrom(data.scenario());
1007
1008 // Adapt to 1.0 records
1009 if (!data.scenario().has_scenario_plugin_type()) {
1010 planning_data->mutable_scenario()->set_scenario_plugin_type(
1011 ScenarioType[planning_data->scenario().scenario_type()]);
1012 planning_data->mutable_scenario()->set_stage_plugin_type(
1013 StageType[planning_data->scenario().stage_type()]);
1014 }
1015 }
1016
1017 // Update init point
1018 if (data.has_init_point()) {
1019 auto &planning_path_point = data.init_point().path_point();
1020 auto *world_obj_path_point =
1021 planning_data->mutable_init_point()->mutable_path_point();
1022 world_obj_path_point->set_x(planning_path_point.x() +
1023 map_service_->GetXOffset());
1024 world_obj_path_point->set_y(planning_path_point.y() +
1025 map_service_->GetYOffset());
1026 world_obj_path_point->set_theta(planning_path_point.theta());
1027 }
1028
1029 // Update Chart
1030 planning_data->mutable_chart()->CopyFrom(data.chart());
1031
1032 // Update SL Frame
1033 planning_data->mutable_sl_frame()->CopyFrom(data.sl_frame());
1034
1035 // Update DP path
1036 if (data.has_dp_poly_graph()) {
1037 planning_data->mutable_dp_poly_graph()->CopyFrom(data.dp_poly_graph());
1038 }
1039
1040 // Update ST Graph
1041 planning_data->clear_st_graph();
1042 for (auto &graph : data.st_graph()) {
1043 auto *st_graph = planning_data->add_st_graph();
1044 st_graph->set_name(graph.name());
1045 st_graph->mutable_boundary()->CopyFrom(graph.boundary());
1046 if (graph.has_kernel_cruise_ref()) {
1047 st_graph->mutable_kernel_cruise_ref()->CopyFrom(
1048 graph.kernel_cruise_ref());
1049 }
1050 if (graph.has_kernel_follow_ref()) {
1051 st_graph->mutable_kernel_follow_ref()->CopyFrom(
1052 graph.kernel_follow_ref());
1053 }
1054 if (graph.has_speed_constraint()) {
1055 st_graph->mutable_speed_constraint()->CopyFrom(graph.speed_constraint());
1056 }
1057
1058 // downsample speed_profile and speed_limit
1059 // The x-axis range is always [-10, 200], downsample to ~200 points but skip
1060 // max 10 points
1061 size_t profile_downsample_interval =
1062 std::max(1, (graph.speed_profile_size() / 200));
1063 profile_downsample_interval =
1064 std::min(profile_downsample_interval, max_interval);
1065 DownsampleSpeedPointsByInterval(graph.speed_profile(),
1066 profile_downsample_interval,
1067 st_graph->mutable_speed_profile());
1068
1069 size_t limit_downsample_interval =
1070 std::max(1, (graph.speed_limit_size() / 200));
1071 limit_downsample_interval =
1072 std::min(limit_downsample_interval, max_interval);
1073 DownsampleSpeedPointsByInterval(graph.speed_limit(),
1074 limit_downsample_interval,
1075 st_graph->mutable_speed_limit());
1076 }
1077
1078 // Update Speed Plan
1079 planning_data->clear_speed_plan();
1080 for (auto &plan : data.speed_plan()) {
1081 if (plan.speed_point_size() > 0) {
1082 auto *downsampled_plan = planning_data->add_speed_plan();
1083 downsampled_plan->set_name(plan.name());
1084
1085 // Downsample the speed plan for frontend display.
1086 // The x-axis range is always [-2, 10], downsample to ~80 points
1087 size_t interval = std::max(1, (plan.speed_point_size() / 80));
1088 interval = std::min(interval, max_interval);
1089 DownsampleSpeedPointsByInterval(plan.speed_point(), interval,
1090 downsampled_plan->mutable_speed_point());
1091 }
1092 }
1093
1094 // Update path
1095 planning_data->clear_path();
1096 for (auto &path : data.path()) {
1097 DownsamplePath(path, planning_data->add_path());
1098 }
1099
1100 // Update pull over status
1101 planning_data->clear_pull_over();
1102 if (data.has_pull_over()) {
1103 planning_data->mutable_pull_over()->CopyFrom(data.pull_over());
1104 }
1105
1106 // Update planning signal
1107 world_.clear_traffic_signal();
1108 if (data.has_signal_light() && data.signal_light().signal_size() > 0) {
1110 int green_light_count = 0;
1111
1112 for (auto &signal : data.signal_light().signal()) {
1113 switch (signal.color()) {
1114 case TrafficLight::RED:
1117 current_signal = signal.color();
1118 break;
1120 green_light_count++;
1121 break;
1122 default:
1123 break;
1124 }
1125 }
1126
1127 if (green_light_count == data.signal_light().signal_size()) {
1128 current_signal = TrafficLight::GREEN;
1129 }
1130
1131 world_.mutable_traffic_signal()->set_current_signal(
1132 TrafficLight_Color_Name(current_signal));
1133 }
1134}
1135
1136template <>
1137void SimulationWorldService::UpdateSimulationWorld(
1138 const ADCTrajectory &trajectory) {
1139 const double header_time = trajectory.header().timestamp_sec();
1140
1141 UpdatePlanningTrajectory(trajectory);
1142
1143 UpdateRSSInfo(trajectory);
1144
1145 UpdateDecision(trajectory.decision(), header_time);
1146
1147 UpdatePlanningData(trajectory.debug().planning_data());
1148
1149 Latency latency;
1150 latency.set_timestamp_sec(header_time);
1151 latency.set_total_time_ms(trajectory.latency_stats().total_time_ms());
1152 (*world_.mutable_latency())["planning"] = latency;
1153}
1154
1155void SimulationWorldService::CreatePredictionTrajectory(
1156 const PredictionObstacle &obstacle, Object *world_object) {
1157 for (const auto &traj : obstacle.trajectory()) {
1158 Prediction *prediction = world_object->add_prediction();
1159 prediction->set_probability(traj.probability());
1160
1161 std::vector<PathPoint> points;
1162 for (const auto &point : traj.trajectory_point()) {
1163 points.push_back(point.path_point());
1164 }
1165 auto sampled_indices = DownsampleByAngle(points, kAngleThreshold);
1166
1167 for (auto index : sampled_indices) {
1168 const auto &point = points[index];
1169 PolygonPoint *world_point = prediction->add_predicted_trajectory();
1170 world_point->set_x(point.x() + map_service_->GetXOffset());
1171 world_point->set_y(point.y() + map_service_->GetYOffset());
1172
1173 const TrajectoryPoint &traj_point = traj.trajectory_point(index);
1174 if (traj_point.has_gaussian_info()) {
1175 const apollo::common::GaussianInfo &gaussian =
1176 traj_point.gaussian_info();
1177
1178 auto *ellipse = world_point->mutable_gaussian_info();
1179 ellipse->set_ellipse_a(gaussian.ellipse_a());
1180 ellipse->set_ellipse_b(gaussian.ellipse_b());
1181 ellipse->set_theta_a(gaussian.theta_a());
1182 }
1183 }
1184 }
1185}
1186
1187template <>
1188void SimulationWorldService::UpdateSimulationWorld(
1189 const PredictionObstacles &obstacles) {
1190 for (const auto &obstacle : obstacles.prediction_obstacle()) {
1191 // Note: There's a perfect one-to-one mapping between the perception
1192 // obstacles and prediction obstacles within the same frame. Creating a new
1193 // world object here is only possible when we happen to be processing a
1194 // perception and prediction message from two frames.
1195 auto &world_obj = CreateWorldObjectIfAbsent(obstacle.perception_obstacle());
1196
1197 // Add prediction trajectory to the object.
1198 CreatePredictionTrajectory(obstacle, &world_obj);
1199
1200 // Add prediction priority
1201 if (obstacle.has_priority()) {
1202 world_obj.mutable_obstacle_priority()->CopyFrom(obstacle.priority());
1203 }
1204
1205 // Add prediction interactive tag
1206 if (obstacle.has_interactive_tag()) {
1207 world_obj.mutable_interactive_tag()->CopyFrom(obstacle.interactive_tag());
1208 }
1209
1210 world_obj.set_timestamp_sec(
1211 std::max(obstacle.timestamp(), world_obj.timestamp_sec()));
1212 }
1213}
1214
1215template <>
1216void SimulationWorldService::UpdateSimulationWorld(
1217 const PlanningCommand &planning_command) {
1218 auto routing_response = planning_command.lane_follow_command();
1219 {
1220 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1221 if (world_.has_routing_time() &&
1222 world_.routing_time() == planning_command.header().timestamp_sec()) {
1223 // This routing response has been processed.
1224 return;
1225 }
1226 }
1227
1228 std::vector<Path> paths;
1229 if (!map_service_->GetPathsFromRouting(routing_response, &paths)) {
1230 return;
1231 }
1232
1233 world_.clear_route_path();
1234
1235 std::vector<RoutePath> route_paths;
1236 for (const Path &path : paths) {
1237 // Downsample the path points for frontend display.
1238 auto sampled_indices =
1239 DownsampleByAngle(path.path_points(), kAngleThreshold);
1240
1241 route_paths.emplace_back();
1242 RoutePath *route_path = &route_paths.back();
1243 for (const size_t index : sampled_indices) {
1244 const auto &path_point = path.path_points()[index];
1245 PolygonPoint *route_point = route_path->add_point();
1246 route_point->set_x(path_point.x() + map_service_->GetXOffset());
1247 route_point->set_y(path_point.y() + map_service_->GetYOffset());
1248 }
1249
1250 // Populate route path
1251 if (FLAGS_sim_world_with_routing_path) {
1252 auto *new_path = world_.add_route_path();
1253 *new_path = *route_path;
1254 }
1255 }
1256 {
1257 boost::unique_lock<boost::shared_mutex> writer_lock(route_paths_mutex_);
1258 std::swap(route_paths, route_paths_);
1259 world_.set_routing_time(planning_command.header().timestamp_sec());
1260 }
1261}
1262
1264 Json response;
1265 response["routePath"] = Json::array();
1266 std::vector<RoutePath> route_paths;
1267 {
1268 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1269 response["routingTime"] = world_.routing_time();
1270 route_paths = route_paths_;
1271 }
1272 for (const auto &route_path : route_paths) {
1273 Json path;
1274 path["point"] = Json::array();
1275 for (const auto &route_point : route_path.point()) {
1276 path["point"].push_back({{"x", route_point.x()},
1277 {"y", route_point.y()},
1278 {"z", route_point.z()}});
1279 }
1280 response["routePath"].push_back(path);
1281 }
1282 return response;
1283}
1284
1285void SimulationWorldService::ReadPlanningCommandFromFile(
1286 const std::string &planning_command_file) {
1287 auto planning_command = std::make_shared<PlanningCommand>();
1288 if (!GetProtoFromFile(planning_command_file, planning_command.get())) {
1289 AWARN << "Unable to read planning command from file: "
1290 << planning_command_file;
1291 return;
1292 }
1293 AINFO << "Loaded planning command from " << planning_command_file;
1294
1295 sleep(1); // Wait to make sure the connection has been established before
1296 // publishing.
1297
1298 auto planning_command_writer =
1299 node_->CreateWriter<PlanningCommand>(FLAGS_planning_command);
1300 planning_command_writer->Write(planning_command);
1301 AINFO << "Published PlanningCommand read from file.";
1302}
1303
1304template <>
1305void SimulationWorldService::UpdateSimulationWorld(
1306 const ControlCommand &control_command) {
1307 auto *control_data = world_.mutable_control_data();
1308 const double header_time = control_command.header().timestamp_sec();
1309 control_data->set_timestamp_sec(header_time);
1310
1311 Latency latency;
1312 latency.set_timestamp_sec(header_time);
1313 latency.set_total_time_ms(control_command.latency_stats().total_time_ms());
1314 (*world_.mutable_latency())["control"] = latency;
1315
1316 if (control_command.has_debug()) {
1317 auto &debug = control_command.debug();
1318 if (debug.has_simple_lon_debug() && debug.has_simple_lat_debug()) {
1319 auto &simple_lon = debug.simple_lon_debug();
1320 if (simple_lon.has_station_error()) {
1321 control_data->set_station_error(simple_lon.station_error());
1322 }
1323 auto &simple_lat = debug.simple_lat_debug();
1324 if (simple_lat.has_heading_error()) {
1325 control_data->set_heading_error(simple_lat.heading_error());
1326 }
1327 if (simple_lat.has_lateral_error()) {
1328 control_data->set_lateral_error(simple_lat.lateral_error());
1329 }
1330 if (simple_lat.has_current_target_point()) {
1331 control_data->mutable_current_target_point()->CopyFrom(
1332 simple_lat.current_target_point());
1333 }
1334 } else if (debug.has_simple_mpc_debug()) {
1335 auto &simple_mpc = debug.simple_mpc_debug();
1336 if (simple_mpc.has_station_error()) {
1337 control_data->set_station_error(simple_mpc.station_error());
1338 }
1339 if (simple_mpc.has_heading_error()) {
1340 control_data->set_heading_error(simple_mpc.heading_error());
1341 }
1342 if (simple_mpc.has_lateral_error()) {
1343 control_data->set_lateral_error(simple_mpc.lateral_error());
1344 }
1345 }
1346 }
1347}
1348
1349template <>
1350void SimulationWorldService::UpdateSimulationWorld(
1351 const NavigationInfo &navigation_info) {
1352 world_.clear_navigation_path();
1353 for (auto &navigation_path : navigation_info.navigation_path()) {
1354 if (navigation_path.has_path()) {
1355 DownsamplePath(navigation_path.path(), world_.add_navigation_path());
1356 }
1357 }
1358}
1359
1360template <>
1361void SimulationWorldService::UpdateSimulationWorld(const MapMsg &map_msg) {
1362 if (map_msg.has_hdmap()) {
1363 relative_map_.CopyFrom(map_msg.hdmap());
1364 for (int i = 0; i < relative_map_.lane_size(); ++i) {
1365 auto *lane = relative_map_.mutable_lane(i);
1366 lane->clear_left_sample();
1367 lane->clear_right_sample();
1368 lane->clear_left_road_sample();
1369 lane->clear_right_road_sample();
1370
1371 DownsampleCurve(lane->mutable_central_curve());
1372 DownsampleCurve(lane->mutable_left_boundary()->mutable_curve());
1373 DownsampleCurve(lane->mutable_right_boundary()->mutable_curve());
1374 }
1375 }
1376}
1377
1378template <>
1379void SimulationWorldService::UpdateSimulationWorld(
1380 const MonitorMessage &monitor_msg) {
1381 const int updated_size = std::min(monitor_msg.item_size(),
1383 // Save the latest messages at the end of the history.
1384 for (int idx = 0; idx < updated_size; ++idx) {
1385 auto *notification = world_.add_notification();
1386 notification->mutable_item()->CopyFrom(monitor_msg.item(idx));
1387 notification->set_timestamp_sec(monitor_msg.header().timestamp_sec());
1388 }
1389
1390 int remove_size =
1391 world_.notification_size() - SimulationWorldService::kMaxMonitorItems;
1392 if (remove_size > 0) {
1393 auto *notifications = world_.mutable_notification();
1394 notifications->erase(notifications->begin(),
1395 notifications->begin() + remove_size);
1396 }
1397}
1398
1399void SimulationWorldService::UpdateMonitorMessages() {
1400 std::list<std::shared_ptr<MonitorMessage>> monitor_msgs;
1401 {
1402 std::unique_lock<std::mutex> lock(monitor_msgs_mutex_);
1403 monitor_msgs = monitor_msgs_;
1404 monitor_msgs_.clear();
1405 }
1406
1407 for (const auto &monitor_msg : monitor_msgs) {
1408 UpdateSimulationWorld(*monitor_msg);
1409 }
1410}
1411
1413 DumpMessageFromReader(chassis_reader_.get());
1414 DumpMessageFromReader(prediction_obstacle_reader_.get());
1415 DumpMessageFromReader(planning_command_reader_.get());
1416 DumpMessageFromReader(localization_reader_.get());
1417 DumpMessageFromReader(planning_reader_.get());
1418 DumpMessageFromReader(control_command_reader_.get());
1419 DumpMessageFromReader(perception_obstacle_reader_.get());
1420 DumpMessageFromReader(perception_traffic_light_reader_.get());
1421 DumpMessageFromReader(relative_map_reader_.get());
1422 DumpMessageFromReader(navigation_reader_.get());
1423 DumpMessageFromReader(task_reader_.get());
1424}
1425
1427 const std::shared_ptr<NavigationInfo> &navigation_info) {
1428 FillHeader(FLAGS_dreamview_module_name, navigation_info.get());
1429 navigation_writer_->Write(navigation_info);
1430}
1431
1433 const std::shared_ptr<LaneFollowCommand> &lane_follow_command) {
1434 FillHeader(FLAGS_dreamview_module_name, lane_follow_command.get());
1435 lane_follow_command_client_->SendRequest(lane_follow_command);
1436}
1437
1439 const std::shared_ptr<ValetParkingCommand> &valet_parking_command) {
1440 FillHeader(FLAGS_dreamview_module_name, valet_parking_command.get());
1441 valet_parking_command_client_->SendRequest(valet_parking_command);
1442}
1443
1445 const std::shared_ptr<ActionCommand> &action_command) {
1446 FillHeader(FLAGS_dreamview_module_name, action_command.get());
1447 action_command_client_->SendRequest(action_command);
1448}
1449
1450void SimulationWorldService::PublishTask(const std::shared_ptr<Task> &task) {
1451 FillHeader(FLAGS_dreamview_module_name, task.get());
1452 task_writer_->Write(task);
1453}
1454
1457 const std::string &msg) {
1458 monitor_logger_buffer_.AddMonitorMsgItem(log_level, msg);
1459 monitor_logger_buffer_.Publish();
1460}
1461} // namespace dreamview
1462} // namespace apollo
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
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:683
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
void AddMonitorMsgItem(const MonitorMessageItem::LogLevel log_level, const std::string &msg)
Add monitor message with MonitorMessageItem::LogLevel
void Publish()
publish the monitor messages
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
void CollectMapElementIds(const apollo::common::PointENU &point, double raidus, MapElementIds *ids) const
size_t CalculateMapHash(const MapElementIds &ids) const
bool GetPathsFromRouting(const apollo::routing::RoutingResponse &routing, std::vector< apollo::hdmap::Path > *paths) const
void Update()
The function Update() is periodically called to check for updates from the external messages.
void PublishNavigationInfo(const std::shared_ptr< apollo::relative_map::NavigationInfo > &)
void PublishTask(const std::shared_ptr< apollo::task_manager::Task > &)
void PublishLaneFollowCommand(const std::shared_ptr< apollo::external_command::LaneFollowCommand > &)
nlohmann::json GetUpdateAsJson(double radius) const
Returns the json representation of the SimulationWorld object.
const apollo::hdmap::Map & GetRelativeMap() const
SimulationWorldService(const MapService *map_service, bool routing_from_file=false)
Constructor of SimulationWorldService.
void GetMapElementIds(double radius, MapElementIds *ids) const
void PublishActionCommand(const std::shared_ptr< apollo::external_command::ActionCommand > &)
void PublishMonitorMessage(apollo::common::monitor::MonitorMessageItem::LogLevel log_level, const std::string &msg)
Publish message to the monitor
void GetWireFormatString(double radius, std::string *sim_world, std::string *sim_world_with_planning_data)
Returns the binary representation of the SimulationWorld object.
void PublishValetParkingCommand(const std::shared_ptr< apollo::external_command::ValetParkingCommand > &)
#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
constexpr double kMathEpsilon
Definition vec2d.h:35
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::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 VehicleParam vehicle_param
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