提交 18cf7886 编写于 作者: A Aaron Xiao 提交者: Liangliang Zhang

HMI: Decouple HMIWorker to enable customized HMI client.

上级 3c737561
# Customize Your Own HMI
HMIWorker is a standalone singleton which processes HMI actions. If you want to
have a customized HMI instead the one integrated with Apollo Dreamview, just
develope a frontend and send operations to the backend which delegates to
HMIWorker.
## HMI Config
See modules/dreamview/proto/hmi_config.proto. It defines all supported modes,
modules, hardware and tools.
## HMI Worker
According to the HMIConfig, HMI Worker could trigger actions like:
- Change mode, map, vehicle and driving mode.
- Register event handler for changing mode, map and vehicle.
- Start, stop or execute other registered commands for modules.
- Execute registered tools.
- Submit DriveEvent which will be recorded as a ROS message.
- Get current HMIConfig and HMIStatus, which could be used for UI update.
## Vehicle Manager
VehicleManager is the one to actually config everything when changing vehicles.
The major thing is to copy all vehicle-wised parameter files to right place. The
source and destination mappings are defined by
modules/dreamview/conf/vehicle_data.pb.txt.
......@@ -153,6 +153,15 @@ void HMI::RegisterMessageHandlers() {
});
// HMI client asks for changing map.
HMIWorker::instance()->RegisterChangeMapHandler(
[this](const std::string& new_map) {
// Reload simulation map after changing map.
CHECK(map_service_->ReloadMap(true))
<< "Failed to load new simulation map: " << new_map;
// And then broadcast new HMIStatus to all clients.
BroadcastHMIStatus();
}
);
websocket_->RegisterMessageHandler(
"ChangeMap",
[this](const Json &json, WebSocketHandler::Connection *conn) {
......@@ -160,14 +169,20 @@ void HMI::RegisterMessageHandlers() {
// MapName should be a key of config_.available_maps.
std::string new_map;
if (JsonUtil::GetStringFromJson(json, "new_map", &new_map)) {
HMIWorker::instance()->ChangeToMap(new_map, map_service_);
BroadcastHMIStatus();
HMIWorker::instance()->ChangeToMap(new_map);
} else {
AERROR << "Truncated ChangeMap request.";
}
});
// HMI client asks for changing vehicle.
HMIWorker::instance()->RegisterChangeVehicleHandler(
[this](const std::string& new_vehicle) {
// Broadcast new HMIStatus and VehicleParam.
BroadcastHMIStatus();
SendVehicleParam();
}
);
websocket_->RegisterMessageHandler(
"ChangeVehicle",
[this](const Json &json, WebSocketHandler::Connection *conn) {
......@@ -176,15 +191,18 @@ void HMI::RegisterMessageHandlers() {
std::string new_vehicle;
if (JsonUtil::GetStringFromJson(json, "new_vehicle", &new_vehicle)) {
HMIWorker::instance()->ChangeToVehicle(new_vehicle);
BroadcastHMIStatus();
// Broadcast new VehicleParam.
SendVehicleParam();
} else {
AERROR << "Truncated ChangeVehicle request.";
}
});
// HMI client asks for changing mode.
HMIWorker::instance()->RegisterChangeModeHandler(
[this](const std::string& new_mode) {
// Broadcast new HMIStatus.
BroadcastHMIStatus();
}
);
websocket_->RegisterMessageHandler(
"ChangeMode",
[this](const Json &json, WebSocketHandler::Connection *conn) {
......@@ -193,7 +211,6 @@ void HMI::RegisterMessageHandlers() {
std::string new_mode;
if (JsonUtil::GetStringFromJson(json, "new_mode", &new_mode)) {
HMIWorker::instance()->ChangeToMode(new_mode);
BroadcastHMIStatus();
} else {
AERROR << "Truncated ChangeMode request.";
}
......
......@@ -262,8 +262,7 @@ void HMIWorker::RunModeCommand(const std::string &command_name) {
}
}
void HMIWorker::ChangeToMap(const std::string &map_name,
MapService *map_service) {
void HMIWorker::ChangeToMap(const std::string &map_name) {
const auto *map_dir = FindOrNull(config_.available_maps(), map_name);
if (map_dir == nullptr) {
AERROR << "Unknown map " << map_name;
......@@ -281,9 +280,12 @@ void HMIWorker::ChangeToMap(const std::string &map_name,
apollo::common::KVDB::Put("apollo:dreamview:map", map_name);
SetGlobalFlag("map_dir", *map_dir, &FLAGS_map_dir);
// Also reload simulation map.
CHECK(map_service->ReloadMap(true)) << "Failed to load map from " << *map_dir;
RunModeCommand("stop");
// Trigger registered change map handlers.
for (const auto handler : change_map_handlers_) {
handler(map_name);
}
}
void HMIWorker::ChangeToVehicle(const std::string &vehicle_name) {
......@@ -305,6 +307,11 @@ void HMIWorker::ChangeToVehicle(const std::string &vehicle_name) {
CHECK(VehicleManager::instance()->UseVehicle(*vehicle));
RunModeCommand("stop");
// Trigger registered change vehicle handlers.
for (const auto handler : change_vehicle_handlers_) {
handler(vehicle_name);
}
}
void HMIWorker::ChangeToMode(const std::string &mode_name) {
......@@ -333,6 +340,11 @@ void HMIWorker::ChangeToMode(const std::string &mode_name) {
for (const auto &module : old_modules) {
RunModuleCommand(module, "stop");
}
// Trigger registered change mode handlers.
for (const auto handler : change_mode_handlers_) {
handler(mode_name);
}
}
void HMIWorker::UpdateSystemStatus(const monitor::SystemStatus &system_status) {
......
......@@ -24,7 +24,6 @@
#include "modules/canbus/proto/chassis.pb.h"
#include "modules/common/macro.h"
#include "modules/dreamview/backend/map/map_service.h"
#include "modules/dreamview/proto/hmi_config.pb.h"
#include "modules/dreamview/proto/hmi_status.pb.h"
#include "modules/dreamview/proto/voice_detection.pb.h"
......@@ -37,6 +36,10 @@
namespace apollo {
namespace dreamview {
using ChangeModeHandler = std::function<void(const std::string&)>;
using ChangeMapHandler = std::function<void(const std::string&)>;
using ChangeVehicleHandler = std::function<void(const std::string&)>;
// Singleton worker which does the actual work of HMI actions.
class HMIWorker {
public:
......@@ -56,9 +59,19 @@ class HMIWorker {
// Update system status.
void UpdateSystemStatus(const apollo::monitor::SystemStatus& system_status);
// Register event handlers.
void RegisterChangeModeHandler(ChangeModeHandler handler) {
change_mode_handlers_.emplace_back(handler);
}
void RegisterChangeMapHandler(ChangeMapHandler handler) {
change_map_handlers_.emplace_back(handler);
}
void RegisterChangeVehicleHandler(ChangeVehicleHandler handler) {
change_vehicle_handlers_.emplace_back(handler);
}
// Change current mode, map, vehicle and driving mode.
void ChangeToMode(const std::string& mode_name);
void ChangeToMap(const std::string& map_name, MapService* map_service);
void ChangeToMap(const std::string& map_name);
void ChangeToVehicle(const std::string& vehicle_name);
static bool ChangeToDrivingMode(
const apollo::canbus::Chassis::DrivingMode mode);
......@@ -80,6 +93,10 @@ class HMIWorker {
HMIStatus status_;
mutable boost::shared_mutex status_mutex_;
std::vector<ChangeModeHandler> change_mode_handlers_;
std::vector<ChangeMapHandler> change_map_handlers_;
std::vector<ChangeVehicleHandler> change_vehicle_handlers_;
DECLARE_SINGLETON(HMIWorker);
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册