diff --git a/Dockerfile.openpilot_base b/Dockerfile.openpilot_base index bca2ac4c66..b05b180bd1 100644 --- a/Dockerfile.openpilot_base +++ b/Dockerfile.openpilot_base @@ -28,6 +28,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ liblzma-dev \ libomp-dev \ libopencv-dev \ + libqt5sql5-sqlite \ + libqt5svg5-dev \ libsqlite3-dev \ libssl-dev \ libsystemd-dev \ @@ -40,7 +42,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python-dev \ qml-module-qtquick2 \ qt5-default \ + qtlocation5-dev \ qtmultimedia5-dev \ + qtpositioning5-dev \ qtwebengine5-dev \ sudo \ valgrind \ diff --git a/SConstruct b/SConstruct index 138c6ab3f5..2e38e8bb44 100644 --- a/SConstruct +++ b/SConstruct @@ -128,6 +128,7 @@ else: libpath = [ "#phonelibs/snpe/x86_64-linux-clang", "#phonelibs/libyuv/x64/lib", + "#phonelibs/mapbox-gl-native-qt/x86_64", "#cereal", "#selfdrive/common", "/usr/lib", @@ -190,6 +191,7 @@ env = Environment( "#phonelibs/android_system_core/include", "#phonelibs/linux/include", "#phonelibs/snpe/include", + "#phonelibs/mapbox-gl-native-qt/include", "#phonelibs/nanovg", "#phonelibs/qrcode", "#phonelibs", @@ -272,7 +274,7 @@ Export('envCython') # Qt build environment qt_env = env.Clone() -qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets"] +qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "Location", "Positioning"] if arch != "aarch64": qt_modules += ["DBus"] diff --git a/phonelibs/mapbox-gl-native-qt/.gitattributes b/phonelibs/mapbox-gl-native-qt/.gitattributes new file mode 100644 index 0000000000..323c737ba1 --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/.gitattributes @@ -0,0 +1,2 @@ +x86_64 filter=lfs diff=lfs merge=lfs -text +larch64 filter=lfs diff=lfs merge=lfs -text diff --git a/phonelibs/mapbox-gl-native-qt/build.sh b/phonelibs/mapbox-gl-native-qt/build.sh new file mode 100755 index 0000000000..f2936fad3d --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +cd /tmp +git clone --recursive https://github.com/commaai/mapbox-gl-native.git +cd mapbox-gl-native +mkdir build && cd build +cmake -DMBGL_WITH_QT=ON .. +make -j$(nproc) mbgl-qt diff --git a/phonelibs/mapbox-gl-native-qt/include/QMapbox b/phonelibs/mapbox-gl-native-qt/include/QMapbox new file mode 100644 index 0000000000..a8479c09aa --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/include/QMapbox @@ -0,0 +1 @@ +#include "qmapbox.hpp" diff --git a/phonelibs/mapbox-gl-native-qt/include/QMapboxGL b/phonelibs/mapbox-gl-native-qt/include/QMapboxGL new file mode 100644 index 0000000000..15b55a9abe --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/include/QMapboxGL @@ -0,0 +1 @@ +#include "qmapboxgl.hpp" diff --git a/phonelibs/mapbox-gl-native-qt/include/qmapbox.hpp b/phonelibs/mapbox-gl-native-qt/include/qmapbox.hpp new file mode 100644 index 0000000000..3acc9d55e0 --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/include/qmapbox.hpp @@ -0,0 +1,147 @@ +#ifndef QMAPBOX_H +#define QMAPBOX_H + +#include +#include +#include +#include +#include + +// This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style + +#if !defined(QT_MAPBOXGL_STATIC) +# if defined(QT_BUILD_MAPBOXGL_LIB) +# define Q_MAPBOXGL_EXPORT Q_DECL_EXPORT +# else +# define Q_MAPBOXGL_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_MAPBOXGL_EXPORT +#endif + +namespace QMapbox { + +typedef QPair Coordinate; +typedef QPair CoordinateZoom; +typedef QPair ProjectedMeters; + +typedef QVector Coordinates; +typedef QVector CoordinatesCollection; + +typedef QVector CoordinatesCollections; + +struct Q_MAPBOXGL_EXPORT Feature { + enum Type { + PointType = 1, + LineStringType, + PolygonType + }; + + /*! Class constructor. */ + Feature(Type type_ = PointType, const CoordinatesCollections& geometry_ = CoordinatesCollections(), + const QVariantMap& properties_ = QVariantMap(), const QVariant& id_ = QVariant()) + : type(type_), geometry(geometry_), properties(properties_), id(id_) {} + + Type type; + CoordinatesCollections geometry; + QVariantMap properties; + QVariant id; +}; + +struct Q_MAPBOXGL_EXPORT ShapeAnnotationGeometry { + enum Type { + LineStringType = 1, + PolygonType, + MultiLineStringType, + MultiPolygonType + }; + + /*! Class constructor. */ + ShapeAnnotationGeometry(Type type_ = LineStringType, const CoordinatesCollections& geometry_ = CoordinatesCollections()) + : type(type_), geometry(geometry_) {} + + Type type; + CoordinatesCollections geometry; +}; + +struct Q_MAPBOXGL_EXPORT SymbolAnnotation { + Coordinate geometry; + QString icon; +}; + +struct Q_MAPBOXGL_EXPORT LineAnnotation { + /*! Class constructor. */ + LineAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f, + float width_ = 1.0f, const QColor& color_ = Qt::black) + : geometry(geometry_), opacity(opacity_), width(width_), color(color_) {} + + ShapeAnnotationGeometry geometry; + float opacity; + float width; + QColor color; +}; + +struct Q_MAPBOXGL_EXPORT FillAnnotation { + /*! Class constructor. */ + FillAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f, + const QColor& color_ = Qt::black, const QVariant& outlineColor_ = QVariant()) + : geometry(geometry_), opacity(opacity_), color(color_), outlineColor(outlineColor_) {} + + ShapeAnnotationGeometry geometry; + float opacity; + QColor color; + QVariant outlineColor; +}; + +typedef QVariant Annotation; +typedef quint32 AnnotationID; +typedef QVector AnnotationIDs; + +enum NetworkMode { + Online, // Default + Offline, +}; + +Q_MAPBOXGL_EXPORT QVector >& defaultStyles(); + +Q_MAPBOXGL_EXPORT NetworkMode networkMode(); +Q_MAPBOXGL_EXPORT void setNetworkMode(NetworkMode); + +// This struct is a 1:1 copy of mbgl::CustomLayerRenderParameters. +struct Q_MAPBOXGL_EXPORT CustomLayerRenderParameters { + double width; + double height; + double latitude; + double longitude; + double zoom; + double bearing; + double pitch; + double fieldOfView; +}; + +class Q_MAPBOXGL_EXPORT CustomLayerHostInterface { +public: + virtual ~CustomLayerHostInterface() = default; + virtual void initialize() = 0; + virtual void render(const CustomLayerRenderParameters&) = 0; + virtual void deinitialize() = 0; +}; + +Q_MAPBOXGL_EXPORT double metersPerPixelAtLatitude(double latitude, double zoom); +Q_MAPBOXGL_EXPORT ProjectedMeters projectedMetersForCoordinate(const Coordinate &); +Q_MAPBOXGL_EXPORT Coordinate coordinateForProjectedMeters(const ProjectedMeters &); + +} // namespace QMapbox + +Q_DECLARE_METATYPE(QMapbox::Coordinate); +Q_DECLARE_METATYPE(QMapbox::Coordinates); +Q_DECLARE_METATYPE(QMapbox::CoordinatesCollection); +Q_DECLARE_METATYPE(QMapbox::CoordinatesCollections); +Q_DECLARE_METATYPE(QMapbox::Feature); + +Q_DECLARE_METATYPE(QMapbox::SymbolAnnotation); +Q_DECLARE_METATYPE(QMapbox::ShapeAnnotationGeometry); +Q_DECLARE_METATYPE(QMapbox::LineAnnotation); +Q_DECLARE_METATYPE(QMapbox::FillAnnotation); + +#endif // QMAPBOX_H diff --git a/phonelibs/mapbox-gl-native-qt/include/qmapboxgl.hpp b/phonelibs/mapbox-gl-native-qt/include/qmapboxgl.hpp new file mode 100644 index 0000000000..337991aa1c --- /dev/null +++ b/phonelibs/mapbox-gl-native-qt/include/qmapboxgl.hpp @@ -0,0 +1,277 @@ +#ifndef QMAPBOXGL_H +#define QMAPBOXGL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class QMapboxGLPrivate; + +// This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style + +class Q_MAPBOXGL_EXPORT QMapboxGLSettings +{ +public: + QMapboxGLSettings(); + + enum GLContextMode { + UniqueGLContext = 0, + SharedGLContext + }; + + enum MapMode { + Continuous = 0, + Static + }; + + enum ConstrainMode { + NoConstrain = 0, + ConstrainHeightOnly, + ConstrainWidthAndHeight + }; + + enum ViewportMode { + DefaultViewport = 0, + FlippedYViewport + }; + + GLContextMode contextMode() const; + void setContextMode(GLContextMode); + + MapMode mapMode() const; + void setMapMode(MapMode); + + ConstrainMode constrainMode() const; + void setConstrainMode(ConstrainMode); + + ViewportMode viewportMode() const; + void setViewportMode(ViewportMode); + + unsigned cacheDatabaseMaximumSize() const; + void setCacheDatabaseMaximumSize(unsigned); + + QString cacheDatabasePath() const; + void setCacheDatabasePath(const QString &); + + QString assetPath() const; + void setAssetPath(const QString &); + + QString accessToken() const; + void setAccessToken(const QString &); + + QString apiBaseUrl() const; + void setApiBaseUrl(const QString &); + + QString localFontFamily() const; + void setLocalFontFamily(const QString &); + + std::function resourceTransform() const; + void setResourceTransform(const std::function &); + +private: + GLContextMode m_contextMode; + MapMode m_mapMode; + ConstrainMode m_constrainMode; + ViewportMode m_viewportMode; + + unsigned m_cacheMaximumSize; + QString m_cacheDatabasePath; + QString m_assetPath; + QString m_accessToken; + QString m_apiBaseUrl; + QString m_localFontFamily; + std::function m_resourceTransform; +}; + +struct Q_MAPBOXGL_EXPORT QMapboxGLCameraOptions { + QVariant center; // Coordinate + QVariant anchor; // QPointF + QVariant zoom; // double + QVariant bearing; // double + QVariant pitch; // double +}; + +class Q_MAPBOXGL_EXPORT QMapboxGL : public QObject +{ + Q_OBJECT + Q_PROPERTY(double latitude READ latitude WRITE setLatitude) + Q_PROPERTY(double longitude READ longitude WRITE setLongitude) + Q_PROPERTY(double zoom READ zoom WRITE setZoom) + Q_PROPERTY(double bearing READ bearing WRITE setBearing) + Q_PROPERTY(double pitch READ pitch WRITE setPitch) + Q_PROPERTY(QString styleJson READ styleJson WRITE setStyleJson) + Q_PROPERTY(QString styleUrl READ styleUrl WRITE setStyleUrl) + Q_PROPERTY(double scale READ scale WRITE setScale) + Q_PROPERTY(QMapbox::Coordinate coordinate READ coordinate WRITE setCoordinate) + Q_PROPERTY(QMargins margins READ margins WRITE setMargins) + +public: + enum MapChange { + MapChangeRegionWillChange = 0, + MapChangeRegionWillChangeAnimated, + MapChangeRegionIsChanging, + MapChangeRegionDidChange, + MapChangeRegionDidChangeAnimated, + MapChangeWillStartLoadingMap, + MapChangeDidFinishLoadingMap, + MapChangeDidFailLoadingMap, + MapChangeWillStartRenderingFrame, + MapChangeDidFinishRenderingFrame, + MapChangeDidFinishRenderingFrameFullyRendered, + MapChangeWillStartRenderingMap, + MapChangeDidFinishRenderingMap, + MapChangeDidFinishRenderingMapFullyRendered, + MapChangeDidFinishLoadingStyle, + MapChangeSourceDidChange + }; + + enum MapLoadingFailure { + StyleParseFailure, + StyleLoadFailure, + NotFoundFailure, + UnknownFailure + }; + + // Determines the orientation of the map. + enum NorthOrientation { + NorthUpwards, // Default + NorthRightwards, + NorthDownwards, + NorthLeftwards, + }; + + QMapboxGL(QObject* parent = 0, + const QMapboxGLSettings& = QMapboxGLSettings(), + const QSize& size = QSize(), + qreal pixelRatio = 1); + virtual ~QMapboxGL(); + + QString styleJson() const; + QString styleUrl() const; + + void setStyleJson(const QString &); + void setStyleUrl(const QString &); + + double latitude() const; + void setLatitude(double latitude); + + double longitude() const; + void setLongitude(double longitude); + + double scale() const; + void setScale(double scale, const QPointF ¢er = QPointF()); + + double zoom() const; + void setZoom(double zoom); + + double minimumZoom() const; + double maximumZoom() const; + + double bearing() const; + void setBearing(double degrees); + void setBearing(double degrees, const QPointF ¢er); + + double pitch() const; + void setPitch(double pitch); + void pitchBy(double pitch); + + NorthOrientation northOrientation() const; + void setNorthOrientation(NorthOrientation); + + QMapbox::Coordinate coordinate() const; + void setCoordinate(const QMapbox::Coordinate &); + void setCoordinateZoom(const QMapbox::Coordinate &, double zoom); + + void jumpTo(const QMapboxGLCameraOptions&); + + void setGestureInProgress(bool inProgress); + + void setTransitionOptions(qint64 duration, qint64 delay = 0); + + void addAnnotationIcon(const QString &name, const QImage &sprite); + + QMapbox::AnnotationID addAnnotation(const QMapbox::Annotation &); + void updateAnnotation(QMapbox::AnnotationID, const QMapbox::Annotation &); + void removeAnnotation(QMapbox::AnnotationID); + + bool setLayoutProperty(const QString &layer, const QString &property, const QVariant &value); + bool setPaintProperty(const QString &layer, const QString &property, const QVariant &value); + + bool isFullyLoaded() const; + + void moveBy(const QPointF &offset); + void scaleBy(double scale, const QPointF ¢er = QPointF()); + void rotateBy(const QPointF &first, const QPointF &second); + + void resize(const QSize &size); + + double metersPerPixelAtLatitude(double latitude, double zoom) const; + QMapbox::ProjectedMeters projectedMetersForCoordinate(const QMapbox::Coordinate &) const; + QMapbox::Coordinate coordinateForProjectedMeters(const QMapbox::ProjectedMeters &) const; + QPointF pixelForCoordinate(const QMapbox::Coordinate &) const; + QMapbox::Coordinate coordinateForPixel(const QPointF &) const; + + QMapbox::CoordinateZoom coordinateZoomForBounds(const QMapbox::Coordinate &sw, QMapbox::Coordinate &ne) const; + QMapbox::CoordinateZoom coordinateZoomForBounds(const QMapbox::Coordinate &sw, QMapbox::Coordinate &ne, double bearing, double pitch); + + void setMargins(const QMargins &margins); + QMargins margins() const; + + void addSource(const QString &sourceID, const QVariantMap& params); + bool sourceExists(const QString &sourceID); + void updateSource(const QString &sourceID, const QVariantMap& params); + void removeSource(const QString &sourceID); + + void addImage(const QString &name, const QImage &sprite); + void removeImage(const QString &name); + + void addCustomLayer(const QString &id, + QScopedPointer& host, + const QString& before = QString()); + void addLayer(const QVariantMap ¶ms, const QString& before = QString()); + bool layerExists(const QString &id); + void removeLayer(const QString &id); + + QVector layerIds() const; + + void setFilter(const QString &layer, const QVariant &filter); + QVariant getFilter(const QString &layer) const; + // When rendering on a different thread, + // should be called on the render thread. + void createRenderer(); + void destroyRenderer(); + void setFramebufferObject(quint32 fbo, const QSize &size); + +public slots: + void render(); + void connectionEstablished(); + + // Commit changes, load all the resources + // and renders the map when completed. + void startStaticRender(); + +signals: + void needsRendering(); + void mapChanged(QMapboxGL::MapChange); + void mapLoadingFailed(QMapboxGL::MapLoadingFailure, const QString &reason); + void copyrightsChanged(const QString ©rightsHtml); + + void staticRenderFinished(const QString &error); + +private: + Q_DISABLE_COPY(QMapboxGL) + + QMapboxGLPrivate *d_ptr; +}; + +Q_DECLARE_METATYPE(QMapboxGL::MapChange); +Q_DECLARE_METATYPE(QMapboxGL::MapLoadingFailure); + +#endif // QMAPBOXGL_H diff --git a/phonelibs/mapbox-gl-native-qt/x86_64/libqmapboxgl.so b/phonelibs/mapbox-gl-native-qt/x86_64/libqmapboxgl.so new file mode 100755 index 0000000000..fe3f049f57 Binary files /dev/null and b/phonelibs/mapbox-gl-native-qt/x86_64/libqmapboxgl.so differ diff --git a/phonelibs/qt-plugins/.gitattributes b/phonelibs/qt-plugins/.gitattributes new file mode 100644 index 0000000000..e74eb23bf4 --- /dev/null +++ b/phonelibs/qt-plugins/.gitattributes @@ -0,0 +1 @@ +x86_64 filter=lfs diff=lfs merge=lfs -text diff --git a/phonelibs/qt-plugins/build_qtlocation.sh b/phonelibs/qt-plugins/build_qtlocation.sh new file mode 100755 index 0000000000..09e6182d1f --- /dev/null +++ b/phonelibs/qt-plugins/build_qtlocation.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +# Qtlocation plugin with extra fields parsed from api response +cd /tmp +git clone https://github.com/commaai/qtlocation.git +cd qtlocation +qmake +make -j$(nproc) diff --git a/phonelibs/qt-plugins/x86_64/geoservices/libqtgeoservices_mapbox.so b/phonelibs/qt-plugins/x86_64/geoservices/libqtgeoservices_mapbox.so new file mode 100755 index 0000000000..0a73180d3a Binary files /dev/null and b/phonelibs/qt-plugins/x86_64/geoservices/libqtgeoservices_mapbox.so differ diff --git a/selfdrive/assets/images/triangle.svg b/selfdrive/assets/images/triangle.svg new file mode 100644 index 0000000000..9320269bde --- /dev/null +++ b/selfdrive/assets/images/triangle.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/selfdrive/assets/navigation/direction_arrive.png b/selfdrive/assets/navigation/direction_arrive.png new file mode 100644 index 0000000000..733c129091 Binary files /dev/null and b/selfdrive/assets/navigation/direction_arrive.png differ diff --git a/selfdrive/assets/navigation/direction_arrive_left.png b/selfdrive/assets/navigation/direction_arrive_left.png new file mode 100644 index 0000000000..92ff8e0341 Binary files /dev/null and b/selfdrive/assets/navigation/direction_arrive_left.png differ diff --git a/selfdrive/assets/navigation/direction_arrive_right.png b/selfdrive/assets/navigation/direction_arrive_right.png new file mode 100644 index 0000000000..f5983bfe61 Binary files /dev/null and b/selfdrive/assets/navigation/direction_arrive_right.png differ diff --git a/selfdrive/assets/navigation/direction_arrive_straight.png b/selfdrive/assets/navigation/direction_arrive_straight.png new file mode 100644 index 0000000000..733c129091 Binary files /dev/null and b/selfdrive/assets/navigation/direction_arrive_straight.png differ diff --git a/selfdrive/assets/navigation/direction_close.png b/selfdrive/assets/navigation/direction_close.png new file mode 100644 index 0000000000..4fdb5d195d Binary files /dev/null and b/selfdrive/assets/navigation/direction_close.png differ diff --git a/selfdrive/assets/navigation/direction_continue.png b/selfdrive/assets/navigation/direction_continue.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue.png differ diff --git a/selfdrive/assets/navigation/direction_continue_left.png b/selfdrive/assets/navigation/direction_continue_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_left.png differ diff --git a/selfdrive/assets/navigation/direction_continue_right.png b/selfdrive/assets/navigation/direction_continue_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_right.png differ diff --git a/selfdrive/assets/navigation/direction_continue_slight_left.png b/selfdrive/assets/navigation/direction_continue_slight_left.png new file mode 100644 index 0000000000..08e964dbd6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_continue_slight_right.png b/selfdrive/assets/navigation/direction_continue_slight_right.png new file mode 100644 index 0000000000..3e21cae11e Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_continue_straight.png b/selfdrive/assets/navigation/direction_continue_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_straight.png differ diff --git a/selfdrive/assets/navigation/direction_continue_uturn.png b/selfdrive/assets/navigation/direction_continue_uturn.png new file mode 100644 index 0000000000..0bd1b91777 Binary files /dev/null and b/selfdrive/assets/navigation/direction_continue_uturn.png differ diff --git a/selfdrive/assets/navigation/direction_depart.png b/selfdrive/assets/navigation/direction_depart.png new file mode 100644 index 0000000000..4bf32c870d Binary files /dev/null and b/selfdrive/assets/navigation/direction_depart.png differ diff --git a/selfdrive/assets/navigation/direction_depart_left.png b/selfdrive/assets/navigation/direction_depart_left.png new file mode 100644 index 0000000000..1f8d726911 Binary files /dev/null and b/selfdrive/assets/navigation/direction_depart_left.png differ diff --git a/selfdrive/assets/navigation/direction_depart_right.png b/selfdrive/assets/navigation/direction_depart_right.png new file mode 100644 index 0000000000..f359a685ff Binary files /dev/null and b/selfdrive/assets/navigation/direction_depart_right.png differ diff --git a/selfdrive/assets/navigation/direction_depart_straight.png b/selfdrive/assets/navigation/direction_depart_straight.png new file mode 100644 index 0000000000..4bf32c870d Binary files /dev/null and b/selfdrive/assets/navigation/direction_depart_straight.png differ diff --git a/selfdrive/assets/navigation/direction_end_of_road_left.png b/selfdrive/assets/navigation/direction_end_of_road_left.png new file mode 100644 index 0000000000..5c0a24e7cb Binary files /dev/null and b/selfdrive/assets/navigation/direction_end_of_road_left.png differ diff --git a/selfdrive/assets/navigation/direction_end_of_road_right.png b/selfdrive/assets/navigation/direction_end_of_road_right.png new file mode 100644 index 0000000000..8d9b89d36c Binary files /dev/null and b/selfdrive/assets/navigation/direction_end_of_road_right.png differ diff --git a/selfdrive/assets/navigation/direction_flag.png b/selfdrive/assets/navigation/direction_flag.png new file mode 100644 index 0000000000..bad12ec666 Binary files /dev/null and b/selfdrive/assets/navigation/direction_flag.png differ diff --git a/selfdrive/assets/navigation/direction_fork.png b/selfdrive/assets/navigation/direction_fork.png new file mode 100644 index 0000000000..3e0c262e2a Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork.png differ diff --git a/selfdrive/assets/navigation/direction_fork_left.png b/selfdrive/assets/navigation/direction_fork_left.png new file mode 100644 index 0000000000..b244b42b51 Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork_left.png differ diff --git a/selfdrive/assets/navigation/direction_fork_right.png b/selfdrive/assets/navigation/direction_fork_right.png new file mode 100644 index 0000000000..aa3efaabca Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork_right.png differ diff --git a/selfdrive/assets/navigation/direction_fork_slight_left.png b/selfdrive/assets/navigation/direction_fork_slight_left.png new file mode 100644 index 0000000000..82fa59859b Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_fork_slight_right.png b/selfdrive/assets/navigation/direction_fork_slight_right.png new file mode 100644 index 0000000000..3596a2fbf2 Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_fork_straight.png b/selfdrive/assets/navigation/direction_fork_straight.png new file mode 100644 index 0000000000..86f30ab9b6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_fork_straight.png differ diff --git a/selfdrive/assets/navigation/direction_invalid.png b/selfdrive/assets/navigation/direction_invalid.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_left.png b/selfdrive/assets/navigation/direction_invalid_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_left.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_right.png b/selfdrive/assets/navigation/direction_invalid_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_right.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_slight_left.png b/selfdrive/assets/navigation/direction_invalid_slight_left.png new file mode 100644 index 0000000000..08e964dbd6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_slight_right.png b/selfdrive/assets/navigation/direction_invalid_slight_right.png new file mode 100644 index 0000000000..3e21cae11e Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_straight.png b/selfdrive/assets/navigation/direction_invalid_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_straight.png differ diff --git a/selfdrive/assets/navigation/direction_invalid_uturn.png b/selfdrive/assets/navigation/direction_invalid_uturn.png new file mode 100644 index 0000000000..0bd1b91777 Binary files /dev/null and b/selfdrive/assets/navigation/direction_invalid_uturn.png differ diff --git a/selfdrive/assets/navigation/direction_merge_left.png b/selfdrive/assets/navigation/direction_merge_left.png new file mode 100644 index 0000000000..a713f52c56 Binary files /dev/null and b/selfdrive/assets/navigation/direction_merge_left.png differ diff --git a/selfdrive/assets/navigation/direction_merge_right.png b/selfdrive/assets/navigation/direction_merge_right.png new file mode 100644 index 0000000000..3390b31a05 Binary files /dev/null and b/selfdrive/assets/navigation/direction_merge_right.png differ diff --git a/selfdrive/assets/navigation/direction_merge_slight_left.png b/selfdrive/assets/navigation/direction_merge_slight_left.png new file mode 100644 index 0000000000..308f97b5a5 Binary files /dev/null and b/selfdrive/assets/navigation/direction_merge_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_merge_slight_right.png b/selfdrive/assets/navigation/direction_merge_slight_right.png new file mode 100644 index 0000000000..8f5289011d Binary files /dev/null and b/selfdrive/assets/navigation/direction_merge_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_merge_straight.png b/selfdrive/assets/navigation/direction_merge_straight.png new file mode 100644 index 0000000000..49c464389d Binary files /dev/null and b/selfdrive/assets/navigation/direction_merge_straight.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_left.png b/selfdrive/assets/navigation/direction_new_name_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_left.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_right.png b/selfdrive/assets/navigation/direction_new_name_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_right.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_sharp_left.png b/selfdrive/assets/navigation/direction_new_name_sharp_left.png new file mode 100644 index 0000000000..77106b493f Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_sharp_right.png b/selfdrive/assets/navigation/direction_new_name_sharp_right.png new file mode 100644 index 0000000000..eb3a02f8b3 Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_slight_left.png b/selfdrive/assets/navigation/direction_new_name_slight_left.png new file mode 100644 index 0000000000..08e964dbd6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_slight_right.png b/selfdrive/assets/navigation/direction_new_name_slight_right.png new file mode 100644 index 0000000000..3e21cae11e Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_new_name_straight.png b/selfdrive/assets/navigation/direction_new_name_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_new_name_straight.png differ diff --git a/selfdrive/assets/navigation/direction_notificaiton_right.png b/selfdrive/assets/navigation/direction_notificaiton_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_notificaiton_right.png differ diff --git a/selfdrive/assets/navigation/direction_notificaiton_sharp_right.png b/selfdrive/assets/navigation/direction_notificaiton_sharp_right.png new file mode 100644 index 0000000000..a7e3c4cee5 Binary files /dev/null and b/selfdrive/assets/navigation/direction_notificaiton_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_notification_left.png b/selfdrive/assets/navigation/direction_notification_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_notification_left.png differ diff --git a/selfdrive/assets/navigation/direction_notification_sharp_left.png b/selfdrive/assets/navigation/direction_notification_sharp_left.png new file mode 100644 index 0000000000..dd8a4301db Binary files /dev/null and b/selfdrive/assets/navigation/direction_notification_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_notification_slight_left.png b/selfdrive/assets/navigation/direction_notification_slight_left.png new file mode 100644 index 0000000000..08e964dbd6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_notification_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_notification_slight_right.png b/selfdrive/assets/navigation/direction_notification_slight_right.png new file mode 100644 index 0000000000..3e21cae11e Binary files /dev/null and b/selfdrive/assets/navigation/direction_notification_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_notification_straight.png b/selfdrive/assets/navigation/direction_notification_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_notification_straight.png differ diff --git a/selfdrive/assets/navigation/direction_off_ramp_left.png b/selfdrive/assets/navigation/direction_off_ramp_left.png new file mode 100644 index 0000000000..d3fd182893 Binary files /dev/null and b/selfdrive/assets/navigation/direction_off_ramp_left.png differ diff --git a/selfdrive/assets/navigation/direction_off_ramp_right.png b/selfdrive/assets/navigation/direction_off_ramp_right.png new file mode 100644 index 0000000000..722e3f808f Binary files /dev/null and b/selfdrive/assets/navigation/direction_off_ramp_right.png differ diff --git a/selfdrive/assets/navigation/direction_off_ramp_slight_left.png b/selfdrive/assets/navigation/direction_off_ramp_slight_left.png new file mode 100644 index 0000000000..ddac4aad66 Binary files /dev/null and b/selfdrive/assets/navigation/direction_off_ramp_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_off_ramp_slight_right.png b/selfdrive/assets/navigation/direction_off_ramp_slight_right.png new file mode 100644 index 0000000000..ed57608864 Binary files /dev/null and b/selfdrive/assets/navigation/direction_off_ramp_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_left.png b/selfdrive/assets/navigation/direction_on_ramp_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_left.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_right.png b/selfdrive/assets/navigation/direction_on_ramp_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_right.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_sharp_left.png b/selfdrive/assets/navigation/direction_on_ramp_sharp_left.png new file mode 100644 index 0000000000..77106b493f Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_sharp_right.png b/selfdrive/assets/navigation/direction_on_ramp_sharp_right.png new file mode 100644 index 0000000000..a7e3c4cee5 Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_slight_left.png b/selfdrive/assets/navigation/direction_on_ramp_slight_left.png new file mode 100644 index 0000000000..a5ea8a881e Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_slight_right.png b/selfdrive/assets/navigation/direction_on_ramp_slight_right.png new file mode 100644 index 0000000000..f8ea3800e8 Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_on_ramp_straight.png b/selfdrive/assets/navigation/direction_on_ramp_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_on_ramp_straight.png differ diff --git a/selfdrive/assets/navigation/direction_rotary.png b/selfdrive/assets/navigation/direction_rotary.png new file mode 100644 index 0000000000..2a5d264bd2 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_left.png b/selfdrive/assets/navigation/direction_rotary_left.png new file mode 100644 index 0000000000..0c4e4ab5e6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_left.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_right.png b/selfdrive/assets/navigation/direction_rotary_right.png new file mode 100644 index 0000000000..32a6b2504b Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_right.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_sharp_left.png b/selfdrive/assets/navigation/direction_rotary_sharp_left.png new file mode 100644 index 0000000000..c84a6d96c0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_sharp_right.png b/selfdrive/assets/navigation/direction_rotary_sharp_right.png new file mode 100644 index 0000000000..d15cbee002 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_slight_left.png b/selfdrive/assets/navigation/direction_rotary_slight_left.png new file mode 100644 index 0000000000..3838e720a3 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_slight_right.png b/selfdrive/assets/navigation/direction_rotary_slight_right.png new file mode 100644 index 0000000000..8cd45fe612 Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_rotary_straight.png b/selfdrive/assets/navigation/direction_rotary_straight.png new file mode 100644 index 0000000000..b6b0a7311b Binary files /dev/null and b/selfdrive/assets/navigation/direction_rotary_straight.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout.png b/selfdrive/assets/navigation/direction_roundabout.png new file mode 100644 index 0000000000..2a5d264bd2 Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_left.png b/selfdrive/assets/navigation/direction_roundabout_left.png new file mode 100644 index 0000000000..0c4e4ab5e6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_left.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_right.png b/selfdrive/assets/navigation/direction_roundabout_right.png new file mode 100644 index 0000000000..32a6b2504b Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_right.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_sharp_left.png b/selfdrive/assets/navigation/direction_roundabout_sharp_left.png new file mode 100644 index 0000000000..1e8cce8c8e Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_sharp_right.png b/selfdrive/assets/navigation/direction_roundabout_sharp_right.png new file mode 100644 index 0000000000..d15cbee002 Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_slight_left.png b/selfdrive/assets/navigation/direction_roundabout_slight_left.png new file mode 100644 index 0000000000..da1b112705 Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_slight_right.png b/selfdrive/assets/navigation/direction_roundabout_slight_right.png new file mode 100644 index 0000000000..8cd45fe612 Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_roundabout_straight.png b/selfdrive/assets/navigation/direction_roundabout_straight.png new file mode 100644 index 0000000000..b6b0a7311b Binary files /dev/null and b/selfdrive/assets/navigation/direction_roundabout_straight.png differ diff --git a/selfdrive/assets/navigation/direction_turn_left.png b/selfdrive/assets/navigation/direction_turn_left.png new file mode 100644 index 0000000000..9a618026f0 Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_left.png differ diff --git a/selfdrive/assets/navigation/direction_turn_right.png b/selfdrive/assets/navigation/direction_turn_right.png new file mode 100644 index 0000000000..0fbaa3f253 Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_right.png differ diff --git a/selfdrive/assets/navigation/direction_turn_sharp_left.png b/selfdrive/assets/navigation/direction_turn_sharp_left.png new file mode 100644 index 0000000000..dd8a4301db Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_sharp_left.png differ diff --git a/selfdrive/assets/navigation/direction_turn_sharp_right.png b/selfdrive/assets/navigation/direction_turn_sharp_right.png new file mode 100644 index 0000000000..a7e3c4cee5 Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_sharp_right.png differ diff --git a/selfdrive/assets/navigation/direction_turn_slight_left.png b/selfdrive/assets/navigation/direction_turn_slight_left.png new file mode 100644 index 0000000000..08e964dbd6 Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_slight_left.png differ diff --git a/selfdrive/assets/navigation/direction_turn_slight_right.png b/selfdrive/assets/navigation/direction_turn_slight_right.png new file mode 100644 index 0000000000..3e21cae11e Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_slight_right.png differ diff --git a/selfdrive/assets/navigation/direction_turn_straight.png b/selfdrive/assets/navigation/direction_turn_straight.png new file mode 100644 index 0000000000..a01045ae6a Binary files /dev/null and b/selfdrive/assets/navigation/direction_turn_straight.png differ diff --git a/selfdrive/assets/navigation/direction_updown.png b/selfdrive/assets/navigation/direction_updown.png new file mode 100644 index 0000000000..16d0979f3e Binary files /dev/null and b/selfdrive/assets/navigation/direction_updown.png differ diff --git a/selfdrive/assets/navigation/direction_uturn.png b/selfdrive/assets/navigation/direction_uturn.png new file mode 100644 index 0000000000..0bd1b91777 Binary files /dev/null and b/selfdrive/assets/navigation/direction_uturn.png differ diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index e71b5b80e6..5a299e475d 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -131,6 +131,17 @@ def getMessage(service=None, timeout=1000): return ret.to_dict() +@dispatcher.add_method +def setNavDestination(latitude=0, longitude=0): + destination = { + "latitude": latitude, + "longitude": longitude, + } + Params().put("NavDestination", json.dumps(destination)) + + return {"success": 1} + + @dispatcher.add_method def listDataDirectory(): files = [os.path.relpath(os.path.join(dp, f), ROOT) for dp, dn, fn in os.walk(ROOT) for f in fn] diff --git a/selfdrive/common/params.cc b/selfdrive/common/params.cc index 87d338ed70..fc5fd38061 100644 --- a/selfdrive/common/params.cc +++ b/selfdrive/common/params.cc @@ -183,6 +183,8 @@ std::unordered_map keys = { {"LastUpdateException", PERSISTENT}, {"LastUpdateTime", PERSISTENT}, {"LiveParameters", PERSISTENT}, + {"MapboxToken", PERSISTENT}, + {"NavDestination", PERSISTENT}, // TODO: CLEAR_ON_MANAGER_START {"OpenpilotEnabledToggle", PERSISTENT}, {"PandaFirmware", CLEAR_ON_MANAGER_START | CLEAR_ON_PANDA_DISCONNECT}, {"PandaFirmwareHex", CLEAR_ON_MANAGER_START | CLEAR_ON_PANDA_DISCONNECT}, diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 5be9e43328..c9fe988ca9 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -4,9 +4,17 @@ Import('qt_env', 'arch', 'common', 'messaging', 'gpucommon', 'visionipc', base_libs = [gpucommon, common, messaging, cereal, visionipc, transformations, 'zmq', 'capnp', 'kj', 'm', 'OpenCL', 'ssl', 'crypto', 'pthread'] + qt_env["LIBS"] + +maps = arch in ['larch64', 'x86_64'] and \ + os.path.exists(File("qt/maps/map.cc").srcnode().abspath) + if arch == 'aarch64': base_libs += ['log', 'utils', 'gui', 'ui', 'CB', 'gsl', 'adreno_utils', 'cutils', 'uuid'] +if maps and arch in ['x86_64']: + rpath = [Dir(f"#phonelibs/mapbox-gl-native-qt/{arch}").srcnode().abspath] + qt_env["RPATH"] += rpath + if arch == "Darwin": del base_libs[base_libs.index('OpenCL')] qt_env['FRAMEWORKS'] += ['OpenCL'] @@ -16,9 +24,15 @@ widgets_src = ["qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/offroad_alerts.cc", "qt/widgets/setup.cc", "qt/widgets/keyboard.cc", "qt/widgets/scrollview.cc", "#phonelibs/qrcode/QrCode.cc", "qt/api.cc", "qt/request_repeater.cc"] + if arch != 'aarch64': widgets_src += ["qt/offroad/networking.cc", "qt/offroad/wifiManager.cc"] +if maps: + base_libs += ['qmapboxgl'] + widgets_src += ["qt/maps/map_helpers.cc", "qt/maps/map.cc"] + qt_env['CPPDEFINES'] = ["ENABLE_MAPS"] + widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=base_libs) qt_libs = [widgets] + base_libs diff --git a/selfdrive/ui/paint.cc b/selfdrive/ui/paint.cc index ab46cff65a..854533fc3c 100644 --- a/selfdrive/ui/paint.cc +++ b/selfdrive/ui/paint.cc @@ -442,7 +442,7 @@ static mat4 get_driver_view_transform() { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, }}; - + } else { // frame from 4/3 to 16/9 display transform = (mat4){{ @@ -534,6 +534,14 @@ void ui_nvg_init(UIState *s) { glBindVertexArray(0); } + ui_resize(s, s->fb_w, s->fb_h); +} + + +void ui_resize(UIState *s, int width, int height){ + s->fb_w = width; + s->fb_h = height; + auto intrinsic_matrix = s->wide_camera ? ecam_intrinsic_matrix : fcam_intrinsic_matrix; s->zoom = zoom / intrinsic_matrix.v[0]; diff --git a/selfdrive/ui/paint.h b/selfdrive/ui/paint.h index b955a61630..55fe9c1d08 100644 --- a/selfdrive/ui/paint.h +++ b/selfdrive/ui/paint.h @@ -8,3 +8,4 @@ void ui_draw_rect(NVGcontext *vg, const Rect &r, NVGcolor color, int width, floa void ui_fill_rect(NVGcontext *vg, const Rect &r, const NVGpaint &paint, float radius = 0); void ui_fill_rect(NVGcontext *vg, const Rect &r, const NVGcolor &color, float radius = 0); void ui_nvg_init(UIState *s); +void ui_resize(UIState *s, int width, int height); diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 18070e4e60..4b9f050da3 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -29,6 +29,7 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { onroad = new OnroadWindow(this); slayout->addWidget(onroad); + QObject::connect(this, &HomeWindow::update, onroad, &OnroadWindow::update); QObject::connect(this, &HomeWindow::offroadTransitionSignal, onroad, &OnroadWindow::offroadTransition); @@ -59,7 +60,16 @@ void HomeWindow::mousePressEvent(QMouseEvent* e) { // Handle sidebar collapsing if (onroad->isVisible() && (!sidebar->isVisible() || e->x() > sidebar->width())) { - sidebar->setVisible(!sidebar->isVisible()); + // Hide map first if visible, then hide sidebar + if (onroad->map != nullptr && onroad->map->isVisible()){ + onroad->map->setVisible(false); + } else if (!sidebar->isVisible()) { + sidebar->setVisible(true); + } else { + sidebar->setVisible(false); + + if (onroad->map != nullptr) onroad->map->setVisible(true); + } } } diff --git a/selfdrive/ui/qt/maps/map.cc b/selfdrive/ui/qt/maps/map.cc new file mode 100644 index 0000000000..9620a18de1 --- /dev/null +++ b/selfdrive/ui/qt/maps/map.cc @@ -0,0 +1,489 @@ +#include + +#include +#include +#include + +#include "selfdrive/common/util.h" +#include "selfdrive/common/swaglog.h" +#include "selfdrive/common/params.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/maps/map_helpers.h" +#include "selfdrive/ui/qt/maps/map.h" + + +const int PAN_TIMEOUT = 100; +const bool DRAW_MODEL_PATH = false; +const qreal REROUTE_DISTANCE = 25; +const float MAX_ZOOM = 17; +const float MIN_ZOOM = 14; +const float MAX_PITCH = 50; +const float MIN_PITCH = 0; +const float MAP_SCALE = 2; + + +MapWindow::MapWindow(const QMapboxGLSettings &settings) : m_settings(settings) { + if (DRAW_MODEL_PATH){ + sm = new SubMaster({"liveLocationKalman", "modelV2"}); + } else { + sm = new SubMaster({"liveLocationKalman"}); + } + + timer = new QTimer(this); + QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate())); + + // Instructions + map_instructions = new MapInstructions(this); + connect(this, SIGNAL(instructionsChanged(QMap)), + map_instructions, SLOT(updateInstructions(QMap))); + connect(this, SIGNAL(distanceChanged(float)), + map_instructions, SLOT(updateDistance(float))); + map_instructions->setFixedWidth(width()); + + // Routing + QVariantMap parameters; + parameters["mapbox.access_token"] = m_settings.accessToken(); + + geoservice_provider = new QGeoServiceProvider("mapbox", parameters); + routing_manager = geoservice_provider->routingManager(); + if (routing_manager == nullptr){ + qDebug() << geoservice_provider->errorString(); + assert(routing_manager); + } + connect(routing_manager, SIGNAL(finished(QGeoRouteReply*)), this, SLOT(routeCalculated(QGeoRouteReply*))); + + grabGesture(Qt::GestureType::PinchGesture); +} + +MapWindow::~MapWindow() { + makeCurrent(); +} + +void MapWindow::initLayers() { + // This doesn't work from initializeGL + if (!m_map->layerExists("modelPathLayer")){ + QVariantMap modelPath; + modelPath["id"] = "modelPathLayer"; + modelPath["type"] = "line"; + modelPath["source"] = "modelPathSource"; + m_map->addLayer(modelPath); + m_map->setPaintProperty("modelPathLayer", "line-color", QColor("red")); + m_map->setPaintProperty("modelPathLayer", "line-width", 5.0); + m_map->setLayoutProperty("modelPathLayer", "line-cap", "round"); + } + if (!m_map->layerExists("navLayer")){ + QVariantMap nav; + nav["id"] = "navLayer"; + nav["type"] = "line"; + nav["source"] = "navSource"; + m_map->addLayer(nav, "road-intersection"); + m_map->setPaintProperty("navLayer", "line-color", QColor("#8cb3d1")); + m_map->setPaintProperty("navLayer", "line-width", 7.5); + m_map->setLayoutProperty("navLayer", "line-cap", "round"); + } + if (!m_map->layerExists("carPosLayer")){ + m_map->addImage("label-arrow", QImage("../assets/images/triangle.svg")); + + QVariantMap carPos; + carPos["id"] = "carPosLayer"; + carPos["type"] = "symbol"; + carPos["source"] = "carPosSource"; + m_map->addLayer(carPos); + m_map->setLayoutProperty("carPosLayer", "icon-pitch-alignment", "map"); + m_map->setLayoutProperty("carPosLayer", "icon-image", "label-arrow"); + m_map->setLayoutProperty("carPosLayer", "icon-size", 0.5); + m_map->setLayoutProperty("carPosLayer", "icon-ignore-placement", true); + m_map->setLayoutProperty("carPosLayer", "icon-allow-overlap", true); + m_map->setLayoutProperty("carPosLayer", "symbol-sort-key", 0); + } +} + +void MapWindow::timerUpdate() { + if (!isVisible()) return; + + initLayers(); + + sm->update(0); + if (sm->updated("liveLocationKalman")) { + auto location = (*sm)["liveLocationKalman"].getLiveLocationKalman(); + auto pos = location.getPositionGeodetic(); + auto orientation = location.getOrientationNED(); + + float velocity = location.getVelocityCalibrated().getValue()[0]; + static FirstOrderFilter velocity_filter(velocity, 10, 0.1); + + auto coordinate = QMapbox::Coordinate(pos.getValue()[0], pos.getValue()[1]); + + if (location.getStatus() == cereal::LiveLocationKalman::Status::VALID){ + last_position = coordinate; + gps_ok = location.getGpsOK(); + + if (sm->frame % 10 == 0 && shouldRecompute()){ + calculateRoute(nav_destination); + } + + if (segment.isValid()) { + auto cur_maneuver = segment.maneuver(); + auto attrs = cur_maneuver.extendedAttributes(); + if (cur_maneuver.isValid() && attrs.contains("mapbox.banner_instructions")){ + + auto banner = attrs["mapbox.banner_instructions"].toList(); + if (banner.size()){ + // TOOD: Only show when traveled distanceAlongGeometry since the start + map_instructions->setVisible(true); + emit instructionsChanged(banner[0].toMap()); + } + + } + + auto next_segment = segment.nextRouteSegment(); + if (next_segment.isValid()){ + auto next_maneuver = next_segment.maneuver(); + if (next_maneuver.isValid()){ + float next_maneuver_distance = next_maneuver.position().distanceTo(to_QGeoCoordinate(last_position)); + emit distanceChanged(next_maneuver_distance); + m_map->setPitch(MAX_PITCH); // TODO: smooth pitching based on maneuver distance + + if (next_maneuver_distance < REROUTE_DISTANCE && next_maneuver_distance > last_maneuver_distance){ + segment = next_segment; + } + last_maneuver_distance = next_maneuver_distance; + } + } + } + + if (pan_counter == 0){ + m_map->setCoordinate(coordinate); + m_map->setBearing(RAD2DEG(orientation.getValue()[2])); + } else { + pan_counter--; + } + + if (zoom_counter == 0){ + m_map->setZoom(util::map_val(velocity_filter.update(velocity), 0, 30, MAX_ZOOM, MIN_ZOOM)); + } else { + zoom_counter--; + } + + // Update current location marker + auto point = coordinate_to_collection(coordinate); + QMapbox::Feature feature1(QMapbox::Feature::PointType, point, {}, {}); + QVariantMap carPosSource; + carPosSource["type"] = "geojson"; + carPosSource["data"] = QVariant::fromValue(feature1); + m_map->updateSource("carPosSource", carPosSource); + + // Update model path + if (DRAW_MODEL_PATH) { + auto model = (*sm)["modelV2"].getModelV2(); + auto path_points = model_to_collection(location.getCalibratedOrientationECEF(), location.getPositionECEF(), model.getPosition()); + QMapbox::Feature feature2(QMapbox::Feature::LineStringType, path_points, {}, {}); + QVariantMap modelPathSource; + modelPathSource["type"] = "geojson"; + modelPathSource["data"] = QVariant::fromValue(feature2); + m_map->updateSource("modelPathSource", modelPathSource); + } + } + update(); + } + if (!segment.isValid()){ + map_instructions->setVisible(false); + } + +} + +void MapWindow::resizeGL(int w, int h) { + map_instructions->setFixedWidth(width()); +} + +void MapWindow::initializeGL() { + m_map.reset(new QMapboxGL(nullptr, m_settings, size(), 1)); + + // TODO: Get from last gps position param + m_map->setCoordinateZoom(last_position, MAX_ZOOM); + m_map->setMargins({0, 350, 0, 0}); + m_map->setPitch(MIN_PITCH); + m_map->setStyleUrl("mapbox://styles/pd0wm/cknuhcgvr0vs817o1akcx6pek"); // Larger fonts + + connect(m_map.data(), SIGNAL(needsRendering()), this, SLOT(update())); + timer->start(100); +} + +void MapWindow::paintGL() { + m_map->resize(size() / MAP_SCALE); + m_map->setFramebufferObject(defaultFramebufferObject(), size()); + m_map->render(); +} + + +void MapWindow::calculateRoute(QMapbox::Coordinate destination) { + QGeoRouteRequest request(to_QGeoCoordinate(last_position), to_QGeoCoordinate(destination)); + routing_manager->calculateRoute(request); +} + +void MapWindow::routeCalculated(QGeoRouteReply *reply) { + LOGW("new route calculated"); + if (reply->routes().size() != 0) { + route = reply->routes().at(0); + segment = route.firstRouteSegment(); + + auto route_points = coordinate_list_to_collection(route.path()); + QMapbox::Feature feature(QMapbox::Feature::LineStringType, route_points, {}, {}); + QVariantMap navSource; + navSource["type"] = "geojson"; + navSource["data"] = QVariant::fromValue(feature); + m_map->updateSource("navSource", navSource); + has_route = true; + } + + reply->deleteLater(); +} + + +bool MapWindow::shouldRecompute(){ + if (!gps_ok) return false; // Don't recompute when gps drifts in tunnels + + QString nav_destination_json = QString::fromStdString(Params().get("NavDestination")); + if (nav_destination_json.isEmpty()) return false; + + QJsonDocument doc = QJsonDocument::fromJson(nav_destination_json.toUtf8()); + if (doc.isNull()) return false; + + QJsonObject json = doc.object(); + if (json["latitude"].isDouble() && json["longitude"].isDouble()){ + QMapbox::Coordinate new_destination(json["latitude"].toDouble(), json["longitude"].toDouble()); + if (new_destination != nav_destination){ + nav_destination = new_destination; + return true; + } + } + + if (!segment.isValid()){ + return true; + } + + // Compute closest distance to all line segments in the current path + float min_d = REROUTE_DISTANCE + 1; + auto path = segment.path(); + auto cur = to_QGeoCoordinate(last_position); + for (size_t i = 0; i < path.size() - 1; i++){ + auto a = path[i]; + auto b = path[i+1]; + min_d = std::min(min_d, minimum_distance(a, b, cur)); + } + return min_d > REROUTE_DISTANCE; + + // TODO: Check for going wrong way in segment +} + +void MapWindow::mousePressEvent(QMouseEvent *ev) { + m_lastPos = ev->localPos(); + ev->accept(); +} + +void MapWindow::mouseMoveEvent(QMouseEvent *ev){ + QPointF delta = ev->localPos() - m_lastPos; + + if (!delta.isNull()) { + pan_counter = PAN_TIMEOUT; + m_map->moveBy(delta); + } + + m_lastPos = ev->localPos(); + ev->accept(); +} + +void MapWindow::wheelEvent(QWheelEvent *ev) { + if (ev->orientation() == Qt::Horizontal) { + return; + } + + float factor = ev->delta() / 1200.; + if (ev->delta() < 0) { + factor = factor > -1 ? factor : 1 / factor; + } + + m_map->scaleBy(1 + factor, ev->pos() / MAP_SCALE); + zoom_counter = PAN_TIMEOUT; + ev->accept(); +} + +bool MapWindow::event(QEvent *event) { + if (event->type() == QEvent::Gesture){ + return gestureEvent(static_cast(event)); + } + + return QWidget::event(event); +} + +bool MapWindow::gestureEvent(QGestureEvent *event) { + if (QGesture *pinch = event->gesture(Qt::PinchGesture)){ + pinchTriggered(static_cast(pinch)); + } + return true; +} + +void MapWindow::pinchTriggered(QPinchGesture *gesture) { + QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags(); + if (changeFlags & QPinchGesture::ScaleFactorChanged) { + // TODO: figure out why gesture centerPoint doesn't work + m_map->scaleBy(gesture->scaleFactor(), {width() / 2.0 / MAP_SCALE, height() / 2.0 / MAP_SCALE}); + zoom_counter = PAN_TIMEOUT; + } +} + +MapInstructions::MapInstructions(QWidget * parent) : QWidget(parent){ + QHBoxLayout *layout_outer = new QHBoxLayout; + layout_outer->setContentsMargins(11, 50, 11, 11); + { + QVBoxLayout *layout = new QVBoxLayout; + icon_01 = new QLabel; + layout->addWidget(icon_01); + layout->addStretch(); + layout_outer->addLayout(layout); + } + + { + QVBoxLayout *layout = new QVBoxLayout; + + distance = new QLabel; + distance->setStyleSheet(R"(font-size: 75px; )"); + layout->addWidget(distance); + + primary = new QLabel; + primary->setStyleSheet(R"(font-size: 50px;)"); + primary->setWordWrap(true); + layout->addWidget(primary); + + secondary = new QLabel; + secondary->setStyleSheet(R"(font-size: 40px;)"); + secondary->setWordWrap(true); + layout->addWidget(secondary); + + lane_layout = new QHBoxLayout; + layout->addLayout(lane_layout); + + QWidget * w = new QWidget; + w->setLayout(layout); + layout_outer->addWidget(w); + } + + setLayout(layout_outer); + setStyleSheet(R"( + * { + color: white; + font-family: "Inter"; + } + )"); + + QPalette pal = palette(); + pal.setColor(QPalette::Background, QColor(0, 0, 0, 150)); + setAutoFillBackground(true); + setPalette(pal); +} + +void MapInstructions::updateDistance(float d){ + QString distance_str; + + float miles = d * METER_2_MILE; + float feet = d * METER_2_FOOT; + + if (feet > 500){ + distance_str.setNum(miles, 'f', 1); + distance_str += " miles"; + } else { + distance_str.setNum(50 * int(feet / 50)); + distance_str += " feet"; + } + distance->setText(distance_str); +} + +void MapInstructions::updateInstructions(QMap banner){ + // Need multiple calls to adjustSize for it to properly resize + // seems like it takes a little bit of time for the images to change and + // the size can only be changed afterwards + adjustSize(); + + if (banner == last_banner) return; + QString primary_str, secondary_str; + + auto p = banner["primary"].toMap(); + primary_str += p["text"].toString(); + + // Show arrow with direction + if (p.contains("type")){ + QString fn = "../assets/navigation/direction_" + p["type"].toString(); + if (p.contains("modifier")){ + fn += "_" + p["modifier"].toString(); + } + fn += + ".png"; + fn = fn.replace(' ', '_'); + + QPixmap pix(fn); + icon_01->setPixmap(pix.scaledToWidth(200, Qt::SmoothTransformation)); + icon_01->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + } + + // Parse components (e.g. lanes, exit number) + auto components = p["components"].toList(); + QString icon_fn; + for (auto &c : components) { + auto cc = c.toMap(); + if (cc["type"].toString() == "icon"){ + icon_fn = cc["imageBaseURL"].toString() + "@3x.png"; + } + } + + if (banner.contains("secondary")){ + auto s = banner["secondary"].toMap(); + secondary_str += s["text"].toString(); + } + + clearLayout(lane_layout); + bool has_lanes = false; + + if (banner.contains("sub")){ + auto s = banner["sub"].toMap(); + auto components = s["components"].toList(); + for (auto &c : components) { + auto cc = c.toMap(); + if (cc["type"].toString() == "lane"){ + has_lanes = true; + + bool left = false; + bool straight = false; + bool right = false; + bool active = cc["active"].toBool(); + + for (auto &dir : cc["directions"].toList()){ + auto d = dir.toString(); + left |= d.contains("left"); + straight |= d.contains("straight"); + right |= d.contains("right"); + } + + // TODO: Make more images based on active direction and combined directions + QString fn = "../assets/navigation/direction_"; + if (left) { + fn += "turn_left"; + } else if (right){ + fn += "turn_right"; + } else if (straight) { + fn += "turn_straight"; + } + + QPixmap pix(fn + ".png"); + auto icon = new QLabel; + icon->setPixmap(pix.scaledToWidth(active ? 125 : 75, Qt::SmoothTransformation)); + icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + lane_layout->addWidget(icon); + } + } + } + + primary->setText(primary_str); + secondary->setVisible(secondary_str.length() > 0); + secondary->setText(secondary_str); + adjustSize(); + last_banner = banner; +} diff --git a/selfdrive/ui/qt/maps/map.h b/selfdrive/ui/qt/maps/map.h new file mode 100644 index 0000000000..e282859c36 --- /dev/null +++ b/selfdrive/ui/qt/maps/map.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cereal/messaging/messaging.h" + +class MapWindow : public QOpenGLWidget { + Q_OBJECT + +public: + MapWindow(const QMapboxGLSettings &); + ~MapWindow(); + +private: + void initializeGL() final; + void paintGL() final; + void resizeGL(int w, int h) override; + + QMapboxGLSettings m_settings; + QScopedPointer m_map; + + void initLayers(); + + void mousePressEvent(QMouseEvent *ev) final; + void mouseMoveEvent(QMouseEvent *ev) final; + void wheelEvent(QWheelEvent *ev) final; + bool event(QEvent *event) final; + bool gestureEvent(QGestureEvent *event); + void pinchTriggered(QPinchGesture *gesture); + + bool m_sourceAdded = false; + SubMaster *sm; + QTimer* timer; + + // Panning + QPointF m_lastPos; + int pan_counter = 0; + int zoom_counter = 0; + + // Route + bool gps_ok = false; + bool has_route = false; + QGeoServiceProvider *geoservice_provider; + QGeoRoutingManager *routing_manager; + QGeoRoute route; + QGeoRouteSegment segment; + QWidget* map_instructions; + QMapbox::Coordinate last_position = QMapbox::Coordinate(37.7393118509158, -122.46471285025565); + QMapbox::Coordinate nav_destination; + double last_maneuver_distance = 1000; + void calculateRoute(QMapbox::Coordinate destination); + bool shouldRecompute(); + +private slots: + void timerUpdate(); + void routeCalculated(QGeoRouteReply *reply); + +signals: + void distanceChanged(float distance); + void instructionsChanged(QMap banner); +}; + +class MapInstructions : public QWidget { + Q_OBJECT + +private: + QLabel *distance; + QLabel *primary; + QLabel *secondary; + QLabel *icon_01; + QHBoxLayout *lane_layout; + QMap last_banner; + +public: + MapInstructions(QWidget * parent=nullptr); + +public slots: + void updateDistance(float d); + void updateInstructions(QMap banner); +}; diff --git a/selfdrive/ui/qt/maps/map_helpers.cc b/selfdrive/ui/qt/maps/map_helpers.cc new file mode 100644 index 0000000000..d5c0e405d4 --- /dev/null +++ b/selfdrive/ui/qt/maps/map_helpers.cc @@ -0,0 +1,86 @@ +#include "selfdrive/ui/qt/maps/map_helpers.h" + + +QGeoCoordinate to_QGeoCoordinate(const QMapbox::Coordinate &in) { + return QGeoCoordinate(in.first, in.second); +} + +QMapbox::CoordinatesCollections model_to_collection( + const cereal::LiveLocationKalman::Measurement::Reader &calibratedOrientationECEF, + const cereal::LiveLocationKalman::Measurement::Reader &positionECEF, + const cereal::ModelDataV2::XYZTData::Reader &line){ + + Eigen::Vector3d ecef(positionECEF.getValue()[0], positionECEF.getValue()[1], positionECEF.getValue()[2]); + Eigen::Vector3d orient(calibratedOrientationECEF.getValue()[0], calibratedOrientationECEF.getValue()[1], calibratedOrientationECEF.getValue()[2]); + Eigen::Matrix3d ecef_from_local = euler2rot(orient).transpose(); + + QMapbox::Coordinates coordinates; + auto x = line.getX(); + auto y = line.getY(); + auto z = line.getZ(); + for (int i = 0; i < x.size(); i++){ + Eigen::Vector3d point_ecef = ecef_from_local * Eigen::Vector3d(x[i], y[i], z[i]) + ecef; + Geodetic point_geodetic = ecef2geodetic((ECEF){.x = point_ecef[0], .y = point_ecef[1], .z = point_ecef[2]}); + QMapbox::Coordinate coordinate(point_geodetic.lat, point_geodetic.lon); + coordinates.push_back(coordinate); + } + + QMapbox::CoordinatesCollection collection; + collection.push_back(coordinates); + + QMapbox::CoordinatesCollections collections; + collections.push_back(collection); + return collections; +} + +QMapbox::CoordinatesCollections coordinate_to_collection(QMapbox::Coordinate c){ + QMapbox::Coordinates coordinates; + coordinates.push_back(c); + + QMapbox::CoordinatesCollection collection; + collection.push_back(coordinates); + + QMapbox::CoordinatesCollections collections; + collections.push_back(collection); + return collections; +} + +QMapbox::CoordinatesCollections coordinate_list_to_collection(QList coordinate_list) { + QMapbox::Coordinates coordinates; + + for (auto &c : coordinate_list){ + QMapbox::Coordinate coordinate(c.latitude(), c.longitude()); + coordinates.push_back(coordinate); + } + + QMapbox::CoordinatesCollection collection; + collection.push_back(coordinates); + + QMapbox::CoordinatesCollections collections; + collections.push_back(collection); + return collections; +} + +static QGeoCoordinate sub(QGeoCoordinate v, QGeoCoordinate w){ + return QGeoCoordinate(v.latitude() - w.latitude(), v.longitude() - w.longitude()); +} + +static QGeoCoordinate add(QGeoCoordinate v, QGeoCoordinate w){ + return QGeoCoordinate(v.latitude() + w.latitude(), v.longitude() + w.longitude()); +} + +static QGeoCoordinate mul(QGeoCoordinate v, float c){ + return QGeoCoordinate(c * v.latitude(), c * v.longitude()); +} + +static float dot(QGeoCoordinate v, QGeoCoordinate w){ + return v.latitude() * w.latitude() + v.longitude() * w.longitude(); +} + +float minimum_distance(QGeoCoordinate a, QGeoCoordinate b, QGeoCoordinate p) { + const QGeoCoordinate ap = sub(p, a); + const QGeoCoordinate ab = sub(b, a); + const float t = std::clamp(dot(ap, ab) / dot(ab, ab), 0.0f, 1.0f); + const QGeoCoordinate projection = add(a, mul(ab, t)); + return projection.distanceTo(p); +} diff --git a/selfdrive/ui/qt/maps/map_helpers.h b/selfdrive/ui/qt/maps/map_helpers.h new file mode 100644 index 0000000000..acf42d8b6c --- /dev/null +++ b/selfdrive/ui/qt/maps/map_helpers.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#include "common/transformations/coordinates.hpp" +#include "common/transformations/orientation.hpp" +#include "cereal/messaging/messaging.h" + +const float METER_2_MILE = 0.000621371; +const float METER_2_FOOT = 3.28084; +#define RAD2DEG(x) ((x) * 180.0 / M_PI) + +QGeoCoordinate to_QGeoCoordinate(const QMapbox::Coordinate &in); +QMapbox::CoordinatesCollections model_to_collection( + const cereal::LiveLocationKalman::Measurement::Reader &calibratedOrientationECEF, + const cereal::LiveLocationKalman::Measurement::Reader &positionECEF, + const cereal::ModelDataV2::XYZTData::Reader &line); +QMapbox::CoordinatesCollections coordinate_to_collection(QMapbox::Coordinate c); +QMapbox::CoordinatesCollections coordinate_list_to_collection(QList coordinate_list); + +float minimum_distance(QGeoCoordinate a, QGeoCoordinate b, QGeoCoordinate p); diff --git a/selfdrive/ui/qt/offroad/networking.cc b/selfdrive/ui/qt/offroad/networking.cc index dd3cd5ba53..901315ac52 100644 --- a/selfdrive/ui/qt/offroad/networking.cc +++ b/selfdrive/ui/qt/offroad/networking.cc @@ -6,18 +6,7 @@ #include #include "selfdrive/ui/qt/widgets/scrollview.h" - -void clearLayout(QLayout* layout) { - while (QLayoutItem* item = layout->takeAt(0)) { - if (QWidget* widget = item->widget()) { - widget->deleteLater(); - } - if (QLayout* childLayout = item->layout()) { - clearLayout(childLayout); - } - delete item; - } -} +#include "selfdrive/ui/qt/util.h" // Networking functions diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 7458780edc..ecbe57926b 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -7,15 +7,39 @@ #include "selfdrive/ui/paint.h" #include "selfdrive/ui/qt/util.h" +#ifdef ENABLE_MAPS +#include "selfdrive/ui/qt/maps/map.h" +#endif + OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) { - layout = new QStackedLayout(); + layout = new QStackedLayout(this); layout->setStackingMode(QStackedLayout::StackAll); // old UI on bottom nvg = new NvgWindow(this); - layout->addWidget(nvg); QObject::connect(this, &OnroadWindow::update, nvg, &NvgWindow::update); + QHBoxLayout* split = new QHBoxLayout(); + split->setContentsMargins(0, 0, 0, 0); + split->setSpacing(0); + split->addWidget(nvg); + +#ifdef ENABLE_MAPS + QString token = QString::fromStdString(Params().get("MapboxToken")); + if (!token.isEmpty()){ + QMapboxGLSettings settings; + settings.setCacheDatabasePath("/tmp/mbgl-cache.db"); + settings.setCacheDatabaseMaximumSize(20 * 1024 * 1024); + settings.setAccessToken(token); + map = new MapWindow(settings); + split->addWidget(map); + } +#endif + + QWidget * split_wrapper = new QWidget; + split_wrapper->setLayout(split); + layout->addWidget(split_wrapper); + alerts = new OnroadAlerts(this); QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::updateState); QObject::connect(this, &OnroadWindow::offroadTransition, alerts, &OnroadAlerts::offroadTransition); @@ -193,6 +217,10 @@ void NvgWindow::update(const UIState &s) { repaint(); } +void NvgWindow::resizeGL(int w, int h) { + ui_resize(&QUIState::ui_state, w, h); +} + void NvgWindow::paintGL() { ui_draw(&QUIState::ui_state, width(), height()); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 9e93164e5a..776030a61a 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -66,6 +66,7 @@ public: protected: void paintGL() override; void initializeGL() override; + void resizeGL(int w, int h) override; private: double prev_draw_t = 0; @@ -80,6 +81,7 @@ class OnroadWindow : public QWidget { public: OnroadWindow(QWidget* parent = 0); + QWidget *map = nullptr; private: OnroadAlerts *alerts; diff --git a/selfdrive/ui/qt/util.h b/selfdrive/ui/qt/util.h index 0ba42d3d85..f6eca88abd 100644 --- a/selfdrive/ui/qt/util.h +++ b/selfdrive/ui/qt/util.h @@ -8,3 +8,15 @@ inline void configFont(QPainter &p, QString family, int size, const QString &sty f.setStyleName(style); p.setFont(f); } + +inline void clearLayout(QLayout* layout) { + while (QLayoutItem* item = layout->takeAt(0)) { + if (QWidget* widget = item->widget()) { + widget->deleteLater(); + } + if (QLayout* childLayout = item->layout()) { + clearLayout(childLayout); + } + delete item; + } +} diff --git a/selfdrive/ui/ui b/selfdrive/ui/ui index e1c1748e30..0645287490 100755 --- a/selfdrive/ui/ui +++ b/selfdrive/ui/ui @@ -1,3 +1,4 @@ #!/bin/sh export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH" +export QT_PLUGIN_PATH="../../phonelibs/qt-plugins/$(uname -m)" exec ./_ui diff --git a/tools/ubuntu_setup.sh b/tools/ubuntu_setup.sh index 1ac31bcc3a..16893f6a20 100755 --- a/tools/ubuntu_setup.sh +++ b/tools/ubuntu_setup.sh @@ -45,12 +45,15 @@ sudo apt-get update && sudo apt-get install -y --no-install-recommends \ qt5-default \ qtmultimedia5-dev \ qtwebengine5-dev \ + qtlocation5-dev \ + qtpositioning5-dev \ + libqt5sql5-sqlite \ + libqt5svg5-dev \ screen \ sudo \ vim \ wget \ gcc-arm-none-eabi \ - libqt5svg5-dev \ libqt5x11extras5-dev \ libreadline-dev