提交 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;
using apollo::common::util::PathExists;
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) {
Stop();
......@@ -99,15 +101,17 @@ Status Dreamview::Init() {
image_.reset(new ImageHandler());
websocket_.reset(new WebSocketHandler());
map_ws_.reset(new WebSocketHandler());
map_service_.reset(new MapService());
sim_control_.reset(new SimControl(map_service_.get()));
sim_world_updater_.reset(
new SimulationWorldUpdater(websocket_.get(), sim_control_.get(),
map_service_.get(), FLAGS_routing_from_file));
sim_world_updater_.reset(new SimulationWorldUpdater(
websocket_.get(), map_ws_.get(), sim_control_.get(), map_service_.get(),
FLAGS_routing_from_file));
hmi_.reset(new HMI(websocket_.get(), map_service_.get()));
server_->addWebSocketHandler("/websocket", *websocket_);
server_->addWebSocketHandler("/map", *map_ws_);
server_->addHandler("/image", *image_);
ApolloApp::SetCallbackThreadNumber(FLAGS_dreamview_worker_num);
......
......@@ -54,6 +54,7 @@ class Dreamview : public apollo::common::ApolloApp {
std::unique_ptr<CivetServer> server_;
std::unique_ptr<SimControl> sim_control_;
std::unique_ptr<WebSocketHandler> websocket_;
std::unique_ptr<WebSocketHandler> map_ws_;
std::unique_ptr<ImageHandler> image_;
std::unique_ptr<MapService> map_service_;
std::unique_ptr<HMI> hmi_;
......
......@@ -37,18 +37,20 @@ using google::protobuf::util::JsonStringToMessage;
using google::protobuf::util::MessageToJsonString;
SimulationWorldUpdater::SimulationWorldUpdater(WebSocketHandler *websocket,
WebSocketHandler *map_ws,
SimControl *sim_control,
const MapService *map_service,
bool routing_from_file)
: sim_world_service_(map_service, routing_from_file),
map_service_(map_service),
map_ws_(map_ws),
websocket_(websocket),
sim_control_(sim_control) {
RegisterMessageHandlers();
}
void SimulationWorldUpdater::RegisterMessageHandlers() {
websocket_->RegisterMessageHandler(
map_ws_->RegisterMessageHandler(
"RetrieveMapData",
[this](const Json &json, WebSocketHandler::Connection *conn) {
auto iter = json.find("elements");
......@@ -56,8 +58,11 @@ void SimulationWorldUpdater::RegisterMessageHandlers() {
MapElementIds map_element_ids;
if (JsonStringToMessage(iter->dump(), &map_element_ids).ok()) {
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 {
AERROR << "Failed to parse MapElementIds from json";
}
......
......@@ -58,8 +58,8 @@ class SimulationWorldUpdater {
* of hdmap.
* @param routing_from_file whether to read initial routing from file.
*/
SimulationWorldUpdater(WebSocketHandler *websocket, SimControl *sim_control,
const MapService *map_service,
SimulationWorldUpdater(WebSocketHandler *websocket, WebSocketHandler *map_ws,
SimControl *sim_control, const MapService *map_service,
bool routing_from_file = false);
/**
......@@ -125,6 +125,7 @@ class SimulationWorldUpdater {
SimulationWorldService sim_world_service_;
const MapService *map_service_;
WebSocketHandler *websocket_;
WebSocketHandler *map_ws_;
SimControl *sim_control_;
// End point for requesting default route
......
......@@ -24,10 +24,15 @@ LOCALIZATION_PROTOS='../../localization/proto/localization.proto ../../localizat
CHASSIS_PROTOS='../../canbus/proto/chassis.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'
MAP_PROTOS='../../map/proto/*.proto'
MONITOR_PROTOS='../../common/monitor_log/proto/monitor_log.proto'
ROUTING_PROTOS='../../routing/proto/routing.proto'
node_modules/protobufjs/bin/pbjs -t json ../proto/simulation_world.proto \
$COMMON_PROTOS $LOCALIZATION_PROTOS $CHASSIS_PROTOS $PLANNING_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 @@
"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";
import ToolView from "components/Layouts/ToolView";
import PNCMonitor from "components/PNCMonitor";
import SideBar from "components/SideBar";
import WS from "store/websocket";
import WS, {MAP_WS} from "store/websocket";
@inject("store") @observer
......@@ -31,6 +31,7 @@ export default class Dreamview extends React.Component {
componentDidMount() {
WS.initialize();
MAP_WS.initialize();
window.addEventListener("resize", () => {
this.props.store.updateDimension();
});
......
import * as THREE from "three";
import WS from "store/websocket";
import {MAP_WS} from "store/websocket";
import {
drawSegmentsFromPoints,
......@@ -469,7 +469,7 @@ export default class Map {
this.hash = hash;
const diff = this.diffMapElements(elementIds, this.data);
if (!_.isEmpty(diff) || !this.initialized) {
WS.requestMapData(diff);
MAP_WS.requestMapData(diff);
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";
import PARAMETERS from "store/config/parameters.yml";
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.
// 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
// the webserver plus one.
function deduceWebsocketServerAddr() {
const server = window.location.origin;
const link = document.createElement("a");
link.href = server;
const protocol = location.protocol === "https:" ? "wss" : "ws";
const path = OFFLINE_PLAYBACK ? 'RosPlayBack' : 'websocket';
return `${protocol}://${link.hostname}:${window.location.port}/${path}`;
function deduceWebsocketServerAddr(type) {
const server = window.location.origin;
const link = document.createElement("a");
link.href = server;
const protocol = location.protocol === "https:" ? "wss" : "ws";
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
// invoked in production mode ("-p"). We rely on this to determine which
// websocket server to use.
const serverAddr = process.env.NODE_ENV === "production" ?
deduceWebsocketServerAddr() : `ws://${devConfig.websocketServer}`;
const simWorldServerAddr =
process.env.NODE_ENV === "production"
? deduceWebsocketServerAddr("sim_world")
: `ws://${devConfig.simWorldWebsocketServer}`;
const WS = OFFLINE_PLAYBACK
? new OfflinePlaybackWebSocketEndpoint(serverAddr)
: new RealtimeWebSocketEndpoint(serverAddr);
? new OfflinePlaybackWebSocketEndpoint(simWorldServerAddr)
: new RealtimeWebSocketEndpoint(simWorldServerAddr);
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";
import RENDERER from "renderer";
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");
export default class RosWebSocketEndpoint {
......@@ -77,10 +77,6 @@ export default class RosWebSocketEndpoint {
RENDERER.updateMapIndex(message.mapHash,
message.mapElementIds, message.mapRadius);
break;
case "MapData":
RENDERER.updateMap(message.data);
STORE.setInitializationStatus(true);
break;
case "DefaultEndPoint":
STORE.routeEditingManager.updateDefaultRoutingEndPoint(message);
break;
......@@ -125,13 +121,6 @@ export default class RosWebSocketEndpoint {
this.lastSeqNum = world.sequenceNum;
}
requestMapData(elements) {
this.websocket.send(JSON.stringify({
type: "RetrieveMapData",
elements: elements,
}));
}
requestMapElementIdsByRadius(radius) {
this.websocket.send(JSON.stringify({
type: "RetrieveMapElementIdsByRadius",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册