19#include <unordered_set>
21#include "absl/strings/str_split.h"
22#include "google/protobuf/util/json_util.h"
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"
54using apollo::common::util::FillHeader;
75using apollo::planning::DecisionResult;
76using apollo::planning::StopReasonCode;
89using Json = nlohmann::json;
90using ::google::protobuf::util::MessageToJsonString;
93static constexpr double kAngleThreshold = 0.1;
97std::map<int, std::string> ScenarioType = {
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"},
107 {10,
"VALET_PARKING"},
108 {11,
"EMERGENCY_PULL_OVER"},
109 {12,
"EMERGENCY_STOP"},
110 {13,
"NARROW_STREET_U_TURN"},
112 {15,
"LEARNING_MODEL_SAMPLE"},
113 {16,
"DEADEND_TURNAROUND"}};
115std::map<int, std::string> StageType = {
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"}};
152double CalculateAcceleration(
153 const Point3D &acceleration,
const Point3D &velocity,
154 const apollo::canbus::Chassis_GearPosition &gear_location) {
159 acceleration.x() * velocity.x() + acceleration.y() * velocity.y();
163 double magnitude = std::hypot(acceleration.x(), acceleration.y());
164 if (std::signbit(projection)) {
165 magnitude = -magnitude;
170 magnitude = -magnitude;
181 switch (chassis.driving_mode()) {
199 Object *world_object) {
200 if (world_object ==
nullptr) {
204 switch (obstacle_type) {
206 world_object->set_type(Object_Type_UNKNOWN);
209 world_object->set_type(Object_Type_UNKNOWN_MOVABLE);
212 world_object->set_type(Object_Type_UNKNOWN_UNMOVABLE);
215 world_object->set_type(Object_Type_PEDESTRIAN);
218 world_object->set_type(Object_Type_BICYCLE);
221 world_object->set_type(Object_Type_VEHICLE);
224 world_object->set_type(Object_Type_VIRTUAL);
227 world_object->set_sub_type(obstacle_subtype);
230void SetStopReason(
const StopReasonCode &reason_code, Decision *decision) {
231 switch (reason_code) {
232 case StopReasonCode::STOP_REASON_HEAD_VEHICLE:
235 case StopReasonCode::STOP_REASON_DESTINATION:
238 case StopReasonCode::STOP_REASON_PEDESTRIAN:
241 case StopReasonCode::STOP_REASON_OBSTACLE:
244 case StopReasonCode::STOP_REASON_SIGNAL:
247 case StopReasonCode::STOP_REASON_STOP_SIGN:
250 case StopReasonCode::STOP_REASON_YIELD_SIGN:
253 case StopReasonCode::STOP_REASON_CLEAR_ZONE:
256 case StopReasonCode::STOP_REASON_CROSSWALK:
259 case StopReasonCode::STOP_REASON_PULL_OVER:
263 AWARN <<
"Unrecognizable stop reason code:" << reason_code;
268 Object *auto_driving_car) {
270 auto_driving_car->set_current_signal(
"LEFT");
273 auto_driving_car->set_current_signal(
"RIGHT");
275 auto_driving_car->set_current_signal(
"EMERGENCY");
277 auto_driving_car->set_current_signal(
"");
281void DownsampleCurve(Curve *curve) {
282 if (curve->segment().empty()) {
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();
292 std::vector<size_t> sampled_indices =
294 for (
const size_t index : sampled_indices) {
295 *line_segment->add_point() = points[index];
299inline double SecToMs(
const double sec) {
return sec * 1000.0; }
306 bool routing_from_file)
307 : node_(cyber::CreateNode(
"simulation_world")),
308 map_service_(map_service),
310 ready_to_push_(false) {
314 if (routing_from_file) {
315 ReadPlanningCommandFromFile(FLAGS_routing_response_file);
319 Object *auto_driving_car = world_.mutable_auto_driving_car();
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());
326void SimulationWorldService::InitReaders() {
327 planning_command_reader_ =
329 chassis_reader_ = node_->CreateReader<
Chassis>(FLAGS_chassis_topic);
330 gps_reader_ = node_->CreateReader<
Gps>(FLAGS_gps_topic);
331 localization_reader_ =
333 perception_obstacle_reader_ =
336 FLAGS_traffic_light_detection_topic);
337 prediction_obstacle_reader_ =
340 node_->CreateReader<
ADCTrajectory>(FLAGS_planning_trajectory_topic);
341 control_command_reader_ =
345 relative_map_reader_ = node_->CreateReader<
MapMsg>(FLAGS_relative_map_topic);
346 storytelling_reader_ = node_->CreateReader<
Stories>(FLAGS_storytelling_topic);
347 audio_detection_reader_ =
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()));
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());
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);
373 task_reader_ = node_->CreateReader<Task>(FLAGS_task_topic);
376void SimulationWorldService::InitWriters() {
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);
401 *world_.mutable_auto_driving_car() = car;
404 boost::unique_lock<boost::shared_mutex> writer_lock(route_paths_mutex_);
405 route_paths_.clear();
413 UpdateMonitorMessages();
415 UpdateWithLatestObserved(planning_command_reader_.get(),
false);
416 UpdateWithLatestObserved(chassis_reader_.get());
417 UpdateWithLatestObserved(gps_reader_.get());
418 UpdateWithLatestObserved(localization_reader_.get());
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);
438 for (
const auto &kv : obj_map_) {
439 *world_.add_object() = kv.second;
446 world_.set_timestamp(
Clock::Now().ToSecond() * 1000);
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()));
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());
472 double radius, std::string *sim_world,
473 std::string *sim_world_with_planning_data) {
474 PopulateMapInfo(radius);
476 world_.SerializeToString(sim_world_with_planning_data);
478 world_.clear_planning_data();
479 world_.SerializeToString(sim_world);
483 std::string sim_world_json_string;
484 MessageToJsonString(world_, &sim_world_json_string);
487 update[
"type"] =
"SimWorldUpdate";
489 update[
"world"] = sim_world_json_string;
499 point.set_x(adc.position_x());
500 point.set_y(adc.position_y());
504void SimulationWorldService::PopulateMapInfo(
double radius) {
505 world_.clear_map_element_ids();
508 world_.set_map_radius(radius);
512 return relative_map_;
516void SimulationWorldService::UpdateSimulationWorld(
518 Object *auto_driving_car = world_.mutable_auto_driving_car();
519 const auto &pose = localization.
pose();
522 auto_driving_car->set_position_x(pose.position().x() +
524 auto_driving_car->set_position_y(pose.position().y() +
526 auto_driving_car->set_heading(pose.heading());
529 auto_driving_car->set_speed_acceleration(CalculateAcceleration(
530 pose.linear_acceleration(), pose.linear_velocity(), gear_location_));
536 ready_to_push_.store(
true);
540void SimulationWorldService::UpdateSimulationWorld(
const Gps &gps) {
542 Object *shadow_localization_position = world_.mutable_shadow_localization();
544 shadow_localization_position->set_position_x(pose.position().x() +
546 shadow_localization_position->set_position_y(pose.position().y() +
548 shadow_localization_position->set_heading(pose.heading());
550 Object *gps_position = world_.mutable_gps();
554 gps_position->set_position_x(pose.position().x() +
556 gps_position->set_position_y(pose.position().y() +
560 pose.orientation().qw(), pose.orientation().qx(),
561 pose.orientation().qy(), pose.orientation().qz());
562 gps_position->set_heading(heading);
567void SimulationWorldService::UpdateSimulationWorld(
const Chassis &chassis) {
569 Object *auto_driving_car = world_.mutable_auto_driving_car();
576 auto_driving_car->set_speed(speed);
582 if (angle_percentage > 100 || angle_percentage < -100) {
583 angle_percentage = 0;
585 auto_driving_car->set_steering_percentage(angle_percentage);
587 double steering_angle =
588 angle_percentage / 100.0 * vehicle_param.max_steer_angle();
589 auto_driving_car->set_steering_angle(steering_angle);
591 double kappa = std::tan(steering_angle / vehicle_param.steer_ratio()) /
592 vehicle_param.wheel_base();
593 auto_driving_car->set_kappa(kappa);
595 UpdateTurnSignal(chassis.
signal(), auto_driving_car);
597 auto_driving_car->set_disengage_type(DeduceDisengageType(chassis));
600 auto_driving_car->set_gear_location(chassis.
gear_location());
604void SimulationWorldService::UpdateSimulationWorld(
const Stories &stories) {
605 world_.clear_stories();
606 auto *world_stories = world_.mutable_stories();
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);
620void SimulationWorldService::UpdateSimulationWorld(
622 world_.set_is_siren_on(audio_detection.
is_siren());
625Object &SimulationWorldService::CreateWorldObjectIfAbsent(
627 const std::string
id = std::to_string(obstacle.
id());
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);
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);
653void SimulationWorldService::SetObstacleInfo(
const PerceptionObstacle &obstacle,
654 Object *world_object) {
655 if (world_object ==
nullptr) {
659 world_object->set_id(std::to_string(obstacle.id()));
660 world_object->set_position_x(obstacle.position().x() +
662 world_object->set_position_y(obstacle.position().y() +
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()
677void SimulationWorldService::SetObstaclePolygon(
678 const PerceptionObstacle &obstacle, Object *world_object) {
679 if (world_object ==
nullptr) {
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()) {
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);
698void SimulationWorldService::SetObstacleSensorMeasurements(
699 const PerceptionObstacle &obstacle, Object *world_object) {
700 if (world_object ==
nullptr) {
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);
710void SimulationWorldService::SetObstacleSource(
712 Object *world_object) {
713 if (world_object ==
nullptr || !obstacle.has_source()) {
717 world_object->set_source(obstacle_source);
718 world_object->clear_v2x_info();
720 world_object->mutable_v2x_info()->CopyFrom(obstacle.
v2x_info());
726void SimulationWorldService::UpdateSimulationWorld(
729 auto &world_obj = CreateWorldObjectIfAbsent(obstacle);
730 if (obstacles.has_cipv_info() &&
732 world_obj.set_type(Object_Type_CIPV);
736 if (obstacles.has_lane_marker()) {
737 world_.mutable_lane_marker()->CopyFrom(obstacles.
lane_marker());
742void SimulationWorldService::UpdateSimulationWorld(
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()));
752void SimulationWorldService::UpdatePlanningTrajectory(
755 world_.clear_planning_trajectory();
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() +
762 trajectory_point->set_position_y(point.path_point().y() +
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());
773 if (trajectory.has_engage_advice()) {
774 world_.set_engage_advice(
780 std::stringstream ss;
781 ss << std::fixed << std::setprecision(2) << data;
785void SimulationWorldService::UpdateRSSInfo(
const ADCTrajectory &trajectory) {
786 if (trajectory.has_rss_info()) {
787 if (trajectory.rss_info().is_rss_safe()) {
790 world_.set_is_rss_safe(
true);
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();
797 if (std::fabs(current_real_dist_ - next_real_dist) <
799 std::fabs(current_rss_safe_dist_ - next_rss_safe_dist) <
805 "RSS unsafe: \ncurrent distance: " +
807 "\nsafe distance: " +
809 world_.set_is_rss_safe(
false);
810 current_real_dist_ = next_real_dist;
811 current_rss_safe_dist_ = next_rss_safe_dist;
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();
823 if (main_decision.has_not_ready()) {
830 }
else if (main_decision.has_estop()) {
837 world_.mutable_auto_driving_car()->set_current_signal(
"EMERGENCY");
840 const apollo::planning::MainStop &stop = main_decision.stop();
843 stop_heading = stop.stop_heading();
844 if (stop.has_reason_code()) {
845 SetStopReason(stop.reason_code(), decision);
849 decision->set_position_x(stop_pt.
x());
850 decision->set_position_y(stop_pt.
y());
851 decision->set_heading(stop_heading);
854bool SimulationWorldService::LocateMarker(
855 const apollo::planning::ObjectDecisionType &decision,
856 Decision *world_decision) {
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();
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);
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());
895 const std::vector<apollo::common::math::Vec2d> &nudge_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());
902 world_decision->set_type(Decision_Type_NUDGE);
905void SimulationWorldService::UpdateDecision(
const DecisionResult &decision_res,
906 double header_time) {
908 UpdateTurnSignal(decision_res.vehicle_signal(),
909 world_.mutable_auto_driving_car());
911 const auto &main_decision = decision_res.main_decision();
914 if (main_decision.target_lane_size() > 0) {
915 world_.set_speed_limit(main_decision.target_lane(0).speed_limit());
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);
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);
930 if (world_main_decision->decision_size() > 0) {
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);
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";
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;
958 if (decision.has_stop()) {
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);
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";
974 AWARN <<
"No polygon points found for object id=" << id;
978 FindNudgeRegion(decision, world_obj, world_decision);
982 world_obj.set_timestamp_sec(
983 std::max(world_obj.timestamp_sec(), header_time));
988void SimulationWorldService::DownsamplePath(
const common::Path &path,
989 common::Path *downsampled_path) {
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));
999void SimulationWorldService::UpdatePlanningData(
const PlanningData &data) {
1000 auto *planning_data = world_.mutable_planning_data();
1002 size_t max_interval = 10;
1005 if (data.has_scenario()) {
1006 planning_data->mutable_scenario()->CopyFrom(data.scenario());
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()]);
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() +
1024 world_obj_path_point->set_y(planning_path_point.y() +
1026 world_obj_path_point->set_theta(planning_path_point.theta());
1030 planning_data->mutable_chart()->CopyFrom(data.chart());
1033 planning_data->mutable_sl_frame()->CopyFrom(data.sl_frame());
1036 if (data.has_dp_poly_graph()) {
1037 planning_data->mutable_dp_poly_graph()->CopyFrom(data.dp_poly_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());
1050 if (graph.has_kernel_follow_ref()) {
1051 st_graph->mutable_kernel_follow_ref()->CopyFrom(
1052 graph.kernel_follow_ref());
1054 if (graph.has_speed_constraint()) {
1055 st_graph->mutable_speed_constraint()->CopyFrom(graph.speed_constraint());
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());
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());
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());
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());
1095 planning_data->clear_path();
1096 for (
auto &path : data.path()) {
1097 DownsamplePath(path, planning_data->add_path());
1101 planning_data->clear_pull_over();
1102 if (data.has_pull_over()) {
1103 planning_data->mutable_pull_over()->CopyFrom(data.pull_over());
1107 world_.clear_traffic_signal();
1108 if (data.has_signal_light() && data.signal_light().signal_size() > 0) {
1110 int green_light_count = 0;
1112 for (
auto &signal : data.signal_light().signal()) {
1113 switch (signal.color()) {
1117 current_signal = signal.color();
1120 green_light_count++;
1127 if (green_light_count == data.signal_light().signal_size()) {
1131 world_.mutable_traffic_signal()->set_current_signal(
1132 TrafficLight_Color_Name(current_signal));
1137void SimulationWorldService::UpdateSimulationWorld(
1141 UpdatePlanningTrajectory(trajectory);
1143 UpdateRSSInfo(trajectory);
1145 UpdateDecision(trajectory.
decision(), header_time);
1150 latency.set_timestamp_sec(header_time);
1152 (*world_.mutable_latency())[
"planning"] = latency;
1155void SimulationWorldService::CreatePredictionTrajectory(
1157 for (
const auto &traj : obstacle.trajectory()) {
1158 Prediction *prediction = world_object->add_prediction();
1159 prediction->set_probability(traj.probability());
1161 std::vector<PathPoint> points;
1162 for (
const auto &point : traj.trajectory_point()) {
1163 points.push_back(point.path_point());
1165 auto sampled_indices = DownsampleByAngle(points, kAngleThreshold);
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());
1173 const TrajectoryPoint &traj_point = traj.trajectory_point(index);
1174 if (traj_point.has_gaussian_info()) {
1176 traj_point.gaussian_info();
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());
1188void SimulationWorldService::UpdateSimulationWorld(
1198 CreatePredictionTrajectory(obstacle, &world_obj);
1201 if (obstacle.has_priority()) {
1202 world_obj.mutable_obstacle_priority()->CopyFrom(obstacle.
priority());
1206 if (obstacle.has_interactive_tag()) {
1207 world_obj.mutable_interactive_tag()->CopyFrom(obstacle.
interactive_tag());
1210 world_obj.set_timestamp_sec(
1211 std::max(obstacle.
timestamp(), world_obj.timestamp_sec()));
1216void SimulationWorldService::UpdateSimulationWorld(
1220 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1221 if (world_.has_routing_time() &&
1228 std::vector<Path> paths;
1233 world_.clear_route_path();
1235 std::vector<RoutePath> route_paths;
1236 for (
const Path &path : paths) {
1238 auto sampled_indices =
1239 DownsampleByAngle(path.path_points(), kAngleThreshold);
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];
1246 route_point->set_x(path_point.x() + map_service_->
GetXOffset());
1247 route_point->set_y(path_point.y() + map_service_->
GetYOffset());
1251 if (FLAGS_sim_world_with_routing_path) {
1252 auto *new_path = world_.add_route_path();
1253 *new_path = *route_path;
1257 boost::unique_lock<boost::shared_mutex> writer_lock(route_paths_mutex_);
1258 std::swap(route_paths, route_paths_);
1265 response[
"routePath"] = Json::array();
1266 std::vector<RoutePath> route_paths;
1268 boost::shared_lock<boost::shared_mutex> reader_lock(route_paths_mutex_);
1270 route_paths = route_paths_;
1272 for (
const auto &route_path : route_paths) {
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()}});
1280 response[
"routePath"].push_back(path);
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;
1293 AINFO <<
"Loaded planning command from " << planning_command_file;
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.";
1305void SimulationWorldService::UpdateSimulationWorld(
1307 auto *control_data = world_.mutable_control_data();
1309 control_data->set_timestamp_sec(header_time);
1312 latency.set_timestamp_sec(header_time);
1314 (*world_.mutable_latency())[
"control"] = latency;
1316 if (control_command.has_debug()) {
1317 auto &debug = control_command.
debug();
1318 if (debug.has_simple_lon_debug() && debug.has_simple_lat_debug()) {
1320 if (simple_lon.has_station_error()) {
1321 control_data->set_station_error(simple_lon.station_error());
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());
1327 if (simple_lat.has_lateral_error()) {
1328 control_data->set_lateral_error(simple_lat.lateral_error());
1330 if (simple_lat.has_current_target_point()) {
1331 control_data->mutable_current_target_point()->CopyFrom(
1332 simple_lat.current_target_point());
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());
1339 if (simple_mpc.has_heading_error()) {
1340 control_data->set_heading_error(simple_mpc.heading_error());
1342 if (simple_mpc.has_lateral_error()) {
1343 control_data->set_lateral_error(simple_mpc.lateral_error());
1350void SimulationWorldService::UpdateSimulationWorld(
1352 world_.clear_navigation_path();
1354 if (navigation_path.has_path()) {
1355 DownsamplePath(navigation_path.path(), world_.add_navigation_path());
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();
1371 DownsampleCurve(lane->mutable_central_curve());
1372 DownsampleCurve(lane->mutable_left_boundary()->mutable_curve());
1373 DownsampleCurve(lane->mutable_right_boundary()->mutable_curve());
1379void SimulationWorldService::UpdateSimulationWorld(
1381 const int updated_size = std::min(monitor_msg.item_size(),
1384 for (
int idx = 0; idx < updated_size; ++idx) {
1385 auto *notification = world_.add_notification();
1386 notification->mutable_item()->CopyFrom(monitor_msg.
item(idx));
1392 if (remove_size > 0) {
1393 auto *notifications = world_.mutable_notification();
1394 notifications->erase(notifications->begin(),
1395 notifications->begin() + remove_size);
1399void SimulationWorldService::UpdateMonitorMessages() {
1400 std::list<std::shared_ptr<MonitorMessage>> monitor_msgs;
1402 std::unique_lock<std::mutex> lock(monitor_msgs_mutex_);
1403 monitor_msgs = monitor_msgs_;
1404 monitor_msgs_.clear();
1407 for (
const auto &monitor_msg : monitor_msgs) {
1408 UpdateSimulationWorld(*monitor_msg);
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());
1427 const std::shared_ptr<NavigationInfo> &navigation_info) {
1428 FillHeader(FLAGS_dreamview_module_name, navigation_info.get());
1429 navigation_writer_->Write(navigation_info);
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);
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);
1445 const std::shared_ptr<ActionCommand> &action_command) {
1446 FillHeader(FLAGS_dreamview_module_name, action_command.get());
1447 action_command_client_->SendRequest(action_command);
1451 FillHeader(FLAGS_dreamview_module_name, task.get());
1452 task_writer_->Write(task);
1457 const std::string &msg) {
1459 monitor_logger_buffer_.
Publish();
@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.
Polygon2d ExpandByDistance(const double distance) const
Expand this polygon by a distance.
const std::vector< Vec2d > & points() const
Get the vertices of the polygon.
Implements a class of 2-dimensional vectors.
void set_x(const double x)
Setter for x component
double y() const
Getter for y component
double x() const
Getter for x component
void set_y(const double y)
Setter for y component
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.
static Time Now()
PRECISION >= 1000000 means the precision is at least 1us.
double ToSecond() const
convert time to second.
double GetYOffset() const
double GetXOffset() const
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
nlohmann::json GetRoutePathAsJson() const
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 > &)
static constexpr int kMaxMonitorItems
constexpr double kMathEpsilon
double QuaternionToHeading(const double qw, const double qx, const double qy, const double qz)
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,...
std::string formatDoubleToString(const double data)
Contains a number of helper functions related to quaternions.
optional GearPosition gear_location
optional apollo::common::VehicleSignal signal
optional float steering_percentage
optional float brake_percentage
optional int32 battery_soc_percentage
optional float throttle_percentage
optional VehicleParam vehicle_param
optional bool emergency_light
optional TurnSignal turn_signal
repeated MonitorMessageItem item
optional apollo::common::Header header
optional apollo::common::Header header
optional LatencyStats latency_stats
optional SimpleLongitudinalDebug simple_lon_debug
optional double total_time_ms
@ STOP_REASON_DESTINATION
@ STOP_REASON_HEAD_VEHICLE
optional double position_x
@ DISENGAGE_AUTO_STEER_ONLY
@ DISENGAGE_CHASSIS_ERROR
@ DISENGAGE_AUTO_SPEED_ONLY
optional double position_y
optional MapElementIds map_element_ids
optional Object auto_driving_car
optional uint32 sequence_num
optional double routing_time
optional bool is_rss_safe
optional apollo::common::Header header
optional apollo::localization::Pose localization
optional apollo::localization::Pose pose
optional apollo::common::Header header
optional V2XInformation v2x_info
optional SubType sub_type
optional LaneMarkers lane_marker
repeated PerceptionObstacle perception_obstacle
optional CIPVInfo cipv_info
repeated TrafficLight traffic_light
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 double total_time_ms
optional apollo::common::Header header
optional apollo::routing::RoutingResponse lane_follow_command
optional PlanningData planning_data
optional ObstacleInteractiveTag interactive_tag
optional apollo::perception::PerceptionObstacle perception_obstacle
optional ObstaclePriority priority
optional double timestamp
repeated PredictionObstacle prediction_obstacle
optional apollo::hdmap::Map hdmap
repeated NavigationPath navigation_path