diff options
author | Mikhail Gorbushin <m.gorbushin@corp.mail.ru> | 2018-08-17 17:12:58 +0300 |
---|---|---|
committer | Mikhail Gorbushin <m.gorbushin@corp.mail.ru> | 2018-09-05 13:50:45 +0300 |
commit | 03fa341b7ce54763cac226f8f93f9d0dc53d0486 (patch) | |
tree | 091c77664bf2b85fd0a11a611ca3688b2a50f4c1 | |
parent | 75204f8440e7efce6c691c5783f8c630e95b1cb8 (diff) |
[routing] routing part + routing testsMAPSME-8120.speed_cam.ROUTING_PART
-rw-r--r-- | routing/deserialize_speed_cameras.cpp | 71 | ||||
-rw-r--r-- | routing/deserialize_speed_cameras.hpp | 33 | ||||
-rw-r--r-- | routing/routing_integration_tests/CMakeLists.txt | 18 | ||||
-rw-r--r-- | routing/routing_integration_tests/speed_camera_notification_test.cpp | 90 | ||||
-rw-r--r-- | routing/serialize_speed_camera.cpp | 45 | ||||
-rw-r--r-- | routing/serialize_speed_camera.hpp | 80 |
6 files changed, 328 insertions, 9 deletions
diff --git a/routing/deserialize_speed_cameras.cpp b/routing/deserialize_speed_cameras.cpp new file mode 100644 index 0000000000..3ba0244a55 --- /dev/null +++ b/routing/deserialize_speed_cameras.cpp @@ -0,0 +1,71 @@ +#include "routing/deserialize_speed_cameras.hpp" + +#include "routing/routing_session.hpp" +#include "routing/serialize_speed_camera.hpp" + +#include "generator/camera_info_collector.hpp" + +#include "coding/pointd_to_pointu.hpp" +#include "coding/varint.hpp" + +#include "base/assert.hpp" +#include "base/macros.hpp" + +#include <limits> +#include <vector> + +namespace routing +{ +std::vector<RouteSegment::SpeedCamera> kEmptyVectorOfSpeedCameras = {}; + +void DeserializeSpeedCamsFromMwm(ReaderSource<FilesContainerR::TReader> & src, + std::map<SegmentCoord, vector<RouteSegment::SpeedCamera>> & map) +{ + SpeedCameraMwmHeader header; + header.Deserialize(src); + CHECK(header.IsValid(), ("Bad header of speed cam section")); + uint32_t const amount = header.GetAmount(); + + SegmentCoord segment; + RouteSegment::SpeedCamera speedCamera; + uint32_t prevFeatureId = 0; + for (uint32_t i = 0; i < amount; i++) + { + auto featureId = ReadVarUint<uint32_t>(src); + featureId += prevFeatureId; // delta coding + prevFeatureId = featureId; + + auto const segmentId = ReadVarUint<uint32_t>(src); + + uint32_t coefInt = 0; + ReadPrimitiveFromSource(src, coefInt); + double const coef = Uint32ToDouble(coefInt, 0, 1, 32); + + uint8_t speed; + ReadPrimitiveFromSource(src, speed); + CHECK_LESS(speed, kMaxCameraSpeedKmpH, ()); + if (speed == 0) + { + // TODO (@gmoryes) change to (speed = routing::SpeedCameraOnRoute::kNoSpeedInfo) + speed = std::numeric_limits<uint8_t>::max(); + } + + // We don't use direction of camera, because of bad data in OSM. + UNUSED_VALUE(ReadPrimitiveFromSource<uint8_t>(src)); // direction + + // Number of time conditions of camera. + auto const conditionsNumber = ReadVarUint<uint32_t>(src); + CHECK_EQUAL(conditionsNumber, 0, + ("Number of conditions should be 0, non zero number is not implemented now")); + + segment = {featureId, segmentId}; + speedCamera = {coef, static_cast<uint8_t>(speed)}; + + auto it = map.find(segment); + if (it == map.end()) + map.emplace(segment, vector<RouteSegment::SpeedCamera>{speedCamera}); + else + it->second.emplace_back(speedCamera); + } +} +} // namespace routing diff --git a/routing/deserialize_speed_cameras.hpp b/routing/deserialize_speed_cameras.hpp new file mode 100644 index 0000000000..b1007bc7b8 --- /dev/null +++ b/routing/deserialize_speed_cameras.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "routing/route.hpp" +#include "routing/segment.hpp" + +#include "coding/reader.hpp" + +#include <cstdint> +#include <map> +#include <utility> + +namespace routing +{ +// Pair of featureId and segmentId +struct SegmentCoord { + SegmentCoord() = default; + SegmentCoord(uint32_t fId, uint32_t sId) : m_featureId(fId), m_segmentId(sId) {} + + friend bool operator<(SegmentCoord const & lhs, SegmentCoord const & rhs) + { + return lhs.m_featureId < rhs.m_featureId && lhs.m_segmentId < rhs.m_featureId; + } + + uint32_t m_featureId; + uint32_t m_segmentId; +}; + +extern std::vector<RouteSegment::SpeedCamera> kEmptyVectorOfSpeedCameras; + +void DeserializeSpeedCamsFromMwm( + ReaderSource<FilesContainerR::TReader> & src, + std::map<SegmentCoord, std::vector<RouteSegment::SpeedCamera>> & camerasVector); +} // namespace routing diff --git a/routing/routing_integration_tests/CMakeLists.txt b/routing/routing_integration_tests/CMakeLists.txt index 49d2c05da5..e5d988f069 100644 --- a/routing/routing_integration_tests/CMakeLists.txt +++ b/routing/routing_integration_tests/CMakeLists.txt @@ -9,18 +9,18 @@ project(routing_integration_tests) set( SRC - #bicycle_route_test.cpp - #bicycle_turn_test.cpp - #get_altitude_test.cpp - #online_cross_tests.cpp - #pedestrian_route_test.cpp - #road_graph_tests.cpp - #route_test.cpp + bicycle_route_test.cpp + bicycle_turn_test.cpp + get_altitude_test.cpp + online_cross_tests.cpp + pedestrian_route_test.cpp + road_graph_tests.cpp + route_test.cpp routing_test_tools.cpp routing_test_tools.hpp speed_camera_notification.cpp - #street_names_test.cpp - #turn_test.cpp + street_names_test.cpp + turn_test.cpp ) omim_add_test(${PROJECT_NAME} ${SRC}) diff --git a/routing/routing_integration_tests/speed_camera_notification_test.cpp b/routing/routing_integration_tests/speed_camera_notification_test.cpp new file mode 100644 index 0000000000..52ea3284a9 --- /dev/null +++ b/routing/routing_integration_tests/speed_camera_notification_test.cpp @@ -0,0 +1,90 @@ +#include "testing/testing.hpp" + +#include "routing/routing_integration_tests/routing_test_tools.hpp" + +#include "routing/route.hpp" +#include "routing/routing_callbacks.hpp" +#include "routing/routing_session.hpp" +#include "routing/routing_tests/tools.hpp" + +#include "platform/location.hpp" + +#include <memory> + +using namespace routing; +using namespace routing::turns; +using namespace std; + +namespace +{ + +string const kCameraOnTheWay = "Speed camera on the way"; + +location::GpsInfo MoveTo(ms::LatLon const & coords, double speed = -1) +{ + location::GpsInfo info; + info.m_horizontalAccuracy = 0.01; + info.m_verticalAccuracy = 0.01; + info.m_latitude = coords.lat; + info.m_longitude = coords.lon; + info.m_speed = speed; + return info; +} + +void ChangePosition(RoutingSession & routingSession, ms::LatLon const & coords, double speed = -1) +{ + static double constexpr kCoordEpsilon = 1e-6; + + routingSession.OnLocationPositionChanged(MoveTo({coords.lat, coords.lon}, 100)); + routingSession.OnLocationPositionChanged(MoveTo({coords.lat + kCoordEpsilon, coords.lon + kCoordEpsilon}, 100)); +} + +void InitRoutingSession(ms::LatLon const & from, ms::LatLon const & to, RoutingSession & routingSession) +{ + TRouteResult const routeResult = + integration::CalculateRoute(integration::GetVehicleComponents<VehicleType::Car>(), + MercatorBounds::FromLatLon(from), {0., 0.}, + MercatorBounds::FromLatLon(to)); + + Route & route = *routeResult.first; + RouterResultCode const result = routeResult.second; + TEST_EQUAL(result, RouterResultCode::NoError, ()); + + routingSession.Init(nullptr, nullptr); + routingSession.SetRoutingSettings(routing::GetRoutingSettings(routing::VehicleType::Car)); + routingSession.AssignRouteForTests(std::make_shared<Route>(route), result); + string const engShortJson = R"( + { + "speed_camera": ")" + kCameraOnTheWay + R"(" + } + )"; + routingSession.ForTestingSetLocaleWithJson(engShortJson, "en"); +} + +bool IsExistsInNotification(vector<string> const & notifications, string const & value) +{ + for (auto const & item : notifications) + { + if (item == value) + return true; + } + + return false; +} + +UNIT_TEST(SpeedCameraNotification_1) +{ + RoutingSession routingSession; + InitRoutingSession(/* from = */ {55.6793107, 37.5326805}, + /* to = */ {55.6876463, 37.5450897}, + routingSession); + + ChangePosition(routingSession, {55.6812619, 37.5355195}, 100); + + vector<string> notifications; + routingSession.GenerateNotifications(notifications); + + TEST(IsExistsInNotification(notifications, kCameraOnTheWay), ()); +} + +} // namespace
\ No newline at end of file diff --git a/routing/serialize_speed_camera.cpp b/routing/serialize_speed_camera.cpp new file mode 100644 index 0000000000..131f7fccb2 --- /dev/null +++ b/routing/serialize_speed_camera.cpp @@ -0,0 +1,45 @@ +#include "routing/serialize_speed_camera.hpp" + +#include "coding/pointd_to_pointu.hpp" +#include "coding/varint.hpp" +#include "coding/write_to_sink.hpp" + +#include "base/assert.hpp" + +namespace routing +{ +uint32_t constexpr SpeedCameraMwmHeader::kLatestVersion; + +void SerializeSpeedCamera(FileWriter & writer, uint32_t prevFeatureId, const routing::SpeedCameraMetadata & data) +{ + CHECK_EQUAL(data.m_ways.size(), 1, ()); + + auto const & way = data.m_ways.back(); + + auto featureId = static_cast<uint32_t>(way.m_featureId); + CHECK_GREATER_OR_EQUAL(featureId, prevFeatureId, ()); + featureId -= prevFeatureId; // delta coding + WriteVarUint(writer, featureId); + WriteVarUint(writer, way.m_segmentId); + + uint32_t const coef = DoubleToUint32(way.m_coef, 0, 1, 32); + WriteToSink(writer, coef); + + WriteToSink(writer, data.m_maxSpeedKmPH); + + auto const direction = static_cast<uint8_t>(data.m_direction); + WriteToSink(writer, direction); + + // TODO (@gmoryes) add implementation of this feature + // List of time conditions will be saved here. For example: + // "maxspeed:conditional": "60 @ (23:00-05:00)" + // or + // "60 @ (Su 00:00-24:00; Mo-Sa 00:00-06:00,22:30-24:00)" + // We store number of conditions first, then each condition in 3 bytes: + // 1. Type of condition (day, hour, month) + start value of range. + // 2. End value of range. + // 3. Maxspeed in this time range. + WriteVarInt(writer, 0 /* number of time condition */); +} +} // namespace routing + diff --git a/routing/serialize_speed_camera.hpp b/routing/serialize_speed_camera.hpp new file mode 100644 index 0000000000..6ead56b479 --- /dev/null +++ b/routing/serialize_speed_camera.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "coding/file_writer.hpp" + +#include "geometry/point2d.hpp" + +#include <cstdint> +#include <vector> + +namespace routing +{ +static uint32_t constexpr kMaxCameraSpeedKmpH = std::numeric_limits<uint8_t>::max(); + +/// \brief |m_featureId| and |m_segmentId| identify the place where the camera is located. +/// |m_coef| is a factor [0, 1] where the camera is placed at the segment. |m_coef| == 0 +/// means the camera is placed at the beginning of the segment. +struct SpeedCameraMwmPosition +{ + SpeedCameraMwmPosition() = default; + SpeedCameraMwmPosition(uint32_t fId, uint32_t sId, double k) : m_featureId(fId), m_segmentId(sId), m_coef(k) {} + + uint32_t m_featureId = 0; + uint32_t m_segmentId = 0; + double m_coef = 0.0; +}; + +// Don't touch the order of enum (this is part of mwm). +enum class SpeedCameraDirection +{ + Unknown = 0, + Forward = 1, + Backward = 2, + Both = 3 +}; + +struct SpeedCameraMetadata +{ + SpeedCameraMetadata() = default; + SpeedCameraMetadata(m2::PointD const & center, uint8_t maxSpeed, + std::vector<routing::SpeedCameraMwmPosition> && ways) + : m_center(center), m_maxSpeedKmPH(maxSpeed), m_ways(std::move(ways)) {} + + m2::PointD m_center; + uint8_t m_maxSpeedKmPH; + std::vector<routing::SpeedCameraMwmPosition> m_ways; + SpeedCameraDirection m_direction = SpeedCameraDirection::Unknown; +}; + +class SpeedCameraMwmHeader +{ +public: + static uint32_t constexpr kLatestVersion = 1; + + void SetVersion(uint32_t v) { m_version = v; } + void SetAmount(uint32_t n) { m_amount = n; } + uint32_t GetAmount() const { return m_amount; } + + template <typename T> + void Serialize(T & sink) + { + WriteToSink(sink, m_version); + WriteToSink(sink, m_amount); + } + + template <typename T> + void Deserialize(T & sink) + { + ReadPrimitiveFromSource(sink, m_version); + ReadPrimitiveFromSource(sink, m_amount); + } + + bool IsValid() const { return m_version == kLatestVersion; } + +private: + uint32_t m_version = 0; + uint32_t m_amount = 0; +}; + +void SerializeSpeedCamera(FileWriter & writer, uint32_t prevFeatureId, SpeedCameraMetadata const & data); +} // namespace routing |