Commit a9bd26d9 authored by hengli's avatar hengli

Merge branch 'experimental' of pixhawk.ethz.ch:qgroundcontrol into experimental

parents 15852ad5 2c92489b
......@@ -126,8 +126,7 @@ Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
//mainWindow->addLink(simulationLink);
mainWindow = MainWindow::instance();
// Remove splash screen
// Remove splash screen
splashScreen->finish(mainWindow);
// Check if link could be connected
......
......@@ -58,19 +58,23 @@ void LogCompressor::run()
QStringList* keys = new QStringList();
QList<quint64> times;// = new QList<quint64>();
QList<quint64> finalTimes;
qDebug() << "LOG COMPRESSOR: Starting" << fileName;
if (!file.exists()) return;
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() << "LOG COMPRESSOR: INPUT FILE DOES NOT EXIST";
emit logProcessingStatusChanged(tr("Log Compressor: Cannot start/compress log file, since input file %1 is not readable").arg(QFileInfo(fileName).absoluteFilePath()));
return;
}
if (outFileName != "")
{
// Check if file is writeable
if (!QFileInfo(outfile).isWritable())
if (outFileName == ""/* || !QFileInfo(outfile).isWritable()*/)
{
qDebug() << "LOG COMPRESSOR: OUTPUT FILE DOES NOT EXIST" << outFileName;
emit logProcessingStatusChanged(tr("Log Compressor: Cannot start/compress log file, since output file %1 is not writable").arg(QFileInfo(outFileName).absoluteFilePath()));
return;
}
}
// Find all keys
QTextStream in(&file);
......@@ -132,7 +136,8 @@ void LogCompressor::run()
QStringList* outLines = new QStringList();
for (int i = 0; i < times.length(); i++)
{
if (times.at(i) != lastTime)
// Cast to signed on purpose, 64 bit timestamp still long enough
if (static_cast<qint64>(times.at(i)) != lastTime)
{
outLines->append(QString("%1").arg(times.at(i)) + separator + spacer);
lastTime = static_cast<qint64>(times.at(i));
......@@ -197,6 +202,7 @@ void LogCompressor::run()
if (offset == 0)
{
emit logProcessingStatusChanged(tr("Log compressor: Timestamp %1 not found in dataset, ignoring log line %2").arg(time).arg(linecounter));
qDebug() << "Completely failed finding value";
//continue;
failed = true;
}
......@@ -208,16 +214,19 @@ void LogCompressor::run()
}
}
if (index % (dataLines/10) == 0) emit logProcessingStatusChanged(tr("Log compressor: Processed %1%% of %2 lines").arg(index/(float)dataLines).arg(dataLines));
if (index % (dataLines/100) == 0) emit logProcessingStatusChanged(tr("Log compressor: Processed %1% of %2 lines").arg(index/(float)dataLines*100, 0, 'f', 2).arg(dataLines));
// When the algorithm reaches here the correct index was found
lastTimeIndex = index;
QString outLine = outLines->at(index);
QStringList outParts = outLine.split(separator);
// Replace measurement placeholder with current value
outParts.replace(keys->indexOf(field)+1, value);
outLine = outParts.join(separator);
outLines->replace(index, outLine);
if (!failed)
{
// When the algorithm reaches here the correct index was found
lastTimeIndex = index;
QString outLine = outLines->at(index);
QStringList outParts = outLine.split(separator);
// Replace measurement placeholder with current value
outParts.replace(keys->indexOf(field)+1, value);
outLine = outParts.join(separator);
outLines->replace(index, outLine);
}
}
......@@ -246,7 +255,7 @@ void LogCompressor::run()
dataLines = 1;
delete keys;
emit logProcessingStatusChanged(tr("Log compressor: Finished processing file: %1").arg(outfile.fileName()));
//qDebug() << "Done with logfile processing";
qDebug() << "Done with logfile processing";
emit finishedFile(outfile.fileName());
running = false;
}
......
......@@ -59,7 +59,9 @@ MAVLinkProtocol::MAVLinkProtocol() :
heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE),
m_heartbeatsEnabled(false),
m_loggingEnabled(false),
m_logfile(NULL)
m_logfile(NULL),
m_enable_version_check(true),
versionMismatchIgnore(false)
{
start(QThread::LowPriority);
// Start heartbeat timer, emitting a heartbeat at the configured rate
......@@ -76,6 +78,8 @@ MAVLinkProtocol::MAVLinkProtocol() :
lastIndex[i][j] = -1;
}
}
emit versionCheckChanged(m_enable_version_check);
}
MAVLinkProtocol::~MAVLinkProtocol()
......@@ -91,7 +95,6 @@ MAVLinkProtocol::~MAVLinkProtocol()
void MAVLinkProtocol::run()
{
}
QString MAVLinkProtocol::getLogfileName()
......@@ -146,7 +149,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
// Check if the UAS has the same id like this system
if (message.sysid == getSystemId())
{
qDebug() << "WARNING\nWARNING\nWARNING\nWARNING\nWARNING\nWARNING\nWARNING\n\n RECEIVED MESSAGE FROM THIS SYSTEM WITH ID" << message.msgid << "FROM COMPONENT" << message.compid;
emit protocolStatusMessage(tr("SYSTEM ID CONFLICT!"), tr("Warning: A second system is using the same system id (%1)").arg(getSystemId()));
}
// Create a new UAS based on the heartbeat received
......@@ -161,12 +164,15 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
mavlink_msg_heartbeat_decode(&message, &heartbeat);
// Check if the UAS has a different protocol version
if (heartbeat.mavlink_version != MAVLINK_VERSION)
if (m_enable_version_check && (heartbeat.mavlink_version != MAVLINK_VERSION))
{
// Bring up dialog to inform user
MainWindow::instance()->showCriticalMessage(tr("The MAVLink protocol version on the MAV and QGroundControl mismatch!"),
if (!versionMismatchIgnore)
{
emit protocolStatusMessage(tr("The MAVLink protocol version on the MAV and QGroundControl mismatch!"),
tr("It is unsafe to use different MAVLink versions. QGroundControl therefore refuses to connect to system %1, which sends MAVLink version %2 (QGroundControl uses version %3).").arg(message.sysid).arg(heartbeat.mavlink_version).arg(MAVLINK_VERSION));
versionMismatchIgnore = true;
}
// Ignore this message and continue gracefully
continue;
......@@ -397,6 +403,11 @@ void MAVLinkProtocol::enableLogging(bool enabled)
m_loggingEnabled = enabled;
}
void MAVLinkProtocol::enableVersionCheck(bool enabled)
{
m_enable_version_check = enabled;
}
bool MAVLinkProtocol::heartbeatsEnabled(void)
{
return m_heartbeatsEnabled;
......@@ -407,6 +418,11 @@ bool MAVLinkProtocol::loggingEnabled(void)
return m_loggingEnabled;
}
bool MAVLinkProtocol::versionCheckEnabled(void)
{
return m_enable_version_check;
}
/**
* The default rate is 1 Hertz.
*
......
......@@ -68,6 +68,8 @@ public:
bool heartbeatsEnabled(void);
/** @brief Get logging state */
bool loggingEnabled(void);
/** @brief Get protocol version check state */
bool versionCheckEnabled(void);
/** @brief Get the name of the packet log file */
static QString getLogfileName();
......@@ -87,6 +89,9 @@ public slots:
/** @brief Enable/disable binary packet logging */
void enableLogging(bool enabled);
/** @brief Enable / disable version check */
void enableVersionCheck(bool enabled);
/** @brief Send an extra heartbeat to all connected units */
void sendHeartbeat();
......@@ -96,12 +101,14 @@ protected:
bool m_heartbeatsEnabled; ///< Enabled/disable heartbeat emission
bool m_loggingEnabled; ///< Enable/disable packet logging
QFile* m_logfile; ///< Logfile
bool m_enable_version_check; ///< Enable checking of version match of MAV and QGC
QMutex receiveMutex; ///< Mutex to protect receiveBytes function
int lastIndex[256][256];
int totalReceiveCounter;
int totalLossCounter;
int currReceiveCounter;
int currLossCounter;
bool versionMismatchIgnore;
signals:
/** @brief Message received and directly copied via signal */
......@@ -110,6 +117,10 @@ signals:
void heartbeatChanged(bool heartbeats);
/** @brief Emitted if logging is started / stopped */
void loggingChanged(bool enabled);
/** @brief Emitted if version check is enabled / disabled */
void versionCheckChanged(bool enabled);
/** @brief Emitted if a message from the protocol should reach the user */
void protocolStatusMessage(const QString& title, const QString& message);
};
#endif // MAVLINKPROTOCOL_H_
......@@ -85,6 +85,8 @@ SerialLink::SerialLink(QString portname, BaudRateType baudrate, FlowType flow, P
#endif
loadSettings();
// Link is setup, register it with link manager
LinkManager::instance()->add(this);
}
......
......@@ -118,6 +118,21 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message)
emit valueChanged(uasId, "vis. z", pos.z, time);
}
break;
case MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE:
{
mavlink_vicon_position_estimate_t pos;
mavlink_msg_vicon_position_estimate_decode(&message, &pos);
quint64 time = getUnixTime(pos.usec);
//emit valueChanged(uasId, "vis. time", pos.usec, time);
emit valueChanged(uasId, "vicon roll", pos.roll, time);
emit valueChanged(uasId, "vicon pitch", pos.pitch, time);
emit valueChanged(uasId, "vicon yaw", pos.yaw, time);
emit valueChanged(uasId, "vicon x", pos.x, time);
emit valueChanged(uasId, "vicon y", pos.y, time);
emit valueChanged(uasId, "vicon z", pos.z, time);
emit localPositionChanged(this, pos.x, pos.y, pos.z, time);
}
break;
case MAVLINK_MSG_ID_AUX_STATUS:
{
mavlink_aux_status_t status;
......
......@@ -37,15 +37,19 @@ MAVLinkSettingsWidget::MAVLinkSettingsWidget(MAVLinkProtocol* protocol, QWidget
{
m_ui->setupUi(this);
// Initialize state
m_ui->heartbeatCheckBox->setChecked(protocol->heartbeatsEnabled());
m_ui->loggingCheckBox->setChecked(protocol->loggingEnabled());
m_ui->versionCheckBox->setChecked(protocol->versionCheckEnabled());
// Connect actions
connect(protocol, SIGNAL(heartbeatChanged(bool)), m_ui->heartbeatCheckBox, SLOT(setChecked(bool)));
connect(m_ui->heartbeatCheckBox, SIGNAL(toggled(bool)), protocol, SLOT(enableHeartbeats(bool)));
connect(protocol, SIGNAL(loggingChanged(bool)), m_ui->loggingCheckBox, SLOT(setChecked(bool)));
connect(m_ui->loggingCheckBox, SIGNAL(toggled(bool)), protocol, SLOT(enableLogging(bool)));
connect(protocol, SIGNAL(versionCheckChanged(bool)), m_ui->versionCheckBox, SLOT(setChecked(bool)));
connect(m_ui->versionCheckBox, SIGNAL(toggled(bool)), protocol, SLOT(enableVersionCheck(bool)));
// Initialize state
m_ui->heartbeatCheckBox->setChecked(protocol->heartbeatsEnabled());
m_ui->loggingCheckBox->setChecked(protocol->loggingEnabled());
}
MAVLinkSettingsWidget::~MAVLinkSettingsWidget()
......
......@@ -31,6 +31,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="versionCheckBox">
<property name="text">
<string>Only accept MAVs with same protocol version</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
......
......@@ -153,6 +153,7 @@ void MainWindow::buildCommonWidgets()
{
//TODO: move protocol outside UI
mavlink = new MAVLinkProtocol();
connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
// Dock widgets
if (!controlDockWidget)
......@@ -202,6 +203,12 @@ void MainWindow::buildCommonWidgets()
protocolWidget = new XMLCommProtocolWidget(this);
addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
}
if (!dataplotWidget)
{
dataplotWidget = new QGCDataPlot2D(this);
addToCentralWidgetsMenu (dataplotWidget, "Data Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
}
}
void MainWindow::buildPxWidgets()
......@@ -742,6 +749,7 @@ void MainWindow::arrangeCommonCenterStack()
if (!centerStack) return;
if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);
setCentralWidget(centerStack);
......
......@@ -40,6 +40,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCDataPlot2D.h"
#include "ui_QGCDataPlot2D.h"
#include "MG.h"
#include "MainWindow.h"
#include <cmath>
#include <QDebug>
......@@ -75,7 +76,7 @@ void QGCDataPlot2D::reloadFile()
{
if (QFileInfo(fileName).isReadable())
{
if (ui->inputFileType->currentText().contains("pxIMU"))
if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW"))
{
loadRawLog(fileName, ui->xAxis->currentText(), ui->yAxis->text());
}
......@@ -88,9 +89,10 @@ void QGCDataPlot2D::reloadFile()
void QGCDataPlot2D::loadFile()
{
qDebug() << "DATA PLOT: Loading file:" << fileName;
if (QFileInfo(fileName).isReadable())
{
if (ui->inputFileType->currentText().contains("pxIMU"))
if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW"))
{
loadRawLog(fileName);
}
......@@ -110,7 +112,7 @@ void QGCDataPlot2D::loadFile(QString file)
{
loadRawLog(fileName);
}
else if (fileName.contains(".txt") || fileName.contains(".csv"))
else if (fileName.contains(".txt") || fileName.contains(".csv") || fileName.contains(".csv"))
{
loadCsvLog(fileName);
}
......@@ -129,7 +131,7 @@ void QGCDataPlot2D::savePlot()
if (!fileName.contains("."))
{
// .csv is default extension
// .pdf is default extension
fileName.append(".pdf");
}
......@@ -269,7 +271,16 @@ void QGCDataPlot2D::selectFile()
// Let user select the log file name
//QDate date(QDate::currentDate());
// QString("./pixhawk-log-" + date.toString("yyyy-MM-dd") + "-" + QString::number(logindex) + ".log")
fileName = QFileDialog::getOpenFileName(this, tr("Specify log file name"), QString(), "Logfile (*.csv *.txt *.log)");
if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW"))
{
fileName = QFileDialog::getOpenFileName(this, tr("Specify log file name"), QString(), "Logfile (*.imu *.raw)");
}
else
{
fileName = QFileDialog::getOpenFileName(this, tr("Specify log file name"), QString(), "Logfile (*.csv *.txt *.log)");
}
// Store reference to file
QFileInfo fileInfo(fileName);
......@@ -296,32 +307,36 @@ void QGCDataPlot2D::selectFile()
void QGCDataPlot2D::loadRawLog(QString file, QString xAxisName, QString yAxisFilter)
{
qDebug() << "LOADING RAW LOG!";
if (logFile != NULL)
{
logFile->close();
delete logFile;
}
// Postprocess log file
logFile = new QTemporaryFile();
logFile = new QTemporaryFile("qt_qgc_temp_log.XXXXXX.csv");
compressor = new LogCompressor(file, logFile->fileName());
connect(compressor, SIGNAL(logProcessingStatusChanged(QString)), MainWindow::instance(), SLOT(showStatusMessage(QString)));
connect(compressor, SIGNAL(finishedFile(QString)), this, SLOT(loadFile(QString)));
compressor->startCompression();
// Block UI
QProgressDialog progress("Transforming RAW log file to CSV", "Abort Transformation", 0, 1, this);
progress.setWindowModality(Qt::WindowModal);
// // Block UI
// QProgressDialog progress("Transforming RAW log file to CSV", "Abort Transformation", 0, 1, this);
// progress.setWindowModality(Qt::WindowModal);
while (!compressor->isFinished())
{
MG::SLEEP::usleep(100000);
progress.setMaximum(compressor->getDataLines());
progress.setValue(compressor->getCurrentLine());
}
// Enforce end
progress.setMaximum(compressor->getDataLines());
progress.setValue(compressor->getDataLines());
// while (!compressor->isFinished())
// {
// MG::SLEEP::usleep(100000);
//// progress.setMaximum(compressor->getDataLines());
//// progress.setValue(compressor->getCurrentLine());
// }
// // Enforce end
// progress.setMaximum(compressor->getDataLines());
// progress.setValue(compressor->getDataLines());
// Done with preprocessing - now load csv log
loadCsvLog(logFile->fileName(), xAxisName, yAxisFilter);
//loadFile(logFile->fileName());
}
/**
......@@ -654,6 +669,13 @@ void QGCDataPlot2D::saveCsvLog()
fileName = QFileDialog::getSaveFileName(
this, "Export CSV File Name", QDesktopServices::storageLocation(QDesktopServices::DesktopLocation),
"CSV file (*.csv);;Text file (*.txt)");
if (!fileName.contains("."))
{
// .csv is default extension
fileName.append(".csv");
}
// QFileInfo fileInfo(fileName);
//
// // Check if we could create a new file in this directory
......
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