Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Gorbushin <m.gorbushin@corp.mail.ru>2018-08-17 17:12:58 +0300
committerMikhail Gorbushin <m.gorbushin@corp.mail.ru>2018-09-05 13:50:45 +0300
commit03fa341b7ce54763cac226f8f93f9d0dc53d0486 (patch)
tree091c77664bf2b85fd0a11a611ca3688b2a50f4c1
parent75204f8440e7efce6c691c5783f8c630e95b1cb8 (diff)
[routing] routing part + routing testsMAPSME-8120.speed_cam.ROUTING_PART
-rw-r--r--routing/deserialize_speed_cameras.cpp71
-rw-r--r--routing/deserialize_speed_cameras.hpp33
-rw-r--r--routing/routing_integration_tests/CMakeLists.txt18
-rw-r--r--routing/routing_integration_tests/speed_camera_notification_test.cpp90
-rw-r--r--routing/serialize_speed_camera.cpp45
-rw-r--r--routing/serialize_speed_camera.hpp80
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