Apollo 10.0
自动驾驶开放平台
simulation_world_updater.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 "google/protobuf/util/json_util.h"
20
21#include "cyber/common/file.h"
28
29namespace apollo {
30namespace dreamview {
31
33using apollo::common::util::ContainsKey;
51
52using Json = nlohmann::json;
53using google::protobuf::util::JsonStringToMessage;
54using google::protobuf::util::MessageToJsonString;
55
57 WebSocketHandler *websocket, WebSocketHandler *map_ws,
58 WebSocketHandler *camera_ws,
59 WebSocketHandler *plugin_ws, const MapService *map_service,
60 PerceptionCameraUpdater *perception_camera_updater,
61 PluginManager *plugin_manager, bool routing_from_file)
62 : sim_world_service_(map_service, routing_from_file),
63 map_service_(map_service),
64 websocket_(websocket),
65 map_ws_(map_ws),
66 camera_ws_(camera_ws),
67 plugin_ws_(plugin_ws),
68 perception_camera_updater_(perception_camera_updater),
69 plugin_manager_(plugin_manager),
70 command_id_(0) {
71 RegisterMessageHandlers();
72}
73
74void SimulationWorldUpdater::RegisterMessageHandlers() {
75 // Send current sim_control status to the new client.
77 [this](WebSocketHandler::Connection *conn) {
78 Json response;
79 response["type"] = "SimControlStatus";
80 response["enabled"] = SimControlManager::Instance()->IsEnabled();
81 websocket_->SendData(conn, response.dump());
82 });
83
85 "RetrieveMapData",
86 [this](const Json &json, WebSocketHandler::Connection *conn) {
87 auto iter = json.find("elements");
88 if (iter != json.end()) {
89 MapElementIds map_element_ids;
90 if (JsonStringToMessage(iter->dump(), &map_element_ids).ok()) {
91 auto retrieved = map_service_->RetrieveMapElements(map_element_ids);
92
93 std::string retrieved_map_string;
94 retrieved.SerializeToString(&retrieved_map_string);
95
96 map_ws_->SendBinaryData(conn, retrieved_map_string, true);
97 } else {
98 AERROR << "Failed to parse MapElementIds from json";
99 }
100 }
101 });
102
103 map_ws_->RegisterMessageHandler(
104 "RetrieveRelativeMapData",
105 [this](const Json &json, WebSocketHandler::Connection *conn) {
106 std::string to_send;
107 {
108 boost::shared_lock<boost::shared_mutex> reader_lock(mutex_);
109 to_send = relative_map_string_;
110 }
111 map_ws_->SendBinaryData(conn, to_send, true);
112 });
113
114 websocket_->RegisterMessageHandler(
115 "Binary",
116 [this](const std::string &data, WebSocketHandler::Connection *conn) {
117 // Navigation info in binary format
118 auto navigation_info = std::make_shared<NavigationInfo>();
119 if (navigation_info->ParseFromString(data)) {
120 sim_world_service_.PublishNavigationInfo(navigation_info);
121 } else {
122 AERROR << "Failed to parse navigation info from string. String size: "
123 << data.size();
124 }
125 });
126
127 websocket_->RegisterMessageHandler(
128 "RetrieveMapElementIdsByRadius",
129 [this](const Json &json, WebSocketHandler::Connection *conn) {
130 auto radius = json.find("radius");
131 if (radius == json.end()) {
132 AERROR << "Cannot retrieve map elements with unknown radius.";
133 return;
134 }
135
136 if (!radius->is_number()) {
137 AERROR << "Expect radius with type 'number', but was "
138 << radius->type_name();
139 return;
140 }
141
142 Json response;
143 response["type"] = "MapElementIds";
144 response["mapRadius"] = *radius;
145
146 MapElementIds ids;
147 sim_world_service_.GetMapElementIds(*radius, &ids);
148 std::string elementIds;
149 MessageToJsonString(ids, &elementIds);
150 response["mapElementIds"] = Json::parse(elementIds);
151
152 websocket_->SendData(conn, response.dump());
153 });
154
155 websocket_->RegisterMessageHandler(
156 "CheckRoutingPoint",
157 [this](const Json &json, WebSocketHandler::Connection *conn) {
158 Json response = CheckRoutingPoint(json);
159 response["type"] = "RoutingPointCheckResult";
160 websocket_->SendData(conn, response.dump());
161 });
162
163 websocket_->RegisterMessageHandler(
164 "SetStartPoint",
165 [this](const Json &json, WebSocketHandler::Connection *conn) {
166 auto point = json["point"];
167 if (!SimControlManager::Instance()->IsEnabled()) {
168 AWARN << "Set start point need start sim_control.";
169 } else {
170 if (!ContainsKey(point, "heading")) {
171 AWARN << "Set start point need set heading.";
172 return;
173 }
174 SimControlManager::Instance()->ReSetPoinstion(point["x"], point["y"],
175 point["heading"]);
176
177 // Send a ActionCommand to clear the trajectory of planning.
178 if (isProcessRunning("planning.dag")) {
179 auto action_command = std::make_shared<ActionCommand>();
180 action_command->set_command_id(++command_id_);
181 action_command->set_command(ActionCommandType::CLEAR_PLANNING);
182 sim_world_service_.PublishActionCommand(action_command);
183 }
184 }
185 });
186
187 websocket_->RegisterMessageHandler(
188 "SendRoutingRequest",
189 [this](const Json &json, WebSocketHandler::Connection *conn) {
190 auto lane_follow_command = std::make_shared<LaneFollowCommand>();
191 bool succeed =
192 ConstructLaneFollowCommand(json, lane_follow_command.get());
193 if (succeed) {
194 sim_world_service_.PublishLaneFollowCommand(lane_follow_command);
196 "Lane follow command sent.");
197 } else {
198 sim_world_service_.PublishMonitorMessage(
200 "Failed to send a Lane follow command.");
201 }
202 });
203
204 websocket_->RegisterMessageHandler(
205 "SendDefaultCycleRoutingRequest",
206 [this](const Json &json, WebSocketHandler::Connection *conn) {
207 auto task = std::make_shared<Task>();
208 auto *cycle_routing_task = task->mutable_cycle_routing_task();
209 auto *lane_follow_command =
210 cycle_routing_task->mutable_lane_follow_command();
211 if (!ContainsKey(json, "cycleNumber") ||
212 !json.find("cycleNumber")->is_number()) {
213 AERROR
214 << "Failed to prepare a cycle lane follow command: Invalid cycle "
215 "number";
216 return;
217 }
218 bool succeed = ConstructLaneFollowCommand(json, lane_follow_command);
219 if (succeed) {
220 cycle_routing_task->set_cycle_num(
221 static_cast<int>(json["cycleNumber"]));
222 task->set_task_name("cycle_routing_task");
224 sim_world_service_.PublishTask(task);
225 AINFO << "The task is : " << task->DebugString();
226 sim_world_service_.PublishMonitorMessage(
228 "Default cycle lane follow command sent.");
229 } else {
230 sim_world_service_.PublishMonitorMessage(
232 "Failed to send a default cycle lane follow command.");
233 }
234 });
235
236 // websocket_->RegisterMessageHandler(
237 // "SendParkGoRoutingRequest",
238 // [this](const Json &json, WebSocketHandler::Connection *conn) {
239 // auto task = std::make_shared<Task>();
240 // auto *park_go_routing_task = task->mutable_park_go_routing_task();
241 // if (!ContainsKey(json, "parkTime") ||
242 // !json.find("parkTime")->is_number()) {
243 // AERROR << "Failed to prepare a park go routing request: Invalid
244 // park "
245 // "time";
246 // return;
247 // }
248 // bool succeed = ConstructRoutingRequest(
249 // json, park_go_routing_task->mutable_routing_request());
250 // if (succeed) {
251 // park_go_routing_task->set_park_time(
252 // static_cast<int>(json["parkTime"]));
253 // task->set_task_name("park_go_routing_task");
254 // task->set_task_type(apollo::task_manager::TaskType::PARK_GO_ROUTING);
255 // sim_world_service_.PublishTask(task);
256 // AINFO << "The task is : " << task->DebugString();
257 // sim_world_service_.PublishMonitorMessage(
258 // MonitorMessageItem::INFO, "Park go routing request sent.");
259 // } else {
260 // sim_world_service_.PublishMonitorMessage(
261 // MonitorMessageItem::ERROR,
262 // "Failed to send a park go routing request.");
263 // }
264 // });
265
266 websocket_->RegisterMessageHandler(
267 "SendParkingRoutingRequest",
268 [this](const Json &json, WebSocketHandler::Connection *conn) {
269 auto valet_parking_command = std::make_shared<ValetParkingCommand>();
270 bool succeed =
271 ConstructValetParkingCommand(json, valet_parking_command.get());
272 if (succeed) {
273 sim_world_service_.PublishValetParkingCommand(valet_parking_command);
274 sim_world_service_.PublishMonitorMessage(
275 MonitorMessageItem::INFO, "Valet parking command sent.");
276 } else {
277 sim_world_service_.PublishMonitorMessage(
279 "Failed to send a Valet parking command.");
280 }
281 });
282
283 websocket_->RegisterMessageHandler(
284 "RequestSimulationWorld",
285 [this](const Json &json, WebSocketHandler::Connection *conn) {
286 if (!sim_world_service_.ReadyToPush()) {
287 AWARN_EVERY(100)
288 << "Not sending simulation world as the data is not ready!";
289 return;
290 }
291
292 bool enable_pnc_monitor = false;
293 auto planning = json.find("planning");
294 if (planning != json.end() && planning->is_boolean()) {
295 enable_pnc_monitor = json["planning"];
296 }
297 std::string to_send;
298 {
299 // Pay the price to copy the data instead of sending data over the
300 // wire while holding the lock.
301 boost::shared_lock<boost::shared_mutex> reader_lock(mutex_);
302 to_send = enable_pnc_monitor ? simulation_world_with_planning_data_
303 : simulation_world_;
304 }
305 if (FLAGS_enable_update_size_check && !enable_pnc_monitor &&
306 to_send.size() > FLAGS_max_update_size) {
307 AWARN << "update size is too big:" << to_send.size();
308 return;
309 }
310 websocket_->SendBinaryData(conn, to_send, true);
311 });
312
313 websocket_->RegisterMessageHandler(
314 "RequestRoutePath",
315 [this](const Json &json, WebSocketHandler::Connection *conn) {
316 Json response = sim_world_service_.GetRoutePathAsJson();
317 response["type"] = "RoutePath";
318 websocket_->SendData(conn, response.dump());
319 });
320
321 websocket_->RegisterMessageHandler(
322 "GetDefaultEndPoint",
323 [this](const Json &json, WebSocketHandler::Connection *conn) {
324 Json response;
325 response["type"] = "DefaultEndPoint";
326
327 Json poi_list = Json::array();
328 if (LoadPOI()) {
329 for (const auto &landmark : poi_.landmark()) {
330 Json place;
331 place["name"] = landmark.name();
332
333 Json parking_info =
335 "parkingInfo", landmark.parking_info());
336 place["parkingInfo"] = parking_info["data"];
337
338 Json waypoint_list;
339 for (const auto &waypoint : landmark.waypoint()) {
340 waypoint_list.push_back(GetPointJsonFromLaneWaypoint(waypoint));
341 }
342 place["waypoint"] = waypoint_list;
343
344 poi_list.push_back(place);
345 }
346 } else {
348 "Failed to load default "
349 "POI. Please make sure the "
350 "file exists at " +
352 }
353 response["poi"] = poi_list;
354 websocket_->SendData(conn, response.dump());
355 });
356
357 websocket_->RegisterMessageHandler(
358 "GetDefaultRoutings",
359 [this](const Json &json, WebSocketHandler::Connection *conn) {
360 Json response;
361 response["type"] = "DefaultRoutings";
362 response["threshold"] =
363 FLAGS_loop_routing_end_to_start_distance_threshold;
364
365 Json default_routing_list = Json::array();
366 if (LoadUserDefinedRoutings(DefaultRoutingFile(), &default_routings_)) {
367 for (const auto &landmark : default_routings_.landmark()) {
368 Json drouting;
369 drouting["name"] = landmark.name();
370
371 Json point_list;
372 for (const auto &point : landmark.waypoint()) {
373 point_list.push_back(GetPointJsonFromLaneWaypoint(point));
374 }
375 drouting["point"] = point_list;
376 default_routing_list.push_back(drouting);
377 }
378 } else {
379 sim_world_service_.PublishMonitorMessage(
381 "Failed to load default "
382 "routing. Please make sure the "
383 "file exists at " +
385 }
386 response["defaultRoutings"] = default_routing_list;
387 websocket_->SendData(conn, response.dump());
388 });
389
390 websocket_->RegisterMessageHandler(
391 "GetParkAndGoRoutings",
392 [this](const Json &json, WebSocketHandler::Connection *conn) {
393 Json response;
394 response["type"] = "ParkAndGoRoutings";
395 Json park_go_routing_list = Json::array();
396 if (LoadUserDefinedRoutings(ParkGoRoutingFile(), &park_go_routings_)) {
397 for (const auto &landmark : park_go_routings_.landmark()) {
398 Json park_go_routing;
399 park_go_routing["name"] = landmark.name();
400
401 Json point_list;
402 for (const auto &point : landmark.waypoint()) {
403 point_list.push_back(GetPointJsonFromLaneWaypoint(point));
404 }
405 park_go_routing["point"] = point_list;
406 park_go_routing_list.push_back(park_go_routing);
407 }
408 // } else {
409 // sim_world_service_.PublishMonitorMessage(
410 // MonitorMessageItem::ERROR,
411 // "Failed to load park go "
412 // "routing. Please make sure the "
413 // "file exists at " +
414 // ParkGoRoutingFile());
415 }
416 response["parkAndGoRoutings"] = park_go_routing_list;
417 websocket_->SendData(conn, response.dump());
418 });
419
420 websocket_->RegisterMessageHandler(
421 "Reset", [this](const Json &json, WebSocketHandler::Connection *conn) {
422 sim_world_service_.SetToClear();
423 SimControlManager::Instance()->Reset();
424 });
425
426 websocket_->RegisterMessageHandler(
427 "Dump", [this](const Json &json, WebSocketHandler::Connection *conn) {
428 sim_world_service_.DumpMessages();
429 });
430
431 websocket_->RegisterMessageHandler(
432 "ToggleSimControl",
433 [this](const Json &json, WebSocketHandler::Connection *conn) {
434 auto enable = json.find("enable");
435 if (enable != json.end() && enable->is_boolean()) {
436 if (*enable) {
437 SimControlManager::Instance()->Start();
438 } else {
439 SimControlManager::Instance()->Stop();
440 }
441 }
442 });
443
444 websocket_->RegisterMessageHandler(
445 "RequestDataCollectionProgress",
446 [this](const Json &json, WebSocketHandler::Connection *conn) {
447 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
448 if (monitors) {
449 const auto iter = monitors->find("DataCollectionMonitor");
450 if (iter != monitors->end() && iter->second->IsEnabled()) {
451 Json response;
452 response["type"] = "DataCollectionProgress";
453 response["data"] = iter->second->GetProgressAsJson();
454 websocket_->SendData(conn, response.dump());
455 }
456 }
457 });
458
459 websocket_->RegisterMessageHandler(
460 "GetParkingRoutingDistance",
461 [this](const Json &json, WebSocketHandler::Connection *conn) {
462 Json response;
463 response["type"] = "ParkingRoutingDistance";
464 response["threshold"] = FLAGS_parking_routing_distance_threshold;
465 websocket_->SendData(conn, response.dump());
466 });
467
468 websocket_->RegisterMessageHandler(
469 "RequestPreprocessProgress",
470 [this](const Json &json, WebSocketHandler::Connection *conn) {
471 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
472 if (monitors) {
473 const auto iter = monitors->find("PreprocessMonitor");
474 if (iter != monitors->end() && iter->second->IsEnabled()) {
475 Json response;
476 response["type"] = "PreprocessProgress";
477 response["data"] = iter->second->GetProgressAsJson();
478 websocket_->SendData(conn, response.dump());
479 }
480 }
481 });
482
483 websocket_->RegisterMessageHandler(
484 "SaveDefaultRouting",
485 [this](const Json &json, WebSocketHandler::Connection *conn) {
486 bool succeed = AddDefaultRouting(json);
487 if (succeed) {
488 sim_world_service_.PublishMonitorMessage(
489 MonitorMessageItem::INFO, "Successfully add a routing.");
490 if (!default_routing_) {
491 AERROR << "Failed to add a routing" << std::endl;
492 }
493 Json response = JsonUtil::ProtoToTypedJson("AddDefaultRoutingPath",
494 *default_routing_);
495 response["routingType"] = json["routingType"];
496 websocket_->SendData(conn, response.dump());
497 } else {
499 "Failed to add a routing.");
500 }
501 });
502
503 camera_ws_->RegisterMessageHandler(
504 "RequestCameraData",
505 [this](const Json &json, WebSocketHandler::Connection *conn) {
506 if (!perception_camera_updater_->IsEnabled()) {
507 return;
508 }
509 std::string to_send;
510 perception_camera_updater_->GetUpdate(&to_send);
511 camera_ws_->SendBinaryData(conn, to_send, true);
512 });
513
514 camera_ws_->RegisterMessageHandler(
515 "GetCameraChannel",
516 [this](const Json &json, WebSocketHandler::Connection *conn) {
517 std::vector<std::string> channels;
518 perception_camera_updater_->GetChannelMsg(&channels);
519 Json response({});
520 response["data"]["name"] = "GetCameraChannelListSuccess";
521 for (unsigned int i = 0; i < channels.size(); i++) {
522 response["data"]["info"]["channel"][i] = channels[i];
523 }
524 camera_ws_->SendData(conn, response.dump());
525 });
526 camera_ws_->RegisterMessageHandler(
527 "ChangeCameraChannel",
528 [this](const Json &json, WebSocketHandler::Connection *conn) {
529 if (!perception_camera_updater_->IsEnabled()) {
530 return;
531 }
532 auto channel_info = json.find("data");
533 Json response({});
534 if (channel_info == json.end()) {
535 AERROR << "Cannot retrieve channel info with unknown channel.";
536 response["type"] = "ChangeCameraChannelFail";
537 camera_ws_->SendData(conn, response.dump());
538 return;
539 }
540 std::string channel =
541 channel_info->dump().substr(1, channel_info->dump().length() - 2);
542 if (perception_camera_updater_->ChangeChannel(channel)) {
543 Json response({});
544 response["type"] = "ChangeCameraChannelSuccess";
545 camera_ws_->SendData(conn, response.dump());
546 } else {
547 response["type"] = "ChangeCameraChannelFail";
548 camera_ws_->SendData(conn, response.dump());
549 }
550 });
551 plugin_ws_->RegisterMessageHandler(
552 "PluginRequest",
553 [this](const Json &json, WebSocketHandler::Connection *conn) {
554 if (!plugin_manager_->IsEnabled()) {
555 return;
556 }
557 auto iter = json.find("data");
558 if (iter == json.end()) {
559 AERROR << "Failed to get plugin msg!";
560 return;
561 }
562 if (!plugin_manager_->SendMsgToPlugin(iter->dump())) {
563 AERROR << "Failed to send msg to plugin";
564 }
565 });
566}
567
568Json SimulationWorldUpdater::CheckRoutingPoint(const Json &json) {
569 Json result;
570 if (!ContainsKey(json, "point")) {
571 result["error"] = "Failed to check routing point: point not found.";
572 AERROR << result["error"];
573 return result;
574 }
575 auto point = json["point"];
576 if (!ValidateCoordinate(point) || !ContainsKey(point, "id")) {
577 result["error"] = "Failed to check routing point: invalid point.";
578 AERROR << result["error"];
579 return result;
580 }
581 if (!ContainsKey(point, "heading")) {
582 if (!map_service_->CheckRoutingPoint(point["x"], point["y"])) {
583 result["pointId"] = point["id"];
584 result["error"] = "Selected point cannot be a routing point.";
585 AWARN << result["error"];
586 }
587 } else {
588 if (!map_service_->CheckRoutingPointWithHeading(point["x"], point["y"],
589 point["heading"])) {
590 result["pointId"] = point["id"];
591 result["error"] = "Selected point cannot be a routing point.";
592 AWARN << result["error"];
593 }
594 }
595 return result;
596}
597
598Json SimulationWorldUpdater::GetPointJsonFromLaneWaypoint(
599 const apollo::routing::LaneWaypoint &waypoint) {
600 Json point;
601 point["x"] = waypoint.pose().x();
602 point["y"] = waypoint.pose().y();
603 if (waypoint.has_heading()) {
604 point["heading"] = waypoint.heading();
605 }
606 return point;
607}
608
609bool SimulationWorldUpdater::ConstructLaneWayPoint(const Json &point,
610 LaneWaypoint *laneWayPoint,
611 std::string description) {
612 if (ContainsKey(point, "heading")) {
613 if (!map_service_->ConstructLaneWayPointWithHeading(
614 point["x"], point["y"], point["heading"], laneWayPoint)) {
615 AERROR << "Failed to prepare a routing request with heading: "
616 << point["heading"] << " cannot locate " << description
617 << " on map.";
618 return false;
619 }
620 } else {
621 if (!map_service_->ConstructLaneWayPoint(point["x"], point["y"],
622 laneWayPoint)) {
623 AERROR << "Failed to prepare a routing request:"
624 << " cannot locate " << description << " on map.";
625 return false;
626 }
627 }
628 return true;
629}
630
631bool SimulationWorldUpdater::ConstructLaneFollowCommand(
632 const Json &json, LaneFollowCommand *lane_follow_command) {
633 lane_follow_command->set_command_id(++command_id_);
634
635 auto iter = json.find("waypoint");
636 if (iter != json.end() && iter->is_array()) {
637 auto waypoint = lane_follow_command->mutable_way_point();
638 for (size_t i = 0; i < iter->size(); ++i) {
639 auto &point = (*iter)[i];
640 auto *pose = waypoint->Add();
641 if (ContainsKey(point, "heading")) {
642 pose->set_heading(point["heading"]);
643 }
644 pose->set_x(point["x"]);
645 pose->set_y(point["y"]);
646 }
647 }
648
649 // set end point
650 if (!ContainsKey(json, "end")) {
651 AERROR << "Failed to prepare a routing request: end point not found.";
652 return false;
653 }
654
655 auto end = json["end"];
656 if (!ValidateCoordinate(end)) {
657 AERROR << "Failed to prepare a routing request: invalid end point.";
658 return false;
659 }
660 auto end_pose = lane_follow_command->mutable_end_pose();
661 end_pose->Clear();
662 if (ContainsKey(end, "heading")) {
663 end_pose->set_heading(end["heading"]);
664 }
665 end_pose->set_x(end["x"]);
666 end_pose->set_y(end["y"]);
667
668 AINFO << "Constructed LaneFollowCommand to be sent:\n"
669 << lane_follow_command->DebugString();
670
671 return true;
672}
673
674bool SimulationWorldUpdater::ConstructValetParkingCommand(
675 const Json &json, ValetParkingCommand *valet_parking_command) {
676 valet_parking_command->clear_parking_spot_id();
677 valet_parking_command->set_command_id(++command_id_);
678 if (ContainsKey(json, "parkingInfo")) {
679 auto parkingInfo = json["parkingInfo"];
680 valet_parking_command->set_parking_spot_id(parkingInfo["parkingSpaceId"]);
681 } else {
682 return false;
683 }
684 AINFO << "Constructed ValetParkingCommand to be sent:\n"
685 << valet_parking_command->DebugString();
686 return true;
687}
688
689Json SimulationWorldUpdater::GetConstructRoutingRequestJson(
690 const nlohmann::json &start, const nlohmann::json &end) {
691 Json result;
692 result["start"] = start;
693 result["end"] = end;
694 return result;
695}
696
697bool SimulationWorldUpdater::ValidateCoordinate(const nlohmann::json &json) {
698 if (!ContainsKey(json, "x") || !ContainsKey(json, "y")) {
699 AERROR << "Failed to find x or y coordinate.";
700 return false;
701 }
702 if (json.find("x")->is_number() && json.find("y")->is_number()) {
703 return true;
704 }
705 AERROR << "Both x and y coordinate should be a number.";
706 return false;
707}
708
710 timer_.reset(new cyber::Timer(
711 kSimWorldTimeIntervalMs, [this]() { this->OnTimer(); }, false));
712 timer_->Start();
713}
714
715void SimulationWorldUpdater::OnTimer() {
716 sim_world_service_.Update();
717
718 {
719 boost::unique_lock<boost::shared_mutex> writer_lock(mutex_);
720 last_pushed_adc_timestamp_sec_ =
721 sim_world_service_.world().auto_driving_car().timestamp_sec();
722 sim_world_service_.GetWireFormatString(
723 FLAGS_sim_map_radius, &simulation_world_,
724 &simulation_world_with_planning_data_);
725 sim_world_service_.GetRelativeMap().SerializeToString(
726 &relative_map_string_);
727 }
728}
729
730bool SimulationWorldUpdater::LoadPOI() {
731 if (GetProtoFromASCIIFile(EndWayPointFile(), &poi_)) {
732 return true;
733 }
734
735 AWARN << "Failed to load default list of POI from " << EndWayPointFile();
736 return false;
737}
738
739bool SimulationWorldUpdater::isProcessRunning(const std::string &process_name) {
740 std::stringstream commandStream;
741 commandStream << "pgrep -f " << process_name;
742 std::string command = commandStream.str();
743
744 FILE *fp = popen(command.c_str(), "r");
745 if (fp) {
746 char result[128];
747 if (fgets(result, sizeof(result), fp) != nullptr) {
748 AINFO << process_name << " is running";
749 pclose(fp);
750 return true;
751 } else {
752 AINFO << process_name << " is not running";
753 }
754 pclose(fp);
755 }
756 return false;
757}
758
759bool SimulationWorldUpdater::LoadUserDefinedRoutings(
760 const std::string &file_name, google::protobuf::Message *message) {
761 if (GetProtoFromASCIIFile(file_name, message)) {
762 return true;
763 }
764
765 AWARN << "Failed to load routings from " << file_name;
766 return false;
767}
768
769bool SimulationWorldUpdater::AddDefaultRouting(const Json &json) {
770 if (!ContainsKey(json, "name")) {
771 AERROR << "Failed to save a routing: routing name not found.";
772 return false;
773 }
774
775 if (!ContainsKey(json, "point")) {
776 AERROR << "Failed to save a routing: routing points not "
777 "found.";
778 return false;
779 }
780
781 if (!ContainsKey(json, "routingType")) {
782 AERROR << "Failed to save a routing: routing type not "
783 "found.";
784 return false;
785 }
786
787 std::string name = json["name"];
788 auto iter = json.find("point");
789 std::string routingType = json["routingType"];
790 bool isDefaultRouting = (routingType == "defaultRouting");
791 default_routing_ = isDefaultRouting ? default_routings_.add_landmark()
792 : park_go_routings_.add_landmark();
793 default_routing_->clear_name();
794 default_routing_->clear_waypoint();
795 default_routing_->set_name(name);
796 auto *waypoint = default_routing_->mutable_waypoint();
797 if (iter != json.end() && iter->is_array()) {
798 for (size_t i = 0; i < iter->size(); ++i) {
799 auto &point = (*iter)[i];
800 if (!ValidateCoordinate(point)) {
801 AERROR << "Failed to save a routing: invalid waypoint.";
802 return false;
803 }
804 auto *p = waypoint->Add();
805 auto *pose = p->mutable_pose();
806 pose->set_x(static_cast<double>(point["x"]));
807 pose->set_y(static_cast<double>(point["y"]));
808 if (ContainsKey(point, "heading")) {
809 p->set_heading(point["heading"]);
810 }
811 }
812 }
813 AINFO << "User Defined Routing Points to be saved:\n";
814 std::string file_name =
815 isDefaultRouting ? DefaultRoutingFile() : ParkGoRoutingFile();
817 isDefaultRouting ? default_routings_ : park_go_routings_,
818 file_name)) {
819 AERROR << "Failed to set proto to ascii file " << file_name;
820 return false;
821 }
822 AINFO << "Success in setting proto to file" << file_name;
823
824 return true;
825}
826
827} // namespace dreamview
828} // namespace apollo
static nlohmann::json ProtoToTypedJson(const std::string &json_type, const google::protobuf::Message &proto)
Convert proto to a json string.
Definition json_util.cc:37
Used to perform oneshot or periodic timing tasks
Definition timer.h:71
bool CheckRoutingPoint(const double x, const double y) const
bool CheckRoutingPointWithHeading(const double x, const double y, const double heading) const
hdmap::Map RetrieveMapElements(const MapElementIds &ids) const
bool ConstructLaneWayPointWithHeading(const double x, const double y, const double heading, routing::LaneWaypoint *laneWayPoint) const
bool ConstructLaneWayPoint(const double x, const double y, routing::LaneWaypoint *laneWayPoint) const
The function fills out proper routing lane waypoint from the given (x,y) position.
void GetChannelMsg(std::vector< std::string > *channels)
GetChannelMsg
void SetToClear()
Sets the flag to clear the owned simulation world object.
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 > &)
bool ReadyToPush() const
Check whether the SimulationWorld object has enough information.
const apollo::hdmap::Map & GetRelativeMap() const
const SimulationWorld & world() const
Get a read-only view of the SimulationWorld.
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 > &)
void Start()
Starts to push simulation_world to frontend.
SimulationWorldUpdater(WebSocketHandler *websocket, WebSocketHandler *map_ws, WebSocketHandler *camera_ws, WebSocketHandler *plugin_ws, const MapService *map_service, PerceptionCameraUpdater *perception_camera_updater, PluginManager *plugin_manager, bool routing_from_file=false)
Constructor with the websocket handler.
The WebSocketHandler, built on top of CivetWebSocketHandler, is a websocket handler that handles diff...
void RegisterMessageHandler(std::string type, MessageHandler handler)
Add a new message handler for a message type.
bool SendData(Connection *conn, const std::string &data, bool skippable=false, int op_code=MG_WEBSOCKET_OPCODE_TEXT)
Sends the provided data to a specific connected client.
void RegisterConnectionReadyHandler(ConnectionReadyHandler handler)
Add a new handler for new connections.
bool SendBinaryData(Connection *conn, const std::string &data, bool skippable=false)
Planning module main class.
#define AERROR
Definition log.h:44
#define AWARN_EVERY(freq)
Definition log.h:84
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
Some map util functions.
nlohmann::json Json
bool GetProtoFromASCIIFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as ascii representation of protobufs,...
Definition file.cc:89
bool SetProtoToASCIIFile(const google::protobuf::Message &message, int file_descriptor)
Definition file.cc:43
std::string DefaultRoutingFile()
get default routing file path from flags.
Definition hdmap_util.h:68
std::string EndWayPointFile()
get end way point file path from flags.
Definition hdmap_util.h:56
std::string ParkGoRoutingFile()
get park and go routings file path from flags.
Definition hdmap_util.h:76
class register implement
Definition arena_queue.h:37
optional apollo::common::PointENU pose