提交 6211600a 编写于 作者: V vlin17 提交者: Jiangtao Hu

Dreamview: increase map data transmission efficiency by sending in binary format

上级 34c49f4c
...@@ -37,7 +37,9 @@ using apollo::common::time::Clock; ...@@ -37,7 +37,9 @@ using apollo::common::time::Clock;
using apollo::common::util::PathExists; using apollo::common::util::PathExists;
using apollo::hdmap::BaseMapFile; using apollo::hdmap::BaseMapFile;
std::string Dreamview::Name() const { return FLAGS_dreamview_module_name; } std::string Dreamview::Name() const {
return FLAGS_dreamview_module_name;
}
void Dreamview::TerminateProfilingMode(const ros::TimerEvent& event) { void Dreamview::TerminateProfilingMode(const ros::TimerEvent& event) {
Stop(); Stop();
...@@ -99,15 +101,17 @@ Status Dreamview::Init() { ...@@ -99,15 +101,17 @@ Status Dreamview::Init() {
image_.reset(new ImageHandler()); image_.reset(new ImageHandler());
websocket_.reset(new WebSocketHandler()); websocket_.reset(new WebSocketHandler());
map_ws_.reset(new WebSocketHandler());
map_service_.reset(new MapService()); map_service_.reset(new MapService());
sim_control_.reset(new SimControl(map_service_.get())); sim_control_.reset(new SimControl(map_service_.get()));
sim_world_updater_.reset( sim_world_updater_.reset(new SimulationWorldUpdater(
new SimulationWorldUpdater(websocket_.get(), sim_control_.get(), websocket_.get(), map_ws_.get(), sim_control_.get(), map_service_.get(),
map_service_.get(), FLAGS_routing_from_file)); FLAGS_routing_from_file));
hmi_.reset(new HMI(websocket_.get(), map_service_.get())); hmi_.reset(new HMI(websocket_.get(), map_service_.get()));
server_->addWebSocketHandler("/websocket", *websocket_); server_->addWebSocketHandler("/websocket", *websocket_);
server_->addWebSocketHandler("/map", *map_ws_);
server_->addHandler("/image", *image_); server_->addHandler("/image", *image_);
ApolloApp::SetCallbackThreadNumber(FLAGS_dreamview_worker_num); ApolloApp::SetCallbackThreadNumber(FLAGS_dreamview_worker_num);
......
...@@ -54,6 +54,7 @@ class Dreamview : public apollo::common::ApolloApp { ...@@ -54,6 +54,7 @@ class Dreamview : public apollo::common::ApolloApp {
std::unique_ptr<CivetServer> server_; std::unique_ptr<CivetServer> server_;
std::unique_ptr<SimControl> sim_control_; std::unique_ptr<SimControl> sim_control_;
std::unique_ptr<WebSocketHandler> websocket_; std::unique_ptr<WebSocketHandler> websocket_;
std::unique_ptr<WebSocketHandler> map_ws_;
std::unique_ptr<ImageHandler> image_; std::unique_ptr<ImageHandler> image_;
std::unique_ptr<MapService> map_service_; std::unique_ptr<MapService> map_service_;
std::unique_ptr<HMI> hmi_; std::unique_ptr<HMI> hmi_;
......
...@@ -37,18 +37,20 @@ using google::protobuf::util::JsonStringToMessage; ...@@ -37,18 +37,20 @@ using google::protobuf::util::JsonStringToMessage;
using google::protobuf::util::MessageToJsonString; using google::protobuf::util::MessageToJsonString;
SimulationWorldUpdater::SimulationWorldUpdater(WebSocketHandler *websocket, SimulationWorldUpdater::SimulationWorldUpdater(WebSocketHandler *websocket,
WebSocketHandler *map_ws,
SimControl *sim_control, SimControl *sim_control,
const MapService *map_service, const MapService *map_service,
bool routing_from_file) bool routing_from_file)
: sim_world_service_(map_service, routing_from_file), : sim_world_service_(map_service, routing_from_file),
map_service_(map_service), map_service_(map_service),
map_ws_(map_ws),
websocket_(websocket), websocket_(websocket),
sim_control_(sim_control) { sim_control_(sim_control) {
RegisterMessageHandlers(); RegisterMessageHandlers();
} }
void SimulationWorldUpdater::RegisterMessageHandlers() { void SimulationWorldUpdater::RegisterMessageHandlers() {
websocket_->RegisterMessageHandler( map_ws_->RegisterMessageHandler(
"RetrieveMapData", "RetrieveMapData",
[this](const Json &json, WebSocketHandler::Connection *conn) { [this](const Json &json, WebSocketHandler::Connection *conn) {
auto iter = json.find("elements"); auto iter = json.find("elements");
...@@ -56,8 +58,11 @@ void SimulationWorldUpdater::RegisterMessageHandlers() { ...@@ -56,8 +58,11 @@ void SimulationWorldUpdater::RegisterMessageHandlers() {
MapElementIds map_element_ids; MapElementIds map_element_ids;
if (JsonStringToMessage(iter->dump(), &map_element_ids).ok()) { if (JsonStringToMessage(iter->dump(), &map_element_ids).ok()) {
auto retrieved = map_service_->RetrieveMapElements(map_element_ids); auto retrieved = map_service_->RetrieveMapElements(map_element_ids);
websocket_->SendData(
conn, JsonUtil::ProtoToTypedJson("MapData", retrieved).dump()); std::string retrieved_map_string;
retrieved.SerializeToString(&retrieved_map_string);
map_ws_->SendBinaryData(conn, retrieved_map_string, true);
} else { } else {
AERROR << "Failed to parse MapElementIds from json"; AERROR << "Failed to parse MapElementIds from json";
} }
......
...@@ -58,8 +58,8 @@ class SimulationWorldUpdater { ...@@ -58,8 +58,8 @@ class SimulationWorldUpdater {
* of hdmap. * of hdmap.
* @param routing_from_file whether to read initial routing from file. * @param routing_from_file whether to read initial routing from file.
*/ */
SimulationWorldUpdater(WebSocketHandler *websocket, SimControl *sim_control, SimulationWorldUpdater(WebSocketHandler *websocket, WebSocketHandler *map_ws,
const MapService *map_service, SimControl *sim_control, const MapService *map_service,
bool routing_from_file = false); bool routing_from_file = false);
/** /**
...@@ -125,6 +125,7 @@ class SimulationWorldUpdater { ...@@ -125,6 +125,7 @@ class SimulationWorldUpdater {
SimulationWorldService sim_world_service_; SimulationWorldService sim_world_service_;
const MapService *map_service_; const MapService *map_service_;
WebSocketHandler *websocket_; WebSocketHandler *websocket_;
WebSocketHandler *map_ws_;
SimControl *sim_control_; SimControl *sim_control_;
// End point for requesting default route // End point for requesting default route
......
...@@ -24,10 +24,15 @@ LOCALIZATION_PROTOS='../../localization/proto/localization.proto ../../localizat ...@@ -24,10 +24,15 @@ LOCALIZATION_PROTOS='../../localization/proto/localization.proto ../../localizat
CHASSIS_PROTOS='../../canbus/proto/chassis.proto' CHASSIS_PROTOS='../../canbus/proto/chassis.proto'
PLANNING_PROTOS='../../planning/proto/sl_boundary.proto ../../planning/proto/decision.proto ../../planning/proto/planning_internal.proto' PLANNING_PROTOS='../../planning/proto/sl_boundary.proto ../../planning/proto/decision.proto ../../planning/proto/planning_internal.proto'
PERCEPTION_PROTOS='../../perception/proto/traffic_light_detection.proto' PERCEPTION_PROTOS='../../perception/proto/traffic_light_detection.proto'
MAP_PROTOS='../../map/proto/*.proto'
MONITOR_PROTOS='../../common/monitor_log/proto/monitor_log.proto' MONITOR_PROTOS='../../common/monitor_log/proto/monitor_log.proto'
ROUTING_PROTOS='../../routing/proto/routing.proto' ROUTING_PROTOS='../../routing/proto/routing.proto'
node_modules/protobufjs/bin/pbjs -t json ../proto/simulation_world.proto \ node_modules/protobufjs/bin/pbjs -t json ../proto/simulation_world.proto \
$COMMON_PROTOS $LOCALIZATION_PROTOS $CHASSIS_PROTOS $PLANNING_PROTOS \ $COMMON_PROTOS $LOCALIZATION_PROTOS $CHASSIS_PROTOS $PLANNING_PROTOS \
$PERCEPTION_PROTOS $MONITOR_PROTOS $ROUTING_PROTOS \ $PERCEPTION_PROTOS $MONITOR_PROTOS $ROUTING_PROTOS \
-o proto_bundle/proto_bundle.json -o proto_bundle/sim_world_proto_bundle.json
node_modules/protobufjs/bin/pbjs -t json $MAP_PROTOS \
../../common/proto/geometry.proto \
-o proto_bundle/map_proto_bundle.json
\ No newline at end of file
...@@ -2554,6 +2554,32 @@ ...@@ -2554,6 +2554,32 @@
"id": 1 "id": 1
} }
} }
},
"NavigationPath": {
"fields": {
"pathPoint": {
"rule": "repeated",
"type": "apollo.common.PathPoint",
"id": 1
},
"pathPriority": {
"type": "uint32",
"id": 2
}
}
},
"NavigationInfo": {
"fields": {
"header": {
"type": "apollo.common.Header",
"id": 1
},
"navigationPath": {
"rule": "repeated",
"type": "NavigationPath",
"id": 2
}
}
} }
} }
}, },
......
...@@ -7,7 +7,7 @@ import MainView from "components/Layouts/MainView"; ...@@ -7,7 +7,7 @@ import MainView from "components/Layouts/MainView";
import ToolView from "components/Layouts/ToolView"; import ToolView from "components/Layouts/ToolView";
import PNCMonitor from "components/PNCMonitor"; import PNCMonitor from "components/PNCMonitor";
import SideBar from "components/SideBar"; import SideBar from "components/SideBar";
import WS from "store/websocket"; import WS, {MAP_WS} from "store/websocket";
@inject("store") @observer @inject("store") @observer
...@@ -31,6 +31,7 @@ export default class Dreamview extends React.Component { ...@@ -31,6 +31,7 @@ export default class Dreamview extends React.Component {
componentDidMount() { componentDidMount() {
WS.initialize(); WS.initialize();
MAP_WS.initialize();
window.addEventListener("resize", () => { window.addEventListener("resize", () => {
this.props.store.updateDimension(); this.props.store.updateDimension();
}); });
......
import * as THREE from "three"; import * as THREE from "three";
import WS from "store/websocket"; import {MAP_WS} from "store/websocket";
import { import {
drawSegmentsFromPoints, drawSegmentsFromPoints,
...@@ -469,7 +469,7 @@ export default class Map { ...@@ -469,7 +469,7 @@ export default class Map {
this.hash = hash; this.hash = hash;
const diff = this.diffMapElements(elementIds, this.data); const diff = this.diffMapElements(elementIds, this.data);
if (!_.isEmpty(diff) || !this.initialized) { if (!_.isEmpty(diff) || !this.initialized) {
WS.requestMapData(diff); MAP_WS.requestMapData(diff);
this.initialized = true; this.initialized = true;
} }
} }
......
websocketServer: "0.0.0.0:8888/websocket" simWorldWebsocketServer: "0.0.0.0:8888/websocket"
mapWebsocketServer: "0.0.0.0:8888/map"
...@@ -2,31 +2,45 @@ import devConfig from "store/config/dev.yml"; ...@@ -2,31 +2,45 @@ import devConfig from "store/config/dev.yml";
import PARAMETERS from "store/config/parameters.yml"; import PARAMETERS from "store/config/parameters.yml";
import OfflinePlaybackWebSocketEndpoint from "store/websocket/websocket_offline"; import OfflinePlaybackWebSocketEndpoint from "store/websocket/websocket_offline";
import RealtimeWebSocketEndpoint from "store/websocket/websocket_ros"; import RealtimeWebSocketEndpoint from "store/websocket/websocket_realtime";
import MapWebSocketEndpoint from "store/websocket/websocket_map";
// Returns the websocket server address based on the web server address. // Returns the websocket server address based on the web server address.
// Follows the convention that the websocket is served on the same host // Follows the convention that the websocket is served on the same host
// as the web server, the port number of websocket is the port number of // as the web server, the port number of websocket is the port number of
// the webserver plus one. // the webserver plus one.
function deduceWebsocketServerAddr() { function deduceWebsocketServerAddr(type) {
const server = window.location.origin; const server = window.location.origin;
const link = document.createElement("a"); const link = document.createElement("a");
link.href = server; link.href = server;
const protocol = location.protocol === "https:" ? "wss" : "ws"; const protocol = location.protocol === "https:" ? "wss" : "ws";
const path = OFFLINE_PLAYBACK ? 'RosPlayBack' : 'websocket';
return `${protocol}://${link.hostname}:${window.location.port}/${path}`; let path = "";
switch (type) {
case "map":
path = "map";
break;
case "sim_world":
path = OFFLINE_PLAYBACK ? "RosPlayBack" : "websocket";
break;
}
return `${protocol}://${link.hostname}:${window.location.port}/${path}`;
} }
// NOTE: process.env.NODE_ENV will be set to "production" by webpack when // NOTE: process.env.NODE_ENV will be set to "production" by webpack when
// invoked in production mode ("-p"). We rely on this to determine which // invoked in production mode ("-p"). We rely on this to determine which
// websocket server to use. // websocket server to use.
const serverAddr = process.env.NODE_ENV === "production" ? const simWorldServerAddr =
deduceWebsocketServerAddr() : `ws://${devConfig.websocketServer}`; process.env.NODE_ENV === "production"
? deduceWebsocketServerAddr("sim_world")
: `ws://${devConfig.simWorldWebsocketServer}`;
const WS = OFFLINE_PLAYBACK const WS = OFFLINE_PLAYBACK
? new OfflinePlaybackWebSocketEndpoint(serverAddr) ? new OfflinePlaybackWebSocketEndpoint(simWorldServerAddr)
: new RealtimeWebSocketEndpoint(serverAddr); : new RealtimeWebSocketEndpoint(simWorldServerAddr);
export default WS; export default WS;
const mapServerAddr =
process.env.NODE_ENV === "production"
? deduceWebsocketServerAddr("map")
: `ws://${devConfig.mapWebsocketServer}`;
export const MAP_WS = new MapWebSocketEndpoint(mapServerAddr);
import STORE from "store";
import RENDERER from "renderer";
const protobuf = require("protobufjs/light");
const root = protobuf.Root.fromJSON(require("../../../proto_bundle/map_proto_bundle.json"));
const mapMessage = root.lookupType("apollo.hdmap.Map");
export default class MapDataWebSocketEndpoint {
constructor(serverAddr) {
this.serverAddr = serverAddr;
this.websocket = null;
}
initialize() {
try {
this.websocket = new WebSocket(this.serverAddr);
this.websocket.binaryType = "arraybuffer";
} catch (error) {
console.error("Failed to establish a connection: " + error);
setTimeout(() => {
this.initialize();
}, 1000);
return;
}
this.websocket.onmessage = event => {
const data = mapMessage.toObject(
mapMessage.decode(new Uint8Array(event.data)), {enums: String});
RENDERER.updateMap(data);
STORE.setInitializationStatus(true);
};
this.websocket.onclose = event => {
console.log("WebSocket connection closed, close_code: " + event.code);
this.initialize();
};
}
requestMapData(elements) {
this.websocket.send(JSON.stringify({
type: "RetrieveMapData",
elements: elements,
}));
}
}
...@@ -2,7 +2,7 @@ import STORE from "store"; ...@@ -2,7 +2,7 @@ import STORE from "store";
import RENDERER from "renderer"; import RENDERER from "renderer";
const protobuf = require("protobufjs/light"); const protobuf = require("protobufjs/light");
const root = protobuf.Root.fromJSON(require("../../../proto_bundle/proto_bundle.json")); const root = protobuf.Root.fromJSON(require("../../../proto_bundle/sim_world_proto_bundle.json"));
const SimWorldMessage = root.lookupType("apollo.dreamview.SimulationWorld"); const SimWorldMessage = root.lookupType("apollo.dreamview.SimulationWorld");
export default class RosWebSocketEndpoint { export default class RosWebSocketEndpoint {
...@@ -77,10 +77,6 @@ export default class RosWebSocketEndpoint { ...@@ -77,10 +77,6 @@ export default class RosWebSocketEndpoint {
RENDERER.updateMapIndex(message.mapHash, RENDERER.updateMapIndex(message.mapHash,
message.mapElementIds, message.mapRadius); message.mapElementIds, message.mapRadius);
break; break;
case "MapData":
RENDERER.updateMap(message.data);
STORE.setInitializationStatus(true);
break;
case "DefaultEndPoint": case "DefaultEndPoint":
STORE.routeEditingManager.updateDefaultRoutingEndPoint(message); STORE.routeEditingManager.updateDefaultRoutingEndPoint(message);
break; break;
...@@ -125,13 +121,6 @@ export default class RosWebSocketEndpoint { ...@@ -125,13 +121,6 @@ export default class RosWebSocketEndpoint {
this.lastSeqNum = world.sequenceNum; this.lastSeqNum = world.sequenceNum;
} }
requestMapData(elements) {
this.websocket.send(JSON.stringify({
type: "RetrieveMapData",
elements: elements,
}));
}
requestMapElementIdsByRadius(radius) { requestMapElementIdsByRadius(radius) {
this.websocket.send(JSON.stringify({ this.websocket.send(JSON.stringify({
type: "RetrieveMapElementIdsByRadius", type: "RetrieveMapElementIdsByRadius",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册