Commit b36d59c0 authored by Andreas Bircher's avatar Andreas Bircher

updating the geotagging implementation

parent a82877ee
...@@ -508,7 +508,7 @@ SOURCES += \ ...@@ -508,7 +508,7 @@ SOURCES += \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \
src/PositionManager/SimulatedPosition.cc \ src/PositionManager/SimulatedPosition.cc \
src/PositionManager/PositionManager.cpp \ src/PositionManager/PositionManager.cpp \
src/AnalyzeView/ExifParser.cpp src/AnalyzeView/ExifParser.cc
DebugBuild { DebugBuild {
SOURCES += \ SOURCES += \
......
#include "ExifParser.h" #include "ExifParser.h"
#include <math.h>
#include <QtEndian> #include <QtEndian>
#include <QDateTime> #include <QDateTime>
...@@ -14,8 +15,8 @@ ExifParser::~ExifParser() ...@@ -14,8 +15,8 @@ ExifParser::~ExifParser()
double ExifParser::readTime(QByteArray& buf) double ExifParser::readTime(QByteArray& buf)
{ {
char tiffHeader[] = {0x49,0x49,0x2A,0x00}; char tiffHeader[] = {static_cast<char>(0x49),static_cast<char>(0x49),static_cast<char>(0x2A),static_cast<char>(0x00)};
char createDateHeader[] = {0x04,0x90,0x02,0x00}; char createDateHeader[] = {static_cast<char>(0x04),static_cast<char>(0x90),static_cast<char>(0x02),static_cast<char>(0x00)};
// find header position // find header position
uint32_t tiffHeaderIndex = buf.indexOf(tiffHeader); uint32_t tiffHeaderIndex = buf.indexOf(tiffHeader);
...@@ -57,7 +58,9 @@ double ExifParser::readTime(QByteArray& buf) ...@@ -57,7 +58,9 @@ double ExifParser::readTime(QByteArray& buf)
bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate) bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate)
{ {
char app1Header[2] = {0xff, 0xe1}; QByteArray app1Header;
app1Header.append(0xff);
app1Header.append(0xe1);
uint32_t app1HeaderInd = buf.indexOf(app1Header); uint32_t app1HeaderInd = buf.indexOf(app1Header);
uint16_t *conversionPointer = reinterpret_cast<uint16_t *>(buf.mid(app1HeaderInd + 2, 2).data()); uint16_t *conversionPointer = reinterpret_cast<uint16_t *>(buf.mid(app1HeaderInd + 2, 2).data());
uint16_t app1Size = *conversionPointer; uint16_t app1Size = *conversionPointer;
...@@ -122,7 +125,7 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate) ...@@ -122,7 +125,7 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate)
gpsIFDInd.i = nextIfdOffset; gpsIFDInd.i = nextIfdOffset;
// this will stay constant // this will stay constant
char gpsInfo[12] = {0x25, 0x88, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, gpsIFDInd.c[0], gpsIFDInd.c[1], gpsIFDInd.c[2], gpsIFDInd.c[3]}; char gpsInfo[12] = {static_cast<char>(0x25), static_cast<char>(0x88), static_cast<char>(0x04), static_cast<char>(0x00), static_cast<char>(0x01), static_cast<char>(0x00), static_cast<char>(0x00), static_cast<char>(0x00), static_cast<char>(gpsIFDInd.c[0]), static_cast<char>(gpsIFDInd.c[1]), static_cast<char>(gpsIFDInd.c[2]), static_cast<char>(gpsIFDInd.c[3])};
// filling values to gpsData // filling values to gpsData
uint32_t gpsDataExtInd = gpsIFDInd.i + 2 + sizeof(fields_s); uint32_t gpsDataExtInd = gpsIFDInd.i + 2 + sizeof(fields_s);
...@@ -173,14 +176,14 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate) ...@@ -173,14 +176,14 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate)
// Filling up the additional information that does not fit into the fields // Filling up the additional information that does not fit into the fields
gpsData.readable.extendedData.gpsLat[0] = abs(static_cast<int>(coordinate.latitude())); gpsData.readable.extendedData.gpsLat[0] = abs(static_cast<int>(coordinate.latitude()));
gpsData.readable.extendedData.gpsLat[1] = 1; gpsData.readable.extendedData.gpsLat[1] = 1;
gpsData.readable.extendedData.gpsLat[2] = static_cast<int>((fabs(coordinate.latitude()) - std::floor(fabs(coordinate.latitude()))) * 60000.0); gpsData.readable.extendedData.gpsLat[2] = static_cast<int>((fabs(coordinate.latitude()) - floor(fabs(coordinate.latitude()))) * 60000.0);
gpsData.readable.extendedData.gpsLat[3] = 1000; gpsData.readable.extendedData.gpsLat[3] = 1000;
gpsData.readable.extendedData.gpsLat[4] = 0; gpsData.readable.extendedData.gpsLat[4] = 0;
gpsData.readable.extendedData.gpsLat[5] = 1; gpsData.readable.extendedData.gpsLat[5] = 1;
gpsData.readable.extendedData.gpsLon[0] = abs(static_cast<int>(coordinate.longitude())); gpsData.readable.extendedData.gpsLon[0] = abs(static_cast<int>(coordinate.longitude()));
gpsData.readable.extendedData.gpsLon[1] = 1; gpsData.readable.extendedData.gpsLon[1] = 1;
gpsData.readable.extendedData.gpsLon[2] = static_cast<int>((fabs(coordinate.longitude()) - std::floor(fabs(coordinate.longitude()))) * 60000.0); gpsData.readable.extendedData.gpsLon[2] = static_cast<int>((fabs(coordinate.longitude()) - floor(fabs(coordinate.longitude()))) * 60000.0);
gpsData.readable.extendedData.gpsLon[3] = 1000; gpsData.readable.extendedData.gpsLon[3] = 1000;
gpsData.readable.extendedData.gpsLon[4] = 0; gpsData.readable.extendedData.gpsLon[4] = 0;
gpsData.readable.extendedData.gpsLon[5] = 1; gpsData.readable.extendedData.gpsLon[5] = 1;
......
This diff is collapsed.
...@@ -10,9 +10,13 @@ ...@@ -10,9 +10,13 @@
#ifndef GeoTagController_H #ifndef GeoTagController_H
#define GeoTagController_H #define GeoTagController_H
#include "QmlObjectListModel.h"
#include "Fact.h"
#include "FactMetaData.h"
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QThread> #include <QThread>
#include <QFileInfoList>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QDebug> #include <QDebug>
#include <QGeoCoordinate> #include <QGeoCoordinate>
...@@ -24,36 +28,38 @@ class GeoTagWorker : public QThread ...@@ -24,36 +28,38 @@ class GeoTagWorker : public QThread
public: public:
GeoTagWorker(void); GeoTagWorker(void);
QString logFile(void) const { return _logFile; } void setLogFile (const QString& logFile) { _logFile = logFile; }
QString imageDirectory(void) const { return _imageDirectory; } void setImageDirectory (const QString& imageDirectory) { _imageDirectory = imageDirectory; }
void setSaveDirectory (const QString& saveDirectory) { _saveDirectory = saveDirectory; }
void setLogFile(const QString& logFile) { _logFile = logFile; } QString logFile (void) const { return _logFile; }
void setImageDirectory(const QString& imageDirectory) { _imageDirectory = imageDirectory; } QString imageDirectory (void) const { return _imageDirectory; }
QString saveDirectory (void) const { return _saveDirectory; }
void cancelTagging(void) { _cancel = true; } void cancelTagging (void) { _cancel = true; }
protected: protected:
void run(void) final; void run(void) final;
signals: signals:
void error(QString errorMsg); void error (QString errorMsg);
void taggingComplete(void); void taggingComplete (void);
void progressChanged(double progress); void progressChanged (double progress);
private: private:
bool parsePX4Log(); bool parsePX4Log();
bool triggerFiltering(); bool triggerFiltering();
bool _cancel;
bool _cancel; QString _logFile;
QString _logFile; QString _imageDirectory;
QString _imageDirectory; QString _saveDirectory;
QList<QByteArray> _imageBuffers; QFileInfoList _imageList;
QList<double> _tagTime; QList<double> _tagTime;
QList<QGeoCoordinate> _geoRef; QList<QGeoCoordinate> _geoRef;
QList<double> _triggerTime; QList<double> _triggerTime;
QList<int> _imageIndices; QList<int> _imageIndices;
QList<int> _triggerIndices; QList<int> _triggerIndices;
}; };
/// Controller for GeoTagPage.qml. Supports geotagging images based on logfile camera tags. /// Controller for GeoTagPage.qml. Supports geotagging images based on logfile camera tags.
...@@ -67,6 +73,7 @@ public: ...@@ -67,6 +73,7 @@ public:
Q_PROPERTY(QString logFile READ logFile NOTIFY logFileChanged) Q_PROPERTY(QString logFile READ logFile NOTIFY logFileChanged)
Q_PROPERTY(QString imageDirectory READ imageDirectory NOTIFY imageDirectoryChanged) Q_PROPERTY(QString imageDirectory READ imageDirectory NOTIFY imageDirectoryChanged)
Q_PROPERTY(QString saveDirectory READ saveDirectory NOTIFY saveDirectoryChanged)
/// Set to an error message is geotagging fails /// Set to an error message is geotagging fails
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged) Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
...@@ -79,32 +86,35 @@ public: ...@@ -79,32 +86,35 @@ public:
Q_INVOKABLE void pickLogFile(void); Q_INVOKABLE void pickLogFile(void);
Q_INVOKABLE void pickImageDirectory(void); Q_INVOKABLE void pickImageDirectory(void);
Q_INVOKABLE void pickSaveDirectory(void);
Q_INVOKABLE void startTagging(void); Q_INVOKABLE void startTagging(void);
Q_INVOKABLE void cancelTagging(void) { _worker.cancelTagging(); } Q_INVOKABLE void cancelTagging(void) { _worker.cancelTagging(); }
QString logFile (void) const { return _worker.logFile(); } QString logFile (void) const { return _worker.logFile(); }
QString imageDirectory (void) const { return _worker.imageDirectory(); } QString imageDirectory (void) const { return _worker.imageDirectory(); }
double progress (void) const { return _progress; } QString saveDirectory (void) const { return _worker.saveDirectory(); }
bool inProgress (void) const { return _worker.isRunning(); } double progress (void) const { return _progress; }
QString errorMessage (void) const { return _errorMessage; } bool inProgress (void) const { return _worker.isRunning(); }
QString errorMessage (void) const { return _errorMessage; }
signals: signals:
void logFileChanged(QString logFile); void logFileChanged (QString logFile);
void imageDirectoryChanged(QString imageDirectory); void imageDirectoryChanged (QString imageDirectory);
void progressChanged(double progress); void saveDirectoryChanged (QString saveDirectory);
void inProgressChanged(void); void progressChanged (double progress);
void errorMessageChanged(QString errorMessage); void inProgressChanged (void);
void errorMessageChanged (QString errorMessage);
private slots: private slots:
void _workerProgressChanged(double progress); void _workerProgressChanged(double progress);
void _workerError(QString errorMsg); void _workerError(QString errorMsg);
private: private:
QString _errorMessage; QString _errorMessage;
double _progress; double _progress;
bool _inProgress; bool _inProgress;
GeoTagWorker _worker; GeoTagWorker _worker;
}; };
#endif #endif
...@@ -11,7 +11,10 @@ import QtQuick 2.5 ...@@ -11,7 +11,10 @@ import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Controllers 1.0 import QGroundControl.Controllers 1.0
...@@ -19,17 +22,17 @@ import QGroundControl.Controllers 1.0 ...@@ -19,17 +22,17 @@ import QGroundControl.Controllers 1.0
AnalyzePage { AnalyzePage {
id: geoTagPage id: geoTagPage
pageComponent: pageComponent pageComponent: pageComponent
pageName: qsTr("GeoTag Images (WIP)") pageName: qsTr("GeoTag Images")
pageDescription: qsTr("GetTag Images is used to tag a set of images from a survey mission with gps coordinates. You must provide the binary log from the flight as well as the directory which contains the images to tag.") pageDescription: qsTr("GeoTag Images is used to tag a set of images from a survey mission with gps coordinates. You must provide the binary log from the flight as well as the directory which contains the images to tag.")
property real _margin: ScreenTools.defaultFontPixelWidth property real _margin: ScreenTools.defaultFontPixelWidth * 2
GeoTagController { GeoTagController {
id: controller id: controller
} }
Component { Component {
id: pageComponent id: pageComponent
Column { Column {
id: mainColumn id: mainColumn
...@@ -37,67 +40,104 @@ AnalyzePage { ...@@ -37,67 +40,104 @@ AnalyzePage {
spacing: _margin spacing: _margin
Row { Row {
spacing: _margin spacing: ScreenTools.defaultFontPixelWidth * 2
QGCLabel { ProgressBar {
text: "Log file:" id: progressBar
width: qgcView.width -_margin * 5
maximumValue: 100
value: controller.progress
} }
QGCLabel { BusyIndicator {
text: controller.logFile running: controller.progress > 0 && controller.progress < 100 && controller.errorMessage === ""
width: progressBar.height
height: progressBar.height
} }
}
QGCLabel {
text: controller.errorMessage
font.bold: true
font.pointSize: ScreenTools.largeFontPointSize
color: "red"
}
// Horizontal spacer line
Rectangle {
height: 1
width: qgcView.width * 1.0
color: qgcPal.windowShadeDark
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
spacing: _margin
QGCButton { QGCButton {
text: qsTr("Select log file") text: qsTr("Select log file")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: controller.pickLogFile() onClicked: controller.pickLogFile()
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: controller.logFile
anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
spacing: _margin spacing: _margin
QGCLabel { QGCButton {
text: "Image directory:" text: qsTr("Select image directory")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: controller.pickImageDirectory()
anchors.verticalCenter: parent.verticalCenter
} }
QGCLabel { QGCLabel {
text: controller.imageDirectory text: controller.imageDirectory
anchors.verticalCenter: parent.verticalCenter
} }
}
Row {
spacing: _margin
QGCButton { QGCButton {
text: qsTr("Select image directory") text: qsTr("(Optionally) Select save directory")
onClicked: controller.pickImageDirectory() width: ScreenTools.defaultFontPixelWidth * 30
onClicked: controller.pickSaveDirectory()
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: controller.saveDirectory != "" ? controller.saveDirectory : "/TAGGED folder in your image folder"
anchors.verticalCenter: parent.verticalCenter
} }
} }
QGCLabel { text: "NYI - Simulated only" } // Horizontal spacer line
Rectangle {
height: 1
width: qgcView.width * 1.0
color: qgcPal.windowShadeDark
anchors.horizontalCenter: parent.horizontalCenter
}
QGCButton { QGCButton {
text: controller.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging") text: controller.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: { onClicked: {
if (controller.inProgress) { if (controller.inProgress) {
controller.cancelTagging() controller.cancelTagging()
} else { } else {
if (controller.logFile == "" || controller.imageDirectory == "") {
geoTagPage.showMessage(qsTr("Error"), qsTr("You must select a log file and image directory before you can start tagging."), StandardButton.Ok)
return
}
controller.startTagging() controller.startTagging()
} }
} }
} }
QGCLabel {
text: controller.errorMessage
}
ProgressBar {
anchors.left: parent.left
anchors.right: parent.right
maximumValue: 100
value: controller.progress
}
} // Column } // Column
} // Component } // Component
} // AnalyzePage } // AnalyzePage
...@@ -20,7 +20,8 @@ QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog") ...@@ -20,7 +20,8 @@ QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog")
QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog") QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog")
QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog") QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog")
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog") QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog") QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog")
QGC_LOGGING_CATEGORY(GeotaggingLog, "GeotaggingLog")
QGCLoggingCategoryRegister* _instance = NULL; QGCLoggingCategoryRegister* _instance = NULL;
const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters"; const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters";
......
...@@ -23,6 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog) ...@@ -23,6 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog)
Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog) Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog)
Q_DECLARE_LOGGING_CATEGORY(MissionItemLog) Q_DECLARE_LOGGING_CATEGORY(MissionItemLog)
Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog) Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog)
Q_DECLARE_LOGGING_CATEGORY(GeotaggingLog)
/// @def QGC_LOGGING_CATEGORY /// @def QGC_LOGGING_CATEGORY
/// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a /// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment