Commit b36d59c0 authored by Andreas Bircher's avatar Andreas Bircher

updating the geotagging implementation

parent a82877ee
......@@ -508,7 +508,7 @@ SOURCES += \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \
src/PositionManager/SimulatedPosition.cc \
src/PositionManager/PositionManager.cpp \
src/AnalyzeView/ExifParser.cpp
src/AnalyzeView/ExifParser.cc
DebugBuild {
SOURCES += \
......
#include "ExifParser.h"
#include <math.h>
#include <QtEndian>
#include <QDateTime>
......@@ -14,8 +15,8 @@ ExifParser::~ExifParser()
double ExifParser::readTime(QByteArray& buf)
{
char tiffHeader[] = {0x49,0x49,0x2A,0x00};
char createDateHeader[] = {0x04,0x90,0x02,0x00};
char tiffHeader[] = {static_cast<char>(0x49),static_cast<char>(0x49),static_cast<char>(0x2A),static_cast<char>(0x00)};
char createDateHeader[] = {static_cast<char>(0x04),static_cast<char>(0x90),static_cast<char>(0x02),static_cast<char>(0x00)};
// find header position
uint32_t tiffHeaderIndex = buf.indexOf(tiffHeader);
......@@ -57,7 +58,9 @@ double ExifParser::readTime(QByteArray& buf)
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);
uint16_t *conversionPointer = reinterpret_cast<uint16_t *>(buf.mid(app1HeaderInd + 2, 2).data());
uint16_t app1Size = *conversionPointer;
......@@ -122,7 +125,7 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate)
gpsIFDInd.i = nextIfdOffset;
// 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
uint32_t gpsDataExtInd = gpsIFDInd.i + 2 + sizeof(fields_s);
......@@ -173,14 +176,14 @@ bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate)
// 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[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[4] = 0;
gpsData.readable.extendedData.gpsLat[5] = 1;
gpsData.readable.extendedData.gpsLon[0] = abs(static_cast<int>(coordinate.longitude()));
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[4] = 0;
gpsData.readable.extendedData.gpsLon[5] = 1;
......
This diff is collapsed.
......@@ -10,9 +10,13 @@
#ifndef GeoTagController_H
#define GeoTagController_H
#include "QmlObjectListModel.h"
#include "Fact.h"
#include "FactMetaData.h"
#include <QObject>
#include <QString>
#include <QThread>
#include <QFileInfoList>
#include <QElapsedTimer>
#include <QDebug>
#include <QGeoCoordinate>
......@@ -24,36 +28,38 @@ class GeoTagWorker : public QThread
public:
GeoTagWorker(void);
QString logFile(void) const { return _logFile; }
QString imageDirectory(void) const { return _imageDirectory; }
void setLogFile (const QString& logFile) { _logFile = logFile; }
void setImageDirectory (const QString& imageDirectory) { _imageDirectory = imageDirectory; }
void setSaveDirectory (const QString& saveDirectory) { _saveDirectory = saveDirectory; }
void setLogFile(const QString& logFile) { _logFile = logFile; }
void setImageDirectory(const QString& imageDirectory) { _imageDirectory = imageDirectory; }
QString logFile (void) const { return _logFile; }
QString imageDirectory (void) const { return _imageDirectory; }
QString saveDirectory (void) const { return _saveDirectory; }
void cancelTagging(void) { _cancel = true; }
void cancelTagging (void) { _cancel = true; }
protected:
void run(void) final;
signals:
void error(QString errorMsg);
void taggingComplete(void);
void progressChanged(double progress);
void error (QString errorMsg);
void taggingComplete (void);
void progressChanged (double progress);
private:
bool parsePX4Log();
bool triggerFiltering();
bool _cancel;
QString _logFile;
QString _imageDirectory;
QList<QByteArray> _imageBuffers;
QList<double> _tagTime;
QList<QGeoCoordinate> _geoRef;
QList<double> _triggerTime;
QList<int> _imageIndices;
QList<int> _triggerIndices;
bool _cancel;
QString _logFile;
QString _imageDirectory;
QString _saveDirectory;
QFileInfoList _imageList;
QList<double> _tagTime;
QList<QGeoCoordinate> _geoRef;
QList<double> _triggerTime;
QList<int> _imageIndices;
QList<int> _triggerIndices;
};
/// Controller for GeoTagPage.qml. Supports geotagging images based on logfile camera tags.
......@@ -67,6 +73,7 @@ public:
Q_PROPERTY(QString logFile READ logFile NOTIFY logFileChanged)
Q_PROPERTY(QString imageDirectory READ imageDirectory NOTIFY imageDirectoryChanged)
Q_PROPERTY(QString saveDirectory READ saveDirectory NOTIFY saveDirectoryChanged)
/// Set to an error message is geotagging fails
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
......@@ -79,32 +86,35 @@ public:
Q_INVOKABLE void pickLogFile(void);
Q_INVOKABLE void pickImageDirectory(void);
Q_INVOKABLE void pickSaveDirectory(void);
Q_INVOKABLE void startTagging(void);
Q_INVOKABLE void cancelTagging(void) { _worker.cancelTagging(); }
QString logFile (void) const { return _worker.logFile(); }
QString imageDirectory (void) const { return _worker.imageDirectory(); }
double progress (void) const { return _progress; }
bool inProgress (void) const { return _worker.isRunning(); }
QString errorMessage (void) const { return _errorMessage; }
QString logFile (void) const { return _worker.logFile(); }
QString imageDirectory (void) const { return _worker.imageDirectory(); }
QString saveDirectory (void) const { return _worker.saveDirectory(); }
double progress (void) const { return _progress; }
bool inProgress (void) const { return _worker.isRunning(); }
QString errorMessage (void) const { return _errorMessage; }
signals:
void logFileChanged(QString logFile);
void imageDirectoryChanged(QString imageDirectory);
void progressChanged(double progress);
void inProgressChanged(void);
void errorMessageChanged(QString errorMessage);
void logFileChanged (QString logFile);
void imageDirectoryChanged (QString imageDirectory);
void saveDirectoryChanged (QString saveDirectory);
void progressChanged (double progress);
void inProgressChanged (void);
void errorMessageChanged (QString errorMessage);
private slots:
void _workerProgressChanged(double progress);
void _workerError(QString errorMsg);
private:
QString _errorMessage;
double _progress;
bool _inProgress;
QString _errorMessage;
double _progress;
bool _inProgress;
GeoTagWorker _worker;
GeoTagWorker _worker;
};
#endif
......@@ -11,7 +11,10 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controllers 1.0
......@@ -19,17 +22,17 @@ import QGroundControl.Controllers 1.0
AnalyzePage {
id: geoTagPage
pageComponent: pageComponent
pageName: qsTr("GeoTag Images (WIP)")
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.")
pageName: qsTr("GeoTag Images")
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 {
id: controller
}
Component {
id: pageComponent
id: pageComponent
Column {
id: mainColumn
......@@ -37,67 +40,104 @@ AnalyzePage {
spacing: _margin
Row {
spacing: _margin
spacing: ScreenTools.defaultFontPixelWidth * 2
QGCLabel {
text: "Log file:"
ProgressBar {
id: progressBar
width: qgcView.width -_margin * 5
maximumValue: 100
value: controller.progress
}
QGCLabel {
text: controller.logFile
BusyIndicator {
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 {
text: qsTr("Select log file")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: controller.pickLogFile()
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: controller.logFile
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
spacing: _margin
QGCLabel {
text: "Image directory:"
QGCButton {
text: qsTr("Select image directory")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: controller.pickImageDirectory()
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: controller.imageDirectory
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
spacing: _margin
QGCButton {
text: qsTr("Select image directory")
onClicked: controller.pickImageDirectory()
text: qsTr("(Optionally) Select save directory")
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 {
text: controller.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: {
if (controller.inProgress) {
controller.cancelTagging()
} 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()
}
}
}
QGCLabel {
text: controller.errorMessage
}
ProgressBar {
anchors.left: parent.left
anchors.right: parent.right
maximumValue: 100
value: controller.progress
}
} // Column
} // Component
} // AnalyzePage
......@@ -20,7 +20,8 @@ QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog")
QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog")
QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog")
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog")
QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog")
QGC_LOGGING_CATEGORY(GeotaggingLog, "GeotaggingLog")
QGCLoggingCategoryRegister* _instance = NULL;
const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters";
......
......@@ -23,6 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog)
Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog)
Q_DECLARE_LOGGING_CATEGORY(MissionItemLog)
Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog)
Q_DECLARE_LOGGING_CATEGORY(GeotaggingLog)
/// @def QGC_LOGGING_CATEGORY
/// 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