Browse Source

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

QGC4.4
lm 14 years ago
parent
commit
9cc031aa3c
  1. 309
      images/style-outdoor.css
  2. 3
      qgroundcontrol.pri
  3. 10
      src/LogCompressor.cc
  4. 5
      src/QGC.cc
  5. 2
      src/QGC.h
  6. 17
      src/comm/MAVLinkSimulationLink.cc
  7. 2
      src/comm/MAVLinkXMLParser.cc
  8. 30
      src/uas/PxQuadMAV.cc
  9. 103
      src/uas/UAS.cc
  10. 6
      src/uas/UASInterface.h
  11. 10
      src/ui/DebugConsole.cc
  12. 50
      src/ui/HDDisplay.cc
  13. 3
      src/ui/HDDisplay.h
  14. 48
      src/ui/HUD.cc
  15. 3
      src/ui/HUD.h
  16. 368
      src/ui/MainWindow.cc
  17. 16
      src/ui/MainWindow.h
  18. 148
      src/ui/MainWindow.ui
  19. 2
      src/ui/QGCRemoteControlView.cc
  20. 21
      src/ui/UASControl.ui
  21. 26
      src/ui/designer/QGCActionButton.cc
  22. 3
      src/ui/designer/QGCActionButton.h
  23. 21
      src/ui/designer/QGCParamSlider.cc
  24. 8
      src/ui/designer/QGCParamSlider.h
  25. 2
      src/ui/designer/QGCToolWidget.cc
  26. 18
      src/ui/designer/QGCToolWidgetItem.cc
  27. 8
      src/ui/designer/QGCToolWidgetItem.h
  28. 3
      src/ui/linechart/LinechartPlot.cc
  29. 260
      src/ui/linechart/LinechartWidget.cc
  30. 14
      src/ui/linechart/LinechartWidget.h
  31. 7
      src/ui/linechart/Linecharts.cc
  32. 8
      src/ui/uas/UASControlWidget.cc

309
images/style-outdoor.css

@ -0,0 +1,309 @@ @@ -0,0 +1,309 @@
* { font-family: "Bitstream Vera Sans"; font: "Roman"; font-size: 12px; }
QWidget#colorIcon {}
QWidget {
background-color: #F6F6F6;
color: #000000;
background-clip: border;
font-size: 11px;
}
QGroupBox {
border: 1px solid #222216;
border-radius: 3px;
padding: 10px 0px 0px 0px;
margin-top: 1ex; /* leave space at the top for the title */
}
QCheckBox {
/*background-color: #252528;*/
color: #222221;
}
QCheckBox::indicator {
border: 1px solid #111111;
border-radius: 2px;
color: #222221;
width: 10px;
height: 10px;
}
QLineEdit {
border: 1px solid #111111;
border-radius: 2px;
}
QTextEdit {
border: 1px solid #111111;
border-radius: 2px;
}
QPlainTextEdit {
border: 1px solid #111111;
border-radius: 2px;
}
QComboBox {
border: 1px solid #111111;
border-radius: 2px;
}
QCheckBox::indicator:checked {
background-color: #222222;
}
QCheckBox::indicator:checked:hover {
background-color: #222222;
}
QCheckBox::indicator:checked:pressed {
background-color: #222222;
}
QCheckBox::indicator:indeterminate:hover {
image: url(:/images/checkbox_indeterminate_hover.png);
}
QCheckBox::indicator:indeterminate:pressed {
image: url(:/images/checkbox_indeterminate_pressed.png);
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center; /* position at the top center */
margin: 0 3px 0px 3px;
padding: 0 3px 0px 0px;
font: bold 8px;
color: #DDDDDF;
}
QMainWindow::separator {
background: #090909;
width: 2px; /* when vertical */
height: 2px; /* when horizontal */
}
QMainWindow::separator:hover {
background: white;
}
QDockWidget {
border: 1px solid #32345E;
/* titlebar-close-icon: url(close.png);
titlebar-normal-icon: url(undock.png);*/
}
QDockWidget::title {
text-align: left; /* align the text to the left */
background: lightgray;
padding-left: 5px;
}
QDockWidget::close-button, QDockWidget::float-button {
border: 1px solid transparent;
background: darkgray;
padding: 0px;
}
QDockWidget::close-button:hover, QDockWidget::float-button:hover {
background: gray;
}
QDockWidget::close-button:pressed, QDockWidget::float-button:pressed {
padding: 1px -1px -1px 1px;
}
QDockWidget::close-button, QDockWidget::float-button {
background-color: #181820;
color: #EEEEEE;
}
QDockWidget::title {
text-align: left;
background: #121214;
color: #4A4A4F;
padding-left: 5px;
height: 10px;
border-bottom: 1px solid #222222;
}
QSeparator {
color: #EEEEEE;
}
QSpinBox {
min-height: 14px;
max-height: 18px;
border: 1px solid #4A4A4F;
border-radius: 5px;
}
QSpinBox::up-button {
subcontrol-origin: border;
subcontrol-position: top right; /* position at the top right corner */
border-image: url(:/images/actions/go-up.svg) 1;
border-width: 1px;
}
QSpinBox::down-button {
subcontrol-origin: border;
subcontrol-position: bottom right; /* position at the top right corner */
border-image: url(:/images/actions/go-down.svg) 1;
border-width: 1px;
}
QDoubleSpinBox {
min-height: 14px;
max-height: 18px;
border: 1px solid #4A4A4F;
border-radius: 5px;
}
QDoubleSpinBox::up-button {
subcontrol-origin: border;
subcontrol-position: top right; /* position at the top right corner */
border-image: url(:/images/actions/go-up.svg) 1;
border-width: 1px;
max-width: 5px;
}
QDoubleSpinBox::down-button {
subcontrol-origin: border;
subcontrol-position: bottom right; /* position at the top right corner */
border-image: url(:/images/actions/go-down.svg) 1;
border-width: 1px;
max-width: 5px;
}
QPushButton {
font-weight: bold;
min-height: 18px;
max-height: 18px;
border: 2px solid #4A4A4F;
border-radius: 5px;
padding-left: 10px;
padding-right: 10px;
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #232228, stop: 1 #020208);
}
QPushButton:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #404040, stop: 1 #808080);
}
QPushButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #bbbbbb, stop: 1 #b0b0b0);
}
QToolButton {
font-weight: bold;
min-height: 16px;
min-width: 24px;
max-height: 18px;
border: 2px solid #4A4A4F;
border-radius: 5px;
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #232228, stop: 1 #020208);
}
QToolButton:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #090909, stop: 1 #353535);
}
QToolButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #bbbbbb, stop: 1 #b0b0b0);
}
QToolTip {
background-color: #404040;
border-radius: 3px;
}
QPushButton#forceLandButton {
font-weight: bold;
min-height: 30px;
color: #000000;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #ffee01, stop:1 #ae8f00) url("ICONDIR/control/emergency-button.png");
background-clip: border;
border-width: 1px;
border-color: #222222;
border-radius: 5px;
}
QPushButton:pressed#forceLandButton {
font-weight: bold;
min-height: 30px;
color: #000000;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #bbaa00, stop:1 #a05b00) url("ICONDIR/control/emergency-button.png");
background-clip: border;
border-width: 1px;
border-color: #222222;
border-radius: 5px;
}
QPushButton#killButton {
font-weight: bold;
min-height: 30px;
color: #000000;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #ffb917, stop:1 #b37300) url("ICONDIR/control/emergency-button.png");
background-clip: border;
border-width: 1px;
border-color: #222222;
border-radius: 5px;
}
QPushButton:pressed#killButton {
font-weight: bold;
min-height: 30px;
color: #000000;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #bb8500, stop:1 #903000) url("ICONDIR/control/emergency-button.png");
background-clip: border;
border-width: 1px;
border-color: #222222;
border-radius: 5px;
}
QPushButton#controlButton {
min-height: 25px;
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #A0AE00, stop: 1 #909E00);
}
QPushButton:checked#controlButton {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #b76f11, stop: 1 #e1a718);
}
QProgressBar {
border: 1px solid #4A4A4F;
border-radius: 4px;
text-align: center;
padding: 2px;
color: #DDDDDF;
background-color: #111118;
}
QProgressBar:horizontal {
height: 9px;
}
QProgressBar:vertical {
width: 9px;
}
QProgressBar::chunk {
background-color: #3C7B9E;
}
QProgressBar::chunk#batteryBar {
background-color: green;
}
QProgressBar::chunk#speedBar {
background-color: yellow;
}
QProgressBar::chunk#thrustBar {
background-color: orange;
}

3
qgroundcontrol.pri

@ -83,6 +83,9 @@ macx { @@ -83,6 +83,9 @@ macx {
QMAKE_POST_LINK += && cp -rf $$BASEDIR/audio $$TARGETDIR/qgroundcontrol.app/Contents/MacOs
# Copy google earth starter file
QMAKE_POST_LINK += && cp -f $$BASEDIR/images/earth.html $$TARGETDIR/qgroundcontrol.app/Contents/MacOs
# Copy CSS stylesheets
QMAKE_POST_LINK += && cp -f $$BASEDIR/images/style-mission.css $$TARGETDIR/qgroundcontrol.app/Contents/MacOs/style-indoor.css
QMAKE_POST_LINK += && cp -f $$BASEDIR/images/style-outdoor.css $$TARGETDIR/qgroundcontrol.app/Contents/MacOs
# Copy model files
#QMAKE_POST_LINK += && cp -f $$BASEDIR/models/*.dae $$TARGETDIR/qgroundcontrol.app/Contents/MacOs

10
src/LogCompressor.cc

@ -63,7 +63,7 @@ void LogCompressor::run() @@ -63,7 +63,7 @@ void LogCompressor::run()
if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() << "LOG COMPRESSOR: INPUT FILE DOES NOT EXIST";
//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;
}
@ -71,7 +71,7 @@ void LogCompressor::run() @@ -71,7 +71,7 @@ void LogCompressor::run()
// Check if file is writeable
if (outFileName == ""/* || !QFileInfo(outfile).isWritable()*/)
{
qDebug() << "LOG COMPRESSOR: OUTPUT FILE DOES NOT EXIST" << outFileName;
//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;
}
@ -214,7 +214,7 @@ void LogCompressor::run() @@ -214,7 +214,7 @@ void LogCompressor::run()
}
}
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));
if (dataLines > 100) 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));
if (!failed)
{
@ -233,14 +233,16 @@ void LogCompressor::run() @@ -233,14 +233,16 @@ void LogCompressor::run()
// Add header, write out file
file.close();
if (outFileName == "")
if (outFileName == logFileName)
{
QFile::remove(file.fileName());
outfile.setFileName(file.fileName());
}
if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text))
return;
outfile.write(QString(QString("unix_timestamp") + separator + header.replace(" ", "_") + QString("\n")).toLatin1());
emit logProcessingStatusChanged(tr("Log Compressor: Writing output to file %1").arg(QFileInfo(outFileName).absoluteFilePath()));
//QString fileHeader = QString("unix_timestamp") + header.replace(" ", "_") + QString("\n");
// File output

5
src/QGC.cc

@ -34,4 +34,9 @@ quint64 groundTimeUsecs() @@ -34,4 +34,9 @@ quint64 groundTimeUsecs()
return static_cast<quint64>(microseconds + (time.time().msec()*1000));
}
int applicationVersion()
{
return APPLICATIONVERSION;
}
}

2
src/QGC.h

@ -15,9 +15,11 @@ namespace QGC @@ -15,9 +15,11 @@ namespace QGC
/** @brief Get the current ground time in microseconds */
quint64 groundTimeUsecs();
int applicationVersion();
const QString APPNAME = "QGROUNDCONTROL";
const QString COMPANYNAME = "OPENMAV";
const int APPLICATIONVERSION = 80; // 0.8.0
}
#define QGC_EVENTLOOP_DEBUG 0

17
src/comm/MAVLinkSimulationLink.cc

@ -375,13 +375,20 @@ void MAVLinkSimulationLink::mainloop() @@ -375,13 +375,20 @@ void MAVLinkSimulationLink::mainloop()
{
rate10hzCounter = 1;
float lastX = x;
float lastY = y;
float lastZ = z;
float hackDt = 0.1f; // 100 ms
// Move X Position
x = 12.0*sin(((double)circleCounter)/100.0);
y = 5.0*cos(((double)circleCounter)/100.0);
z = 1.8 + 1.2*sin(((double)circleCounter)/60.0);
float xSpeed = (x - lastX)/hackDt;
float ySpeed = (y - lastY)/hackDt;
float zSpeed = (z - lastZ)/hackDt;
circleCounter++;
@ -402,7 +409,7 @@ void MAVLinkSimulationLink::mainloop() @@ -402,7 +409,7 @@ void MAVLinkSimulationLink::mainloop()
streampointer += bufferlength;
// Send back new position
mavlink_msg_local_position_pack(systemId, componentId, &ret, 0, x, y, -fabs(z), 0, 0, 0);
mavlink_msg_local_position_pack(systemId, componentId, &ret, 0, x, y, -fabs(z), xSpeed, ySpeed, zSpeed);
bufferlength = mavlink_msg_to_send_buffer(buffer, &ret);
//add data into datastream
memcpy(stream+streampointer,buffer, bufferlength);
@ -416,14 +423,14 @@ void MAVLinkSimulationLink::mainloop() @@ -416,14 +423,14 @@ void MAVLinkSimulationLink::mainloop()
// streampointer += bufferlength;
// GLOBAL POSITION
mavlink_msg_global_position_int_pack(systemId, componentId, &ret, (473780.28137103+(x))*1E3, (85489.9892510421+(y))*1E3, (z+550.0)*1000.0, 0*100.0, 0*100.0, 0*100.0);
mavlink_msg_global_position_int_pack(systemId, componentId, &ret, (473780.28137103+(x))*1E3, (85489.9892510421+(y))*1E3, (z+550.0)*1000.0, xSpeed*15.0*100.0, ySpeed*15.0*100.0, zSpeed*15*100.0);
bufferlength = mavlink_msg_to_send_buffer(buffer, &ret);
//add data into datastream
memcpy(stream+streampointer,buffer, bufferlength);
streampointer += bufferlength;
// GLOBAL POSITION VEHICLE 2
mavlink_msg_global_position_int_pack(54, componentId, &ret, (473780.28137103+(x+0.002))*1E3, (85489.9892510421+((y/2)+0.3))*1E3, (z+570.0)*1000.0, 0*100.0, 0*100.0, 0*100.0);
mavlink_msg_global_position_int_pack(54, componentId, &ret, (473780.28137103+(x+0.002))*1E3, (85489.9892510421+((y/2)+0.3))*1E3, (z+570.0)*1000.0, xSpeed*15.0*100.0, ySpeed*15.0*100.0, zSpeed*15.0*100.0);
bufferlength = mavlink_msg_to_send_buffer(buffer, &ret);
//add data into datastream
memcpy(stream+streampointer,buffer, bufferlength);
@ -447,7 +454,7 @@ void MAVLinkSimulationLink::mainloop() @@ -447,7 +454,7 @@ void MAVLinkSimulationLink::mainloop()
chan.chan5_raw = (chan.chan3_raw + chan.chan4_raw) / 2.0f;
chan.chan6_raw = (chan.chan3_raw + chan.chan2_raw) / 2.0f;
chan.chan7_raw = (chan.chan4_raw + chan.chan2_raw) / 2.0f;
chan.chan8_raw = (chan.chan6_raw + chan.chan2_raw) / 2.0f;
chan.chan8_raw = 0;
chan.rssi = 100;
messageSize = mavlink_msg_rc_channels_raw_encode(systemId, componentId, &msg, &chan);
// Allocate buffer with packet data

2
src/comm/MAVLinkXMLParser.cc

@ -464,7 +464,7 @@ bool MAVLinkXMLParser::generate() @@ -464,7 +464,7 @@ bool MAVLinkXMLParser::generate()
// Add field to C structure
cStructLines += QString("\t%1 %2[%3]; ///< %4\n").arg(arrayType, fieldName, QString::number(arrayLength), fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_array_by_index((int8_t*)%1, sizeof(%2)*%3, i, msg->payload); // %4\n").arg(fieldName, arrayType, QString::number(arrayLength), fieldText);
packLines += QString("\ti += put_array_by_index((const int8_t*)%1, sizeof(%2)*%3, i, msg->payload); // %4\n").arg(fieldName, arrayType, QString::number(arrayLength), fieldText);
// Add decode function for this type
decodeLines += QString("\tmavlink_msg_%1_get_%2(msg, %1->%2);\n").arg(messageName, fieldName);
arrayDefines += QString("#define MAVLINK_MSG_%1_FIELD_%2_LEN %3\n").arg(messageName.toUpper(), fieldName.toUpper(), QString::number(arrayLength));

30
src/uas/PxQuadMAV.cc

@ -60,8 +60,8 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -60,8 +60,8 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_raw_aux_t raw;
mavlink_msg_raw_aux_decode(&message, &raw);
quint64 time = getUnixTime(0);
emit valueChanged(uasId, "Pressure", raw.baro, time);
emit valueChanged(uasId, "Temperature", raw.temp, time);
emit valueChanged(uasId, "Pressure", "raw", raw.baro, time);
emit valueChanged(uasId, "Temperature", "raw", raw.temp, time);
}
break;
case MAVLINK_MSG_ID_PATTERN_DETECTED:
@ -110,12 +110,12 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -110,12 +110,12 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_msg_vision_position_estimate_decode(&message, &pos);
quint64 time = getUnixTime(pos.usec);
//emit valueChanged(uasId, "vis. time", pos.usec, time);
emit valueChanged(uasId, "vis. roll", pos.roll, time);
emit valueChanged(uasId, "vis. pitch", pos.pitch, time);
emit valueChanged(uasId, "vis. yaw", pos.yaw, time);
emit valueChanged(uasId, "vis. x", pos.x, time);
emit valueChanged(uasId, "vis. y", pos.y, time);
emit valueChanged(uasId, "vis. z", pos.z, time);
emit valueChanged(uasId, "vis. roll", "rad", pos.roll, time);
emit valueChanged(uasId, "vis. pitch", "rad", pos.pitch, time);
emit valueChanged(uasId, "vis. yaw", "rad", pos.yaw, time);
emit valueChanged(uasId, "vis. x", "rad/s", pos.x, time);
emit valueChanged(uasId, "vis. y", "rad/s", pos.y, time);
emit valueChanged(uasId, "vis. z", "rad/s", pos.z, time);
}
break;
case MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE:
@ -124,12 +124,12 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -124,12 +124,12 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message)
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 valueChanged(uasId, "vicon roll", "rad", pos.roll, time);
emit valueChanged(uasId, "vicon pitch", "rad", pos.pitch, time);
emit valueChanged(uasId, "vicon yaw", "rad", pos.yaw, time);
emit valueChanged(uasId, "vicon x", "rad/s", pos.x, time);
emit valueChanged(uasId, "vicon y", "rad/s", pos.y, time);
emit valueChanged(uasId, "vicon z", "rad/s", pos.z, time);
emit localPositionChanged(this, pos.x, pos.y, pos.z, time);
}
break;
@ -143,7 +143,7 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -143,7 +143,7 @@ void PxQuadMAV::receiveMessage(LinkInterface* link, mavlink_message_t message)
emit errCountChanged(uasId, "IMU", "SPI0", status.spi0_err_count);
emit errCountChanged(uasId, "IMU", "SPI1", status.spi1_err_count);
emit errCountChanged(uasId, "IMU", "UART", status.uart_total_err_count);
emit UAS::valueChanged(this, "Load", ((float)status.load)/1000.0f, MG::TIME::getGroundTimeNow());
emit valueChanged(uasId, "Load", "%", ((float)status.load)/1000.0f, MG::TIME::getGroundTimeNow());
}
break;
case MAVLINK_MSG_ID_CONTROL_STATUS:

103
src/uas/UAS.cc

@ -181,7 +181,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -181,7 +181,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
emit statusChanged(this, uasState, stateDescription);
emit statusChanged(this->status);
emit loadChanged(this,state.load/10.0f);
emit UAS::valueChanged(uasId, "Load", ((float)state.load)/1000.0f, MG::TIME::getGroundTimeNow());
emit valueChanged(uasId, "Load", "%", ((float)state.load)/1000.0f, MG::TIME::getGroundTimeNow());
stateAudio = " changed status to " + uasState;
}
@ -279,15 +279,15 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -279,15 +279,15 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_msg_raw_imu_decode(&message, &raw);
quint64 time = getUnixTime(raw.usec);
emit valueChanged(uasId, "Accel. X", raw.xacc, time);
emit valueChanged(uasId, "Accel. Y", raw.yacc, time);
emit valueChanged(uasId, "Accel. Z", raw.zacc, time);
emit valueChanged(uasId, "Gyro Phi", static_cast<double>(raw.xgyro), time);
emit valueChanged(uasId, "Gyro Theta", static_cast<double>(raw.ygyro), time);
emit valueChanged(uasId, "Gyro Psi", static_cast<double>(raw.zgyro), time);
emit valueChanged(uasId, "Mag. X", raw.xmag, time);
emit valueChanged(uasId, "Mag. Y", raw.ymag, time);
emit valueChanged(uasId, "Mag. Z", raw.zmag, time);
emit valueChanged(uasId, "accel x", "raw", raw.xacc, time);
emit valueChanged(uasId, "accel y", "raw", raw.yacc, time);
emit valueChanged(uasId, "accel z", "raw", raw.zacc, time);
emit valueChanged(uasId, "gyro roll", "raw", static_cast<double>(raw.xgyro), time);
emit valueChanged(uasId, "gyro pitch", "raw", static_cast<double>(raw.ygyro), time);
emit valueChanged(uasId, "gyro yaw", "raw", static_cast<double>(raw.zgyro), time);
emit valueChanged(uasId, "mag x", "raw", raw.xmag, time);
emit valueChanged(uasId, "mag y", "raw", raw.ymag, time);
emit valueChanged(uasId, "mag z", "raw", raw.zmag, time);
}
break;
case MAVLINK_MSG_ID_ATTITUDE:
@ -303,20 +303,20 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -303,20 +303,20 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
// emit valueChanged(uasId, "roll IMU", mavlink_msg_attitude_get_roll(&message), time);
// emit valueChanged(uasId, "pitch IMU", mavlink_msg_attitude_get_pitch(&message), time);
// emit valueChanged(uasId, "yaw IMU", mavlink_msg_attitude_get_yaw(&message), time);
emit valueChanged(uasId, "roll IMU", mavlink_msg_attitude_get_roll(&message), time);
emit valueChanged(uasId, "pitch IMU", mavlink_msg_attitude_get_pitch(&message), time);
emit valueChanged(uasId, "yaw IMU", mavlink_msg_attitude_get_yaw(&message), time);
emit valueChanged(uasId, "rollspeed IMU", attitude.rollspeed, time);
emit valueChanged(uasId, "pitchspeed IMU", attitude.pitchspeed, time);
emit valueChanged(uasId, "yawspeed IMU", attitude.yawspeed, time);
emit valueChanged(uasId, "roll", "rad", mavlink_msg_attitude_get_roll(&message), time);
emit valueChanged(uasId, "pitch", "rad", mavlink_msg_attitude_get_pitch(&message), time);
emit valueChanged(uasId, "yaw", "rad", mavlink_msg_attitude_get_yaw(&message), time);
emit valueChanged(uasId, "rollspeed", "rad/s", attitude.rollspeed, time);
emit valueChanged(uasId, "pitchspeed", "rad/s", attitude.pitchspeed, time);
emit valueChanged(uasId, "yawspeed", "rad/s", attitude.yawspeed, time);
// Emit in angles
emit valueChanged(uasId, "roll (deg)", (attitude.roll/M_PI)*180.0, time);
emit valueChanged(uasId, "pitch (deg)", (attitude.pitch/M_PI)*180.0, time);
emit valueChanged(uasId, "yaw (deg)", (attitude.yaw/M_PI)*180.0, time);
emit valueChanged(uasId, "roll V (deg/s)", (attitude.rollspeed/M_PI)*180.0, time);
emit valueChanged(uasId, "pitch V (deg/s)", (attitude.pitchspeed/M_PI)*180.0, time);
emit valueChanged(uasId, "yaw V (deg/s)", (attitude.yawspeed/M_PI)*180.0, time);
emit valueChanged(uasId, "roll", "deg", (attitude.roll/M_PI)*180.0, time);
emit valueChanged(uasId, "pitch", "deg", (attitude.pitch/M_PI)*180.0, time);
emit valueChanged(uasId, "yaw", "deg", (attitude.yaw/M_PI)*180.0, time);
emit valueChanged(uasId, "rollspeed", "deg/s", (attitude.rollspeed/M_PI)*180.0, time);
emit valueChanged(uasId, "pitchspeed", "deg/s", (attitude.pitchspeed/M_PI)*180.0, time);
emit valueChanged(uasId, "yawspeed", "deg/s", (attitude.yawspeed/M_PI)*180.0, time);
emit attitudeChanged(this, attitude.roll, attitude.pitch, attitude.yaw, time);
}
@ -331,12 +331,12 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -331,12 +331,12 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
localX = pos.x;
localY = pos.y;
localZ = pos.z;
emit valueChanged(uasId, "x", pos.x, time);
emit valueChanged(uasId, "y", pos.y, time);
emit valueChanged(uasId, "z", pos.z, time);
emit valueChanged(uasId, "Vx", pos.vx, time);
emit valueChanged(uasId, "Vy", pos.vy, time);
emit valueChanged(uasId, "Vz", pos.vz, time);
emit valueChanged(uasId, "x", "m", pos.x, time);
emit valueChanged(uasId, "y", "m", pos.y, time);
emit valueChanged(uasId, "z", "m", pos.z, time);
emit valueChanged(uasId, "x speed", "m/s", pos.vx, time);
emit valueChanged(uasId, "y speed", "m/s", pos.vy, time);
emit valueChanged(uasId, "z speed", "m/s", pos.vz, time);
emit localPositionChanged(this, pos.x, pos.y, pos.z, time);
emit speedChanged(this, pos.vx, pos.vy, pos.vz, time);
@ -366,12 +366,12 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -366,12 +366,12 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
speedX = pos.vx/100.0;
speedY = pos.vy/100.0;
speedZ = pos.vz/100.0;
emit valueChanged(uasId, "lat", pos.lat, time);
emit valueChanged(uasId, "lon", pos.lon, time);
emit valueChanged(uasId, "alt", pos.alt, time);
emit valueChanged(uasId, "g-vx", speedX, time);
emit valueChanged(uasId, "g-vy", speedY, time);
emit valueChanged(uasId, "g-vz", speedZ, time);
emit valueChanged(uasId, "latitude", "deg", latitude, time);
emit valueChanged(uasId, "longitude", "deg", longitude, time);
emit valueChanged(uasId, "altitude", "m", altitude, time);
emit valueChanged(uasId, "gps x speed", "m/s", speedX, time);
emit valueChanged(uasId, "gps y speed", "m/s", speedY, time);
emit valueChanged(uasId, "gps z speed", "m/s", speedZ, time);
emit globalPositionChanged(this, longitude, latitude, altitude, time);
emit speedChanged(this, speedX, speedY, speedZ, time);
// Set internal state
@ -397,8 +397,8 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -397,8 +397,8 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
// quint64 time = getUnixTime(pos.usec);
quint64 time = MG::TIME::getGroundTimeNow();
emit valueChanged(uasId, "lat", pos.lat, time);
emit valueChanged(uasId, "lon", pos.lon, time);
emit valueChanged(uasId, "latitude", "deg", pos.lat, time);
emit valueChanged(uasId, "longitude", "deg", pos.lon, time);
if (pos.fix_type > 0)
{
@ -411,11 +411,11 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -411,11 +411,11 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
alt = 0;
emit textMessageReceived(uasId, message.compid, 255, "GCS ERROR: RECEIVED NaN FOR ALTITUDE");
}
emit valueChanged(uasId, "alt", pos.alt, time);
emit valueChanged(uasId, "altitude", "m", pos.alt, time);
// Smaller than threshold and not NaN
if (pos.v < 1000000 && pos.v == pos.v)
{
emit valueChanged(uasId, "speed", pos.v, time);
emit valueChanged(uasId, "speed", "m/s", pos.v, time);
//qDebug() << "GOT GPS RAW";
emit speedChanged(this, (double)pos.v, 0.0, 0.0, time);
}
@ -447,9 +447,10 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -447,9 +447,10 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
{
mavlink_raw_pressure_t pressure;
mavlink_msg_raw_pressure_decode(&message, &pressure);
emit valueChanged(uasId, "Abs pressure", pressure.press_abs, this->getUnixTime(0));
emit valueChanged(uasId, "Diff pressure 1", pressure.press_diff1, this->getUnixTime(0));
emit valueChanged(uasId, "Diff pressure 2", pressure.press_diff2, this->getUnixTime(0));
quint64 time = this->getUnixTime(0);
emit valueChanged(uasId, "abs pressure", "hP", pressure.press_abs, time);
emit valueChanged(uasId, "diff pressure 1", "hP", pressure.press_diff1, time);
emit valueChanged(uasId, "diff pressure 2", "hP", pressure.press_diff2, time);
}
break;
case MAVLINK_MSG_ID_RC_CHANNELS_RAW:
@ -506,7 +507,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -506,7 +507,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
}
break;
case MAVLINK_MSG_ID_DEBUG:
emit valueChanged(uasId, QString("debug ") + QString::number(mavlink_msg_debug_get_ind(&message)), mavlink_msg_debug_get_value(&message), MG::TIME::getGroundTimeNow());
emit valueChanged(uasId, QString("debug ") + QString::number(mavlink_msg_debug_get_ind(&message)), "raw", mavlink_msg_debug_get_value(&message), MG::TIME::getGroundTimeNow());
break;
case MAVLINK_MSG_ID_ATTITUDE_CONTROLLER_OUTPUT:
{
@ -514,9 +515,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -514,9 +515,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_msg_attitude_controller_output_decode(&message, &out);
quint64 time = MG::TIME::getGroundTimeNowUsecs();
emit attitudeThrustSetPointChanged(this, out.roll/127.0f, out.pitch/127.0f, out.yaw/127.0f, (uint8_t)out.thrust, time);
emit valueChanged(uasId, "att control roll", out.roll, time/1000.0f);
emit valueChanged(uasId, "att control pitch", out.pitch, time/1000.0f);
emit valueChanged(uasId, "att control yaw", out.yaw, time/1000.0f);
emit valueChanged(uasId, "att control roll", "raw", out.roll, time/1000.0f);
emit valueChanged(uasId, "att control pitch", "raw", out.pitch, time/1000.0f);
emit valueChanged(uasId, "att control yaw", "raw", out.yaw, time/1000.0f);
}
break;
case MAVLINK_MSG_ID_POSITION_CONTROLLER_OUTPUT:
@ -525,9 +526,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -525,9 +526,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_msg_position_controller_output_decode(&message, &out);
quint64 time = MG::TIME::getGroundTimeNow();
//emit positionSetPointsChanged(uasId, out.x/127.0f, out.y/127.0f, out.z/127.0f, out.yaw, time);
emit valueChanged(uasId, "pos control x", out.x, time);
emit valueChanged(uasId, "pos control y", out.y, time);
emit valueChanged(uasId, "pos control z", out.z, time);
emit valueChanged(uasId, "pos control x", "raw", out.x, time);
emit valueChanged(uasId, "pos control y", "raw", out.y, time);
emit valueChanged(uasId, "pos control z", "raw", out.z, time);
}
break;
case MAVLINK_MSG_ID_WAYPOINT_COUNT:
@ -618,9 +619,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) @@ -618,9 +619,9 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
mavlink_msg_debug_vect_decode(&message, &vect);
QString str((const char*)vect.name);
quint64 time = getUnixTime(vect.usec);
emit valueChanged(uasId, str+".x", vect.x, time);
emit valueChanged(uasId, str+".y", vect.y, time);
emit valueChanged(uasId, str+".z", vect.z, time);
emit valueChanged(uasId, str+".x", "raw", vect.x, time);
emit valueChanged(uasId, str+".y", "raw", vect.y, time);
emit valueChanged(uasId, str+".z", "raw", vect.z, time);
}
break;
//#ifdef MAVLINK_ENABLED_PIXHAWK

6
src/uas/UASInterface.h

@ -328,9 +328,9 @@ signals: @@ -328,9 +328,9 @@ signals:
* @param msec the timestamp of the message, in milliseconds
*/
// FIXME Exchange the lines below against the commented ones
void valueChanged(int uasId, QString name, double value, quint64 msec);
void valueChanged(UASInterface* uas, QString name, double value, quint64 msec);
//void valueChanged(const int uasId, const QString& name, const double value, const quint64 msec);
void valueChanged(const int uasId, const QString& name, const QString& unit, const double value, const quint64 msec);
void valueChanged(const int uasId, const QString& name, const QString& unit, const int value, const quint64 msec);
// void valueChanged(const int uasId, const QString& name, const double value, const quint64 msec);
// //void valueChanged(UASInterface* uas, QString name, double value, quint64 msec);

10
src/ui/DebugConsole.cc

@ -454,18 +454,10 @@ void DebugConsole::handleConnectButton() @@ -454,18 +454,10 @@ void DebugConsole::handleConnectButton()
if (currLink->isConnected())
{
currLink->disconnect();
m_ui->connectButton->setText(tr("Connect"));
}
else
{
if (currLink->connect())
{
m_ui->connectButton->setText(tr("Disconn."));
}
else
{
m_ui->receiveText->appendHtml(QString("<font color=\"%1\">%2</font>").arg(QGC::colorRed.name(), tr("Could not connect link %1 ! Please check link hardware.").arg(currLink->getName())));
}
currLink->connect();
}
}
}

50
src/ui/HDDisplay.cc

@ -194,10 +194,10 @@ void HDDisplay::saveState() @@ -194,10 +194,10 @@ void HDDisplay::saveState()
for (int i = 0; i < acceptList->count(); i++)
{
QString key = acceptList->at(i);
instruments += "|" + QString::number(minValues.value(key, -1.0))+","+key+","+QString::number(maxValues.value(key, +1.0));
instruments += "|" + QString::number(minValues.value(key, -1.0))+","+key+","+QString::number(maxValues.value(key, +1.0))+","+((symmetric.value(key, false)) ? "s" : "");
}
qDebug() << "Saving" << instruments;
// qDebug() << "Saving" << instruments;
settings.setValue(windowTitle()+"_gauges", instruments);
settings.sync();
@ -240,6 +240,8 @@ void HDDisplay::removeItemByAction() @@ -240,6 +240,8 @@ void HDDisplay::removeItemByAction()
acceptList->removeAt(index);
minValues.remove(item);
maxValues.remove(item);
symmetric.remove(item);
adjustGaugeAspectRatio();
}
}
@ -277,8 +279,16 @@ void HDDisplay::addGauge(const QString& gauge) @@ -277,8 +279,16 @@ void HDDisplay::addGauge(const QString& gauge)
val = parts.first().toDouble(&ok);
if (ok) minValues.insert(key, val);
// Convert max to double number
val = parts.last().toDouble(&ok);
val = parts.at(2).toDouble(&ok);
if (ok) maxValues.insert(key, val);
// Convert symmetric flag
if (parts.length() >= 4)
{
if (parts.at(3).contains("s"))
{
symmetric.insert(key, true);
}
}
// Add value to acceptlist
acceptList->append(key);
}
@ -394,7 +404,7 @@ void HDDisplay::renderOverlay() @@ -394,7 +404,7 @@ void HDDisplay::renderOverlay()
for (int i = 0; i < acceptList->size(); ++i)
{
QString value = acceptList->at(i);
drawGauge(xCoord, yCoord, gaugeWidth/2.0f, minValues.value(value, -1.0f), maxValues.value(value, 1.0f), value, values.value(value, minValues.value(value, 0.0f)), gaugeColor, &painter, goodRanges.value(value, qMakePair(0.0f, 0.5f)), critRanges.value(value, qMakePair(0.7f, 1.0f)), true);
drawGauge(xCoord, yCoord, gaugeWidth/2.0f, minValues.value(value, -1.0f), maxValues.value(value, 1.0f), value, values.value(value, minValues.value(value, 0.0f)), gaugeColor, &painter, symmetric.value(value, false), goodRanges.value(value, qMakePair(0.0f, 0.5f)), critRanges.value(value, qMakePair(0.7f, 1.0f)), true);
xCoord += gaugeWidth + leftSpacing;
// Move one row down if necessary
if (xCoord + gaugeWidth*0.9f > vwidth)
@ -513,17 +523,33 @@ void HDDisplay::drawChangeRateStrip(float xRef, float yRef, float height, float @@ -513,17 +523,33 @@ void HDDisplay::drawChangeRateStrip(float xRef, float yRef, float height, float
paintText(label, defaultColor, 3.0f, xRef+width/2.0f, yRef+height-((scaledValue - minRate)/(maxRate-minRate))*height - 1.6f, painter);
}
void HDDisplay::drawGauge(float xRef, float yRef, float radius, float min, float max, QString name, float value, const QColor& color, QPainter* painter, QPair<float, float> goodRange, QPair<float, float> criticalRange, bool solid)
void HDDisplay::drawGauge(float xRef, float yRef, float radius, float min, float max, QString name, float value, const QColor& color, QPainter* painter, bool symmetric, QPair<float, float> goodRange, QPair<float, float> criticalRange, bool solid)
{
// Draw the circle
QPen circlePen(Qt::SolidLine);
// Rotate the whole gauge with this angle (in radians) for the zero position
const float zeroRotation = 0.49f;
float zeroRotation;
if (symmetric)
{
zeroRotation = 1.35f;
}
else
{
zeroRotation = 0.49f;
}
// Scale the rotation so that the gauge does one revolution
// per max. change
const float rangeScale = ((2.0f * M_PI) / (max - min)) * 0.72f;
float rangeScale;
if (symmetric)
{
rangeScale = ((2.0f * M_PI) / (max - min)) * 0.57f;
}
else
{
rangeScale = ((2.0f * M_PI) / (max - min)) * 0.72f;
}
const float scaledValue = (value-min)*rangeScale;
@ -558,7 +584,15 @@ void HDDisplay::drawGauge(float xRef, float yRef, float radius, float min, float @@ -558,7 +584,15 @@ void HDDisplay::drawGauge(float xRef, float yRef, float radius, float min, float
QBrush brush(QGC::colorBackground, Qt::SolidPattern);
painter->setBrush(brush);
painter->setPen(Qt::NoPen);
painter->drawRect(refToScreenX(xRef-radius/2.5f), refToScreenY(yRef+nameHeight+radius/4.0f), refToScreenX(radius+radius/2.0f), refToScreenY((radius - radius/4.0f)*1.2f));
if (symmetric)
{
painter->drawRect(refToScreenX(xRef-radius), refToScreenY(yRef+nameHeight+radius/4.0f), refToScreenX(radius+radius), refToScreenY((radius - radius/4.0f)*1.2f));
}
else
{
painter->drawRect(refToScreenX(xRef-radius/2.5f), refToScreenY(yRef+nameHeight+radius/4.0f), refToScreenX(radius+radius/2.0f), refToScreenY((radius - radius/4.0f)*1.2f));
}
// Draw good value and crit. value markers
if (goodRange.first != goodRange.second)

3
src/ui/HDDisplay.h

@ -114,7 +114,7 @@ protected: @@ -114,7 +114,7 @@ protected:
void drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter);
void drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid=true);
void drawGauge(float xRef, float yRef, float radius, float min, float max, const QString name, float value, const QColor& color, QPainter* painter, QPair<float, float> goodRange, QPair<float, float> criticalRange, bool solid=true);
void drawGauge(float xRef, float yRef, float radius, float min, float max, const QString name, float value, const QColor& color, QPainter* painter, bool symmetric, QPair<float, float> goodRange, QPair<float, float> criticalRange, bool solid=true);
void drawSystemIndicator(float xRef, float yRef, int maxNum, float maxWidth, float maxHeight, QPainter* painter);
void paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter);
@ -143,6 +143,7 @@ protected: @@ -143,6 +143,7 @@ protected:
QMap<QString, quint64> lastUpdate; ///< The last update time for this variable
QMap<QString, float> minValues; ///< The minimum value this variable is assumed to have
QMap<QString, float> maxValues; ///< The maximum value this variable is assumed to have
QMap<QString, bool> symmetric; ///< Draw the gauge / dial symmetric bool = yes
QMap<QString, QPair<float, float> > goodRanges; ///< The range of good values
QMap<QString, QPair<float, float> > critRanges; ///< The range of critical values
double scalingFactor; ///< Factor used to scale all absolute values to screen coordinates

48
src/ui/HUD.cc

@ -242,8 +242,7 @@ void HUD::updateValue(UASInterface* uas, QString name, double value, quint64 mse @@ -242,8 +242,7 @@ void HUD::updateValue(UASInterface* uas, QString name, double value, quint64 mse
*/
void HUD::setActiveUAS(UASInterface* uas)
{
qDebug() << "ATTEMPTING TO SET UAS";
if (this->uas != NULL && this->uas != uas)
if (this->uas != NULL)
{
// Disconnect any previously connected active MAV
disconnect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*, double, double, double, quint64)));
@ -251,31 +250,29 @@ void HUD::setActiveUAS(UASInterface* uas) @@ -251,31 +250,29 @@ void HUD::setActiveUAS(UASInterface* uas)
disconnect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString)));
disconnect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
disconnect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));
disconnect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
disconnect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
disconnect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int)));
}
// Now connect the new UAS
//if (this->uas != uas)
// {
qDebug() << "UAS SET!" << "ID:" << uas->getUASID();
// Setup communication
connect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*, double, double, double, quint64)));
connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int)));
connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString)));
connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
connect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));
//connect(uas, SIGNAL(thrustChanged(UASInterface*, double)), this, SLOT(updateThrust(UASInterface*, double)));
//connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
//connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
//connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
//connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString)));
//connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
//connect(uas, SIGNAL(attitudeThrustSetPointChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateAttitudeThrustSetPoint(UASInterface*,double,double,double,double,quint64)));
//connect(uas, SIGNAL(valueChanged(UASInterface*,QString,double,quint64)), this, SLOT(updateValue(UASInterface*,QString,double,quint64)));
//}
connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int)));
// Set new UAS
this->uas = uas;
}
void HUD::updateAttitudeThrustSetPoint(UASInterface*, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec)
void HUD::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec)
{
updateValue(uas, "roll desired", rollDesired, msec);
updateValue(uas, "pitch desired", pitchDesired, msec);
@ -329,7 +326,7 @@ void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint @@ -329,7 +326,7 @@ void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint
updateValue(uas, "z", z, timestamp);
}
void HUD::updateGlobalPosition(UASInterface*,double lat, double lon, double altitude, quint64 timestamp)
void HUD::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp)
{
updateValue(uas, "lat", lat, timestamp);
updateValue(uas, "lon", lon, timestamp);
@ -581,7 +578,7 @@ void HUD::paintHUD() @@ -581,7 +578,7 @@ void HUD::paintHUD()
// Translate for yaw
const float maxYawTrans = 60.0f;
static float yawDiff = 0.0f;
float newYawDiff = valuesDot.value("yaw", 0.0f);
if (isinf(newYawDiff)) newYawDiff = yawDiff;
if (newYawDiff > M_PI) newYawDiff = newYawDiff - M_PI;
@ -722,7 +719,9 @@ void HUD::paintHUD() @@ -722,7 +719,9 @@ void HUD::paintHUD()
QString yawAngle;
// const float yawDeg = ((values.value("yaw", 0.0f)/M_PI)*180.0f)+180.f;
const float yawDeg = ((values.value("yaw", 0.0f)/M_PI)*180.0f);
// YAW is in compass-human readable format, so 0 - 360deg. This is normal in aviation, not -180 - +180.
const float yawDeg = ((values.value("yaw", 0.0f)/M_PI)*180.0f)+180.0f;
yawAngle.sprintf("%03d", (int)yawDeg);
paintText(yawAngle, defaultColor, 3.5f, -3.7f, compassY+ 0.9f, &painter);
@ -741,6 +740,9 @@ void HUD::paintHUD() @@ -741,6 +740,9 @@ void HUD::paintHUD()
drawChangeIndicatorGauge(vGaugeSpacing, -15.0f, 10.0f, 5.0f, values.value("xSpeed", 0.0f), defaultColor, &painter, false);
// Waypoint name
if (waypointName != "") paintText(waypointName, defaultColor, 2.0f, (-vwidth/3.0) + 10, +vheight/3.0 + 15, &painter);
// MOVING PARTS
@ -1362,12 +1364,10 @@ void HUD::resizeGL(int w, int h) @@ -1362,12 +1364,10 @@ void HUD::resizeGL(int w, int h)
paintHUD();
}
void HUD::selectWaypoint(UASInterface* uas, int id)
void HUD::selectWaypoint(int uasId, int id)
{
if (uas == this->uas)
{
waypointName = tr("WP") + QString::number(id);
}
Q_UNUSED(uasId);
waypointName = tr("WP") + QString::number(id);
}
void HUD::setImageSize(int width, int height, int depth, int channels)

3
src/ui/HUD.h

@ -77,7 +77,7 @@ public slots: @@ -77,7 +77,7 @@ public slots:
void updateState(UASInterface*,QString);
void updateMode(int id,QString mode, QString description);
void updateLoad(UASInterface*, double);
void selectWaypoint(UASInterface* uas, int id);
void selectWaypoint(int uasId, int id);
void startImage(int imgid, int width, int height, int depth, int channels);
void setPixels(int imgid, const unsigned char* imageData, int length, int startIndex);
@ -188,6 +188,7 @@ protected: @@ -188,6 +188,7 @@ protected:
float roll;
float pitch;
float yaw;
float yawDiff;
void paintEvent(QPaintEvent *event);
};

368
src/ui/MainWindow.cc

@ -63,15 +63,55 @@ MainWindow* MainWindow::instance() @@ -63,15 +63,55 @@ MainWindow* MainWindow::instance()
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
toolsMenuActions(),
currentView(VIEW_OPERATOR),
currentView(VIEW_ENGINEER),
aboutToCloseFlag(false),
settings()
{
// Get current settings
settings.sync();
if (!settings.contains("CURRENT_VIEW"))
{
// Set this view as default view
settings.setValue("CURRENT_VIEW", currentView);
// Enable default tools
// ENABLE UAS LIST
settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST,currentView), true);
// ENABLE COMMUNICATION CONSOLE
settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_DEBUG_CONSOLE,currentView), true);
}
else
{
currentView = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
}
// Check if the settings exist, instantiate defaults if necessary
QString centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, currentView);
// OPERATOR VIEW DEFAULT
QString centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, VIEW_OPERATOR);
if (!settings.contains(centralKey))
{
settings.setValue(centralKey,true);
}
// ENGINEER VIEW DEFAULT
centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
if (!settings.contains(centralKey))
{
settings.setValue(centralKey,true);
}
// MAVLINK VIEW DEFAULT
centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_PROTOCOL, VIEW_MAVLINK);
if (!settings.contains(centralKey))
{
settings.setValue(centralKey,true);
}
// PILOT VIEW DEFAULT
centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_HUD, VIEW_PILOT);
if (!settings.contains(centralKey))
{
settings.setValue(centralKey,true);
@ -88,6 +128,24 @@ MainWindow::MainWindow(QWidget *parent): @@ -88,6 +128,24 @@ MainWindow::MainWindow(QWidget *parent):
// Setup user interface
ui.setupUi(this);
// Bind together the perspective actions
QActionGroup* perspectives = new QActionGroup(ui.menuPerspectives);
perspectives->addAction(ui.actionEngineersView);
perspectives->addAction(ui.actionMavlinkView);
perspectives->addAction(ui.actionPilotsView);
perspectives->addAction(ui.actionOperatorsView);
perspectives->setExclusive(true);
// Mark the right one as selected
if (currentView == VIEW_ENGINEER) ui.actionEngineersView->setChecked(true);
if (currentView == VIEW_MAVLINK) ui.actionMavlinkView->setChecked(true);
if (currentView == VIEW_PILOT) ui.actionPilotsView->setChecked(true);
if (currentView == VIEW_OPERATOR) ui.actionOperatorsView->setChecked(true);
// The pilot view is not available on startup
ui.actionPilotsView->setEnabled(false);
buildCommonWidgets();
connectCommonWidgets();
@ -104,7 +162,13 @@ MainWindow::MainWindow(QWidget *parent): @@ -104,7 +162,13 @@ MainWindow::MainWindow(QWidget *parent):
qApp->setStyle("plastique");
// Set style sheet as last step
reloadStylesheet();
QFile* styleSheet = new QFile(":/images/style-mission.css");
if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
{
QString style = QString(styleSheet->readAll());
style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
qApp->setStyleSheet(style);
}
// Create actions
connectCommonActions();
@ -122,10 +186,11 @@ MainWindow::MainWindow(QWidget *parent): @@ -122,10 +186,11 @@ MainWindow::MainWindow(QWidget *parent):
statusBar()->setSizeGripEnabled(true);
if (settings.contains("geometry"))
// Restore the window position and size
if (settings.contains(getWindowGeometryKey()))
{
// Restore the window geometry
restoreGeometry(settings.value("geometry").toByteArray());
restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
}
else
{
@ -149,6 +214,16 @@ MainWindow::~MainWindow() @@ -149,6 +214,16 @@ MainWindow::~MainWindow()
}
QString MainWindow::getWindowStateKey()
{
return QString::number(currentView)+"/windowstate";
}
QString MainWindow::getWindowGeometryKey()
{
return QString::number(currentView)+"/geometry";
}
void MainWindow::buildCommonWidgets()
{
//TODO: move protocol outside UI
@ -553,7 +628,6 @@ void MainWindow::showToolWidget() @@ -553,7 +628,6 @@ void MainWindow::showToolWidget()
QAction* temp = qobject_cast<QAction *>(sender());
int tool = temp->data().toInt();
if (temp && dockWidgets[tool])
{
if (temp->isChecked())
@ -565,9 +639,6 @@ void MainWindow::showToolWidget() @@ -565,9 +639,6 @@ void MainWindow::showToolWidget()
{
removeDockWidget(qobject_cast<QDockWidget *>(dockWidgets[tool]));
}
QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
settings.setValue(chKey,temp->isChecked());
settings.sync();
}
}
@ -580,15 +651,6 @@ void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view) @@ -580,15 +651,6 @@ void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
tempVisible = settings.value(buildMenuKey (SUB_SECTION_CHECKED,widget,view), false).toBool();
// Some widgets are per default visible. Overwrite the settings value if not present.
if (widget == MainWindow::MENU_UAS_LIST)
{
if (!settings.contains(buildMenuKey (SUB_SECTION_CHECKED,widget,view)))
{
tempVisible = true;
}
}
if (tempWidget)
{
toolsMenuActions[widget]->setChecked(tempVisible);
@ -633,10 +695,15 @@ QString MainWindow::buildMenuKey(SETTINGS_SECTIONS section, TOOLS_WIDGET_NAMES t @@ -633,10 +695,15 @@ QString MainWindow::buildMenuKey(SETTINGS_SECTIONS section, TOOLS_WIDGET_NAMES t
void MainWindow::closeEvent(QCloseEvent *event)
{
settings.setValue("geometry", saveGeometry());
settings.setValue(getWindowGeometryKey(), saveGeometry());
//settings.setValue("windowState", saveState());
aboutToCloseFlag = true;
settings.setValue("VIEW_ON_APPLICATION_CLOSE", currentView);
// Save the last current view in any case
settings.setValue("CURRENT_VIEW", currentView);
// Save the current window state, but only if a system is connected (else no real number of widgets would be present)
if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
// Save the current view only if a UAS is connected
if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView);
settings.sync();
QMainWindow::closeEvent(event);
}
@ -745,6 +812,7 @@ void MainWindow::connectSlugsWidgets() @@ -745,6 +812,7 @@ void MainWindow::connectSlugsWidgets()
void MainWindow::arrangeCommonCenterStack()
{
centerStack = new QStackedWidget(this);
centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
if (!centerStack) return;
@ -863,8 +931,25 @@ void MainWindow::saveScreen() @@ -863,8 +931,25 @@ void MainWindow::saveScreen()
*/
void MainWindow::reloadStylesheet()
{
QString fileName = QCoreApplication::applicationDirPath() + "/style-indoor.css";
// Let user select style sheet
fileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), fileName, tr("CSS Stylesheet (*.css);;"));
if (!fileName.endsWith(".css"))
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("QGroundControl did lot load a new style"));
msgBox.setInformativeText(tr("No suitable .css file selected. Please select a valid .css file."));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
return;
}
// Load style sheet
QFile* styleSheet = new QFile(QCoreApplication::applicationDirPath() + "/qgroundcontrol.css");
QFile* styleSheet = new QFile(fileName);
if (!styleSheet->exists())
{
styleSheet = new QFile(":/images/style-mission.css");
@ -877,7 +962,13 @@ void MainWindow::reloadStylesheet() @@ -877,7 +962,13 @@ void MainWindow::reloadStylesheet()
}
else
{
qDebug() << "Style not set:" << styleSheet->fileName() << "opened: " << styleSheet->isOpen();
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("QGroundControl did lot load a new style"));
msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(fileName));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
}
delete styleSheet;
}
@ -955,9 +1046,9 @@ void MainWindow::connectCommonActions() @@ -955,9 +1046,9 @@ void MainWindow::connectCommonActions()
connect(ui.actionReloadStyle, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
// Help Actions
connect(ui.actionOnline_documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
connect(ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap()));
connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
}
void MainWindow::connectPxActions()
@ -976,7 +1067,7 @@ void MainWindow::connectSlugsActions() @@ -976,7 +1067,7 @@ void MainWindow::connectSlugsActions()
void MainWindow::showHelp()
{
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/user_guide")))
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/")))
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
@ -990,7 +1081,7 @@ void MainWindow::showHelp() @@ -990,7 +1081,7 @@ void MainWindow::showHelp()
void MainWindow::showCredits()
{
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits")))
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/")))
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
@ -1004,7 +1095,7 @@ void MainWindow::showCredits() @@ -1004,7 +1095,7 @@ void MainWindow::showCredits()
void MainWindow::showRoadMap()
{
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap")))
if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/")))
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
@ -1052,10 +1143,14 @@ void MainWindow::addLink(LinkInterface *link) @@ -1052,10 +1143,14 @@ void MainWindow::addLink(LinkInterface *link)
void MainWindow::UASCreated(UASInterface* uas)
{
// Connect the UAS to the full user interface
if (uas != NULL)
{
// The pilot view was not available on startup, enable it now
ui.actionPilotsView->setEnabled(true);
QIcon icon;
// Set matching icon
switch (uas->getSystemType())
@ -1116,13 +1211,6 @@ void MainWindow::UASCreated(UASInterface* uas) @@ -1116,13 +1211,6 @@ void MainWindow::UASCreated(UASInterface* uas)
}
}
// Camera view
//camera->addUAS(uas);
// Revalidate UI
// TODO Stylesheet reloading should in theory not be necessary
reloadStylesheet();
switch (uas->getAutopilotType())
{
case (MAV_AUTOPILOT_SLUGS):
@ -1184,11 +1272,18 @@ void MainWindow::UASCreated(UASInterface* uas) @@ -1184,11 +1272,18 @@ void MainWindow::UASCreated(UASInterface* uas)
qDebug() << "UPDATING THE VIEW SINCE THIS IS THE FIRST CONNECTED SYSTEM";
// Load last view if setting is present
if (settings.contains("VIEW_ON_APPLICATION_CLOSE"))
if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
{
int view = settings.value("VIEW_ON_APPLICATION_CLOSE").toInt();
int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
currentView = (VIEW_SECTIONS) view;
presentView();
// Restore the widget positions and size
if (settings.contains(getWindowStateKey()))
{
restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
}
}
else
{
@ -1204,6 +1299,30 @@ void MainWindow::UASCreated(UASInterface* uas) @@ -1204,6 +1299,30 @@ void MainWindow::UASCreated(UASInterface* uas)
*/
void MainWindow::clearView()
{
// Save current state
if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
settings.setValue(getWindowGeometryKey(), saveGeometry());
QAction* temp;
// Set tool widget visibility settings for this view
foreach (int key, toolsMenuActions.keys())
{
temp = toolsMenuActions[key];
QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(key), currentView);
if (temp)
{
settings.setValue(chKey,temp->isChecked());
}
else
{
settings.setValue(chKey,false);
}
}
settings.sync();
// Remove all dock widgets from main window
QObjectList childList( this->children() );
@ -1226,51 +1345,61 @@ void MainWindow::clearView() @@ -1226,51 +1345,61 @@ void MainWindow::clearView()
void MainWindow::loadEngineerView()
{
clearView();
if (currentView != VIEW_ENGINEER)
{
clearView();
currentView = VIEW_ENGINEER;
currentView = VIEW_ENGINEER;
presentView();
presentView();
}
}
void MainWindow::loadOperatorView()
{
clearView();
if (currentView != VIEW_OPERATOR)
{
clearView();
currentView = VIEW_OPERATOR;
currentView = VIEW_OPERATOR;
presentView();
presentView();
}
}
void MainWindow::loadPilotView()
{
clearView();
if (currentView != VIEW_PILOT)
{
clearView();
currentView = VIEW_PILOT;
currentView = VIEW_PILOT;
presentView();
presentView();
}
}
void MainWindow::loadMAVLinkView()
{
clearView();
if (currentView != VIEW_MAVLINK)
{
clearView();
currentView = VIEW_MAVLINK;
currentView = VIEW_MAVLINK;
presentView();
presentView();
}
}
void MainWindow::presentView()
{
qDebug() << "LC";
// LINE CHART
showTheCentralWidget(CENTRAL_LINECHART, currentView);
// MAP
qDebug() << "MAP";
showTheCentralWidget(CENTRAL_MAP, currentView);
// PROTOCOL
qDebug() << "CP";
showTheCentralWidget(CENTRAL_PROTOCOL, currentView);
// HEAD UP DISPLAY
@ -1285,6 +1414,9 @@ void MainWindow::presentView() @@ -1285,6 +1414,9 @@ void MainWindow::presentView()
// GLOBAL 3D VIEW
showTheCentralWidget(CENTRAL_3D_MAP, currentView);
// DATA PLOT
showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);
// Show docked widgets based on current view and autopilot type
@ -1318,12 +1450,16 @@ void MainWindow::presentView() @@ -1318,12 +1450,16 @@ void MainWindow::presentView()
if (headUpDockWidget)
{
HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
if (tmpHud){
if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool()){
if (tmpHud)
{
if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool())
{
addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
hsiDockWidget);
headUpDockWidget->show();
} else {
}
else
{
headUpDockWidget->hide();
}
}
@ -1347,52 +1483,12 @@ void MainWindow::presentView() @@ -1347,52 +1483,12 @@ void MainWindow::presentView()
// HORIZONTAL SITUATION INDICATOR
showTheWidget(MENU_HSI, currentView);
// if (hsiDockWidget)
// {
// HSIDisplay* hsi = dynamic_cast<HSIDisplay*>( hsiDockWidget->widget() );
// if (hsi){
// if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HSI,currentView)).toBool()){
// addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HSI, currentView)).toInt()),
// hsiDockWidget);
// }
// }
// }
// HEAD DOWN 1
showTheWidget(MENU_HDD_1, currentView);
// if (headDown1DockWidget)
// {
// HDDisplay *hdd = dynamic_cast<HDDisplay*>(headDown1DockWidget->widget());
// if (hdd) {
// if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HDD_1,currentView)).toBool()) {
// addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HDD_1, currentView)).toInt()),
// headDown1DockWidget);
// headDown1DockWidget->show();
// hdd->start();
// } else {
// headDown1DockWidget->hide();;
// hdd->stop();
// }
// }
// }
// HEAD DOWN 2
showTheWidget(MENU_HDD_2, currentView);
// if (headDown2DockWidget)
// {
// HDDisplay *hdd = dynamic_cast<HDDisplay*>(headDown2DockWidget->widget());
// if (hdd){
// if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HDD_2,currentView)).toBool()){
// addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HDD_2, currentView)).toInt()),
// headDown2DockWidget);
// headDown2DockWidget->show();
// hdd->start();
// } else {
// headDown2DockWidget->hide();
// hdd->stop();
// }
// }
// }
this->show();
@ -1403,7 +1499,7 @@ void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SE @@ -1403,7 +1499,7 @@ void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SE
bool tempVisible;
QWidget* tempWidget = dockWidgets[centralWidget];
tempVisible = settings.value(buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view)).toBool();
tempVisible = settings.value(buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
if (toolsMenuActions[centralWidget])
{
@ -1416,78 +1512,32 @@ void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SE @@ -1416,78 +1512,32 @@ void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SE
}
}
void MainWindow::loadWidgets()
{
loadOperatorView();
//loadMAVLinkView();
//loadPilotView();
}
void MainWindow::loadDataView(QString fileName)
{
// DATAPLOT
if (dataplotWidget)
{
QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
if (centerStack)
{
centerStack->setCurrentWidget(dataplotWidget);
dataplotWidget->loadFile(fileName);
}
}
}
void MainWindow::load3DMapView()
{
#ifdef QGC_OSGEARTH_ENABLED
clearView();
// 3D map
if (_3DMapWidget)
{
QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
if (centerStack)
{
//map3DWidget->setActive(true);
centerStack->setCurrentWidget(_3DMapWidget);
}
}
#endif
}
// Unload line chart
QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(CENTRAL_LINECHART), currentView);
settings.setValue(chKey,false);
void MainWindow::loadGoogleEarthView()
{
#if (defined _MSC_VER) | (defined Q_OS_MAC)
clearView();
// 3D map
if (gEarthWidget)
{
QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
if (centerStack)
{
centerStack->setCurrentWidget(gEarthWidget);
}
}
#endif
}
// Set data plot in settings as current widget and then run usual update procedure
chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(CENTRAL_DATA_PLOT), currentView);
settings.setValue(chKey,true);
void MainWindow::load3DView()
{
#ifdef QGC_OSG_ENABLED
clearView();
presentView();
// 3D map
if (_3DWidget)
// Plot is now selected, now load data from file
if (dataplotWidget)
{
QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
if (centerStack)
{
//map3DWidget->setActive(true);
centerStack->setCurrentWidget(_3DWidget);
}
dataplotWidget->loadFile(fileName);
}
#endif
// QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
// if (centerStack)
// {
// centerStack->setCurrentWidget(dataplotWidget);
// dataplotWidget->loadFile(fileName);
// }
// }
}

16
src/ui/MainWindow.h

@ -142,19 +142,19 @@ public slots: @@ -142,19 +142,19 @@ public slots:
==========================================================
*/
void loadWidgets();
// void loadWidgets();
/** @brief Load data view, allowing to plot flight data */
void loadDataView(QString fileName);
/** @brief Load 3D map view */
void load3DMapView();
// /** @brief Load 3D map view */
// void load3DMapView();
/** @brief Load 3D Google Earth view */
void loadGoogleEarthView();
// /** @brief Load 3D Google Earth view */
// void loadGoogleEarthView();
/** @brief Load 3D view */
void load3DView();
// /** @brief Load 3D view */
// void load3DView();
/**
* @brief Shows a Docked Widget based on the action sender
@ -393,6 +393,8 @@ private: @@ -393,6 +393,8 @@ private:
Ui::MainWindow ui;
QString buildMenuKey (SETTINGS_SECTIONS section , TOOLS_WIDGET_NAMES tool, VIEW_SECTIONS view);
QString getWindowStateKey();
QString getWindowGeometryKey();
};

148
src/ui/MainWindow.ui

@ -50,6 +50,7 @@ @@ -50,6 +50,7 @@
<addaction name="actionMuteAudioOutput"/>
<addaction name="actionSimulate"/>
<addaction name="separator"/>
<addaction name="actionReloadStyle"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuNetwork">
@ -100,7 +101,6 @@ @@ -100,7 +101,6 @@
<addaction name="actionPilotsView"/>
<addaction name="separator"/>
<addaction name="actionMavlinkView"/>
<addaction name="actionReloadStyle"/>
</widget>
<addaction name="menuMGround"/>
<addaction name="menuNetwork"/>
@ -179,33 +179,6 @@ @@ -179,33 +179,6 @@
<string>Open UAS Preferences</string>
</property>
</action>
<action name="actionEngineerView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/apps/utilities-system-monitor.svg</normaloff>:/images/apps/utilities-system-monitor.svg</iconset>
</property>
<property name="text">
<string>Show engineer view</string>
</property>
</action>
<action name="actionPilotView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/weather-overcast.svg</normaloff>:/images/status/weather-overcast.svg</iconset>
</property>
<property name="text">
<string>Show pilot view</string>
</property>
</action>
<action name="actionStyleConfig">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/applications-internet.svg</normaloff>:/images/categories/applications-internet.svg</iconset>
</property>
<property name="text">
<string>Reload visual style</string>
</property>
</action>
<action name="actionJoystickSettings">
<property name="icon">
<iconset resource="../../mavground.qrc">
@ -218,30 +191,6 @@ @@ -218,30 +191,6 @@
<bool>true</bool>
</property>
</action>
<action name="actionOperatorView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/network-wireless-encrypted.svg</normaloff>:/images/status/network-wireless-encrypted.svg</iconset>
</property>
<property name="text">
<string>Show operator view</string>
</property>
<property name="toolTip">
<string>Shop the 2D map and system status</string>
</property>
</action>
<action name="action3DView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/preferences-system.svg</normaloff>:/images/categories/preferences-system.svg</iconset>
</property>
<property name="text">
<string>Show 3D Local View</string>
</property>
<property name="toolTip">
<string>Show 3D view</string>
</property>
</action>
<action name="actionSimulate">
<property name="checkable">
<bool>true</bool>
@ -257,87 +206,6 @@ @@ -257,87 +206,6 @@
<string>Simulate one vehicle to test and evaluate this application</string>
</property>
</action>
<action name="actionShow_full_view">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/network-transmit-receive.svg</normaloff>:/images/status/network-transmit-receive.svg</iconset>
</property>
<property name="text">
<string>Show full view</string>
</property>
</action>
<action name="actionShow_MAVLink_view">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/devices/network-wired.svg</normaloff>:/images/devices/network-wired.svg</iconset>
</property>
<property name="text">
<string>Show MAVLink view</string>
</property>
</action>
<action name="actionOnline_documentation">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/applications-internet.svg</normaloff>:/images/categories/applications-internet.svg</iconset>
</property>
<property name="text">
<string>Online documentation</string>
</property>
</action>
<action name="actionShow_data_analysis_view">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/apps/utilities-system-monitor.svg</normaloff>:/images/apps/utilities-system-monitor.svg</iconset>
</property>
<property name="text">
<string>Show data analysis view</string>
</property>
</action>
<action name="actionProject_Roadmap">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/software-update-available.svg</normaloff>:/images/status/software-update-available.svg</iconset>
</property>
<property name="text">
<string>Project Roadmap</string>
</property>
</action>
<action name="actionCredits_Developers">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/preferences-system.svg</normaloff>:/images/categories/preferences-system.svg</iconset>
</property>
<property name="text">
<string>Credits / Developers</string>
</property>
</action>
<action name="actionGlobalOperatorView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/applications-internet.svg</normaloff>:/images/categories/applications-internet.svg</iconset>
</property>
<property name="text">
<string>Show 2D Map View</string>
</property>
</action>
<action name="action3DMapView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/applications-internet.svg</normaloff>:/images/categories/applications-internet.svg</iconset>
</property>
<property name="text">
<string>Show 3D Global View</string>
</property>
</action>
<action name="actionGoogleEarthView">
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/mapproviders/googleearth.svg</normaloff>:/images/mapproviders/googleearth.svg</iconset>
</property>
<property name="text">
<string>Google Earth View</string>
</property>
</action>
<action name="actionShow_Slugs_View">
<property name="icon">
<iconset resource="../../mavground.qrc">
@ -387,6 +255,9 @@ @@ -387,6 +255,9 @@
</property>
</action>
<action name="actionOperatorsView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/weather-overcast.svg</normaloff>:/images/status/weather-overcast.svg</iconset>
@ -396,6 +267,9 @@ @@ -396,6 +267,9 @@
</property>
</action>
<action name="actionEngineersView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/apps/utilities-system-monitor.svg</normaloff>:/images/apps/utilities-system-monitor.svg</iconset>
@ -405,6 +279,9 @@ @@ -405,6 +279,9 @@
</property>
</action>
<action name="actionMavlinkView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/devices/network-wired.svg</normaloff>:/images/devices/network-wired.svg</iconset>
@ -419,10 +296,13 @@ @@ -419,10 +296,13 @@
<normaloff>:/images/categories/applications-internet.svg</normaloff>:/images/categories/applications-internet.svg</iconset>
</property>
<property name="text">
<string>Reload Style</string>
<string>Reload Stylesheet</string>
</property>
</action>
<action name="actionPilotsView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/network-wireless-encrypted.svg</normaloff>:/images/status/network-wireless-encrypted.svg</iconset>

2
src/ui/QGCRemoteControlView.cc

@ -197,7 +197,7 @@ void QGCRemoteControlView::redraw() @@ -197,7 +197,7 @@ void QGCRemoteControlView::redraw()
// Update raw values
for(int i = 0; i < rawLabels.count(); i++)
{
rawLabels.at(i)->setText(QString("%1 us").arg(raw.at(i), 4));
rawLabels.at(i)->setText(QString("%1 us").arg(raw.at(i), 4, 10, QChar('0')));
}
// Update percent bars

21
src/ui/UASControl.ui

@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>210</width>
<height>141</height>
<width>222</width>
<height>172</height>
</rect>
</property>
<property name="sizePolicy">
@ -18,14 +18,23 @@ @@ -18,14 +18,23 @@
</property>
<property name="minimumSize">
<size>
<width>210</width>
<height>130</height>
<width>222</width>
<height>172</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>267</width>
<height>194</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,100,50,50,100,0">
<property name="toolTip">
<string>Control widget to send basic control actions to the micro air vehicle</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="60,150,80,80,80,100" columnstretch="1,100,40,40,100,1" rowminimumheight="0,0,0,0,0,0">
<item row="0" column="0" rowspan="6">
<spacer name="horizontalSpacer">
<property name="orientation">
@ -93,7 +102,7 @@ @@ -93,7 +102,7 @@
</size>
</property>
<property name="text">
<string>Liftoff</string>
<string>Start</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">

26
src/ui/designer/QGCActionButton.cc

@ -42,15 +42,12 @@ const char* kActionLabels[MAV_ACTION_NB] = @@ -42,15 +42,12 @@ const char* kActionLabels[MAV_ACTION_NB] =
"RESET MAP"};
QGCActionButton::QGCActionButton(QWidget *parent) :
QGCToolWidgetItem(parent),
QGCToolWidgetItem("Button", parent),
ui(new Ui::QGCActionButton),
uas(NULL)
{
ui->setupUi(this);
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
connect(ui->actionButton, SIGNAL(clicked()), this, SLOT(sendAction()));
connect(ui->editFinishButton, SIGNAL(clicked()), this, SLOT(endEditMode()));
connect(ui->editButtonName, SIGNAL(textChanged(QString)), this, SLOT(setActionButtonName(QString)));
@ -71,12 +68,16 @@ QGCActionButton::~QGCActionButton() @@ -71,12 +68,16 @@ QGCActionButton::~QGCActionButton()
void QGCActionButton::sendAction()
{
if (uas)
if (QGCToolWidgetItem::uas)
{
MAV_ACTION action = static_cast<MAV_ACTION>(
ui->editActionComboBox->currentIndex());
uas->setAction(action);
QGCToolWidgetItem::uas->setAction(action);
}
else
{
qDebug() << __FILE__ << __LINE__ << "NO UAS SET, DOING NOTHING";
}
}
@ -90,6 +91,8 @@ void QGCActionButton::startEditMode() @@ -90,6 +91,8 @@ void QGCActionButton::startEditMode()
ui->editActionComboBox->show();
ui->editActionsRefreshButton->show();
ui->editFinishButton->show();
ui->editNameLabel->show();
ui->editButtonName->show();
isInEditMode = true;
}
@ -98,10 +101,11 @@ void QGCActionButton::endEditMode() @@ -98,10 +101,11 @@ void QGCActionButton::endEditMode()
ui->editActionComboBox->hide();
ui->editActionsRefreshButton->hide();
ui->editFinishButton->hide();
isInEditMode = false;
}
ui->editNameLabel->hide();
ui->editButtonName->hide();
void QGCActionButton::setActiveUAS(UASInterface *uas)
{
this->uas = uas;
// Write to settings
isInEditMode = false;
}

3
src/ui/designer/QGCActionButton.h

@ -23,9 +23,6 @@ public slots: @@ -23,9 +23,6 @@ public slots:
void startEditMode();
void endEditMode();
private slots:
void setActiveUAS(UASInterface* uas);
private:
Ui::QGCActionButton *ui;
UASInterface* uas;

21
src/ui/designer/QGCParamSlider.cc

@ -3,9 +3,16 @@ @@ -3,9 +3,16 @@
#include "QGCParamSlider.h"
#include "ui_QGCParamSlider.h"
#include "UASInterface.h"
QGCParamSlider::QGCParamSlider(QWidget *parent) :
QGCToolWidgetItem(parent),
QGCToolWidgetItem("Slider", parent),
parameterName(""),
parameterValue(0.0f),
parameterScalingFactor(0.0),
parameterMin(0.0f),
parameterMax(0.0f),
component(0),
ui(new Ui::QGCParamSlider)
{
ui->setupUi(this);
@ -48,6 +55,18 @@ void QGCParamSlider::endEditMode() @@ -48,6 +55,18 @@ void QGCParamSlider::endEditMode()
isInEditMode = false;
}
void QGCParamSlider::sendParameter()
{
if (QGCToolWidgetItem::uas)
{
QGCToolWidgetItem::uas->setParameter(component, parameterName, parameterValue);
}
else
{
qDebug() << __FILE__ << __LINE__ << "NO UAS SET, DOING NOTHING";
}
}
void QGCParamSlider::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);

8
src/ui/designer/QGCParamSlider.h

@ -22,8 +22,16 @@ public: @@ -22,8 +22,16 @@ public:
public slots:
void startEditMode();
void endEditMode();
/** @brief Send the parameter to the MAV */
void sendParameter();
protected:
QString parameterName; ///< Key/Name of the parameter
float parameterValue; ///< Value of the parameter
double parameterScalingFactor; ///< Factor to scale the parameter between slider and true value
float parameterMin;
float parameterMax;
int component; ///< ID of the MAV component to address
void changeEvent(QEvent *e);
private:

2
src/ui/designer/QGCToolWidget.cc

@ -50,7 +50,7 @@ void QGCToolWidget::addUAS(UASInterface* uas) @@ -50,7 +50,7 @@ void QGCToolWidget::addUAS(UASInterface* uas)
void QGCToolWidget::contextMenuEvent (QContextMenuEvent* event)
{
QMenu menu(this);
menu.addAction(addParamAction);
//menu.addAction(addParamAction);
menu.addAction(addButtonAction);
menu.addAction(setTitleAction);
menu.exec(event->globalPos());

18
src/ui/designer/QGCToolWidgetItem.cc

@ -3,16 +3,25 @@ @@ -3,16 +3,25 @@
#include <QMenu>
#include <QContextMenuEvent>
QGCToolWidgetItem::QGCToolWidgetItem(QWidget *parent) :
#include "UASManager.h"
QGCToolWidgetItem::QGCToolWidgetItem(const QString& name, QWidget *parent) :
QWidget(parent),
isInEditMode(false),
qgcToolWidgetItemName(name),
uas(NULL),
_component(-1)
{
startEditAction = new QAction("Edit Slider", this);
startEditAction = new QAction("Edit "+qgcToolWidgetItemName, this);
connect(startEditAction, SIGNAL(triggered()), this, SLOT(startEditMode()));
stopEditAction = new QAction("Finish Editing Slider", this);
connect(stopEditAction, SIGNAL(triggered()), this, SLOT(endEditMode()));
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
// Set first UAS if it exists
setActiveUAS(UASManager::instance()->getActiveUAS());
endEditMode();
}
@ -35,3 +44,8 @@ void QGCToolWidgetItem::contextMenuEvent (QContextMenuEvent* event) @@ -35,3 +44,8 @@ void QGCToolWidgetItem::contextMenuEvent (QContextMenuEvent* event)
}
menu.exec(event->globalPos());
}
void QGCToolWidgetItem::setActiveUAS(UASInterface *uas)
{
this->uas = uas;
}

8
src/ui/designer/QGCToolWidgetItem.h

@ -4,11 +4,13 @@ @@ -4,11 +4,13 @@
#include <QWidget>
#include <QAction>
#include "UASInterface.h"
class QGCToolWidgetItem : public QWidget
{
Q_OBJECT
public:
explicit QGCToolWidgetItem(QWidget *parent = 0);
QGCToolWidgetItem(const QString& name, QWidget *parent = 0);
~QGCToolWidgetItem();
int component() {return _component;}
@ -17,12 +19,14 @@ public slots: @@ -17,12 +19,14 @@ public slots:
virtual void startEditMode() {}
virtual void endEditMode() {}
virtual void setComponent(int comp) {_component = comp;}
void setActiveUAS(UASInterface *uas);
protected:
QAction* startEditAction;
QAction* stopEditAction;
bool isInEditMode;
QString qgcToolWidgetItemName;
UASInterface* uas;
int _component; ///< The MAV component (the process or device ID)
void contextMenuEvent (QContextMenuEvent* event);

3
src/ui/linechart/LinechartPlot.cc

@ -228,7 +228,8 @@ void LinechartPlot::appendData(QString dataname, quint64 ms, double value) @@ -228,7 +228,8 @@ void LinechartPlot::appendData(QString dataname, quint64 ms, double value)
datalock.lock();
/* Check if dataset identifier already exists */
if(!data.contains(dataname)) {
if(!data.contains(dataname))
{
addCurve(dataname);
}

260
src/ui/linechart/LinechartWidget.cc

@ -35,6 +35,7 @@ This file is part of the PIXHAWK project @@ -35,6 +35,7 @@ This file is part of the PIXHAWK project
#include <QGridLayout>
#include <QComboBox>
#include <QToolButton>
#include <QSizePolicy>
#include <QScrollBar>
#include <QLabel>
#include <QMenu>
@ -69,6 +70,7 @@ curveMenu(new QMenu(this)), @@ -69,6 +70,7 @@ curveMenu(new QMenu(this)),
logFile(new QFile()),
logindex(1),
logging(false),
logStartTime(0),
updateTimer(new QTimer())
{
// Add elements defined in Qt Designer
@ -78,47 +80,57 @@ updateTimer(new QTimer()) @@ -78,47 +80,57 @@ updateTimer(new QTimer())
// Add and customize curve list elements (left side)
curvesWidget = new QWidget(ui.curveListWidget);
ui.curveListWidget->setWidget(curvesWidget);
curvesWidgetLayout = new QVBoxLayout(curvesWidget);
curvesWidgetLayout = new QGridLayout(curvesWidget);
curvesWidgetLayout->setMargin(2);
curvesWidgetLayout->setSpacing(4);
curvesWidgetLayout->setSizeConstraint(QLayout::SetMinimumSize);
//curvesWidgetLayout->setSizeConstraint(QSizePolicy::Expanding);
curvesWidgetLayout->setAlignment(Qt::AlignTop);
curvesWidgetLayout->setColumnStretch(0, 0);
curvesWidgetLayout->setColumnStretch(1, 0);
curvesWidgetLayout->setColumnStretch(2, 80);
curvesWidgetLayout->setColumnStretch(3, 50);
curvesWidgetLayout->setColumnStretch(4, 50);
curvesWidgetLayout->setColumnStretch(5, 50);
// horizontalLayout->setColumnStretch(median, 50);
curvesWidgetLayout->setColumnStretch(6, 50);
curvesWidget->setLayout(curvesWidgetLayout);
// Create curve list headings
QWidget* form = new QWidget(this);
QHBoxLayout *horizontalLayout;
QLabel* label;
QLabel* value;
QLabel* mean;
QLabel* variance;
form->setAutoFillBackground(false);
horizontalLayout = new QHBoxLayout(form);
horizontalLayout->setSpacing(5);
horizontalLayout->setMargin(0);
horizontalLayout->setSizeConstraint(QLayout::SetMinimumSize);
//horizontalLayout->addWidget(checkBox);
label = new QLabel(form);
int labelRow = curvesWidgetLayout->rowCount();
curvesWidgetLayout->addWidget(new QLabel(tr("On")), labelRow, 0, 1, 2);
label = new QLabel(this);
label->setText("Name");
horizontalLayout->addWidget(label);
curvesWidgetLayout->addWidget(label, labelRow, 2);
// Value
value = new QLabel(form);
value = new QLabel(this);
value->setText("Val");
horizontalLayout->addWidget(value);
curvesWidgetLayout->addWidget(value, labelRow, 3);
// Unit
label->setText("Unit");
curvesWidgetLayout->addWidget(new QLabel(tr("Unit")), labelRow, 4);
// Mean
mean = new QLabel(form);
mean = new QLabel(this);
mean->setText("Mean");
horizontalLayout->addWidget(mean);
curvesWidgetLayout->addWidget(mean, labelRow, 5);
// Variance
variance = new QLabel(form);
variance = new QLabel(this);
variance->setText("Variance");
horizontalLayout->addWidget(variance);
curvesWidgetLayout->addWidget(form);
curvesWidgetLayout->addWidget(variance, labelRow, 6);
// Add and customize plot elements (right side)
@ -260,14 +272,83 @@ void LinechartWidget::createLayout() @@ -260,14 +272,83 @@ void LinechartWidget::createLayout()
void LinechartWidget::appendData(int uasId, QString curve, double value, quint64 usec)
{
// Order matters here, first append to plot, then update curve list
activePlot->appendData(curve, usec, value);
// Store data
QLabel* label = curveLabels->value(curve, NULL);
// Make sure the curve will be created if it does not yet exist
if(!label)
static const QString unit("-");
if (isVisible())
{
// Order matters here, first append to plot, then update curve list
activePlot->appendData(curve+unit, usec, value);
// Store data
QLabel* label = curveLabels->value(curve+unit, NULL);
// Make sure the curve will be created if it does not yet exist
if(!label)
{
addCurve(curve, unit);
}
}
// Log data
if (logging)
{
if (activePlot->isVisible(curve))
{
if (logStartTime == 0) logStartTime = usec;
qint64 time = usec - logStartTime;
if (time < 0) time = 0;
logFile->write(QString(QString::number(time) + "\t" + QString::number(uasId) + "\t" + curve + "\t" + QString::number(value) + "\n").toLatin1());
logFile->flush();
}
}
}
void LinechartWidget::appendData(int uasId, const QString& curve, const QString& unit, double value, quint64 usec)
{
if (isVisible())
{
// Order matters here, first append to plot, then update curve list
activePlot->appendData(curve+unit, usec, value);
// Store data
QLabel* label = curveLabels->value(curve+unit, NULL);
// Make sure the curve will be created if it does not yet exist
if(!label)
{
qDebug() << "ADDING CURVE IN APPENDDATE DOUBLE";
addCurve(curve, unit);
}
}
// Log data
if (logging)
{
if (activePlot->isVisible(curve+unit))
{
if (logStartTime == 0) logStartTime = usec;
qint64 time = usec - logStartTime;
if (time < 0) time = 0;
logFile->write(QString(QString::number(time) + "\t" + QString::number(uasId) + "\t" + curve + "\t" + QString::number(value) + "\n").toLatin1());
logFile->flush();
}
}
}
void LinechartWidget::appendData(int uasId, const QString& curve, const QString& unit, int value, quint64 usec)
{
if (isVisible())
{
addCurve(curve);
// Order matters here, first append to plot, then update curve list
activePlot->appendData(curve+unit, usec, value);
// Store data
QLabel* label = curveLabels->value(curve+unit, NULL);
// Make sure the curve will be created if it does not yet exist
if(!label)
{
addCurve(curve, unit);
}
// Add int data
intData.insert(curve+unit, value);
}
// Log data
@ -275,16 +356,9 @@ void LinechartWidget::appendData(int uasId, QString curve, double value, quint64 @@ -275,16 +356,9 @@ void LinechartWidget::appendData(int uasId, QString curve, double value, quint64
{
if (activePlot->isVisible(curve))
{
quint64 time = 0;
// Adjust time
if (activePlot->groundTime())
{
time = QGC::groundTimeUsecs() - logStartTime;
}
else
{
time = usec - logStartTime;
}
if (logStartTime == 0) logStartTime = usec;
qint64 time = usec - logStartTime;
if (time < 0) time = 0;
logFile->write(QString(QString::number(time) + "\t" + QString::number(uasId) + "\t" + curve + "\t" + QString::number(value) + "\n").toLatin1());
logFile->flush();
@ -295,11 +369,28 @@ void LinechartWidget::appendData(int uasId, QString curve, double value, quint64 @@ -295,11 +369,28 @@ void LinechartWidget::appendData(int uasId, QString curve, double value, quint64
void LinechartWidget::refresh()
{
QString str;
// Value
QMap<QString, QLabel*>::iterator i;
for (i = curveLabels->begin(); i != curveLabels->end(); ++i)
{
str.sprintf("%+.2f", activePlot->getCurrentValue(i.key()));
double val = activePlot->getCurrentValue(i.key());
int intval = static_cast<int>(val);
if (intval >= 100000 || intval <= -100000)
{
str.sprintf("% 11i", intval);
}
else if (intval >= 10000 || intval <= -10000)
{
str.sprintf("% 11.2f", val);
}
else if (intval >= 1000 || intval <= -1000)
{
str.sprintf("% 11.4f", val);
}
else
{
str.sprintf("% 11.6f", val);
}
// Value
i.value()->setText(str);
}
@ -307,7 +398,19 @@ void LinechartWidget::refresh() @@ -307,7 +398,19 @@ void LinechartWidget::refresh()
QMap<QString, QLabel*>::iterator j;
for (j = curveMeans->begin(); j != curveMeans->end(); ++j)
{
str.sprintf("%+.2f", activePlot->getMean(j.key()));
double val = activePlot->getCurrentValue(j.key());
if (val > 9999 || val < -9999)
{
str.sprintf("% 11.2f", val);
}
else if (val > 99999 || val < -99999)
{
str.sprintf("% 11d", (int)val);
}
else
{
str.sprintf("% 11.6f", val);
}
j.value()->setText(str);
}
// QMap<QString, QLabel*>::iterator k;
@ -321,7 +424,7 @@ void LinechartWidget::refresh() @@ -321,7 +424,7 @@ void LinechartWidget::refresh()
for (l = curveVariances->begin(); l != curveVariances->end(); ++l)
{
// Variance
str.sprintf("%.2e", activePlot->getVariance(l.key()));
str.sprintf("% 9.4e", activePlot->getVariance(l.key()));
l.value()->setText(str);
}
}
@ -381,7 +484,8 @@ void LinechartWidget::startLogging() @@ -381,7 +484,8 @@ void LinechartWidget::startLogging()
if (logFile->open(QIODevice::WriteOnly | QIODevice::Text))
{
logging = true;
logStartTime = QGC::groundTimeUsecs();
logStartTime = 0;
curvesWidget->setEnabled(false);
logindex++;
logButton->setText(tr("Stop logging"));
disconnect(logButton, SIGNAL(clicked()), this, SLOT(startLogging()));
@ -393,12 +497,13 @@ void LinechartWidget::startLogging() @@ -393,12 +497,13 @@ void LinechartWidget::startLogging()
void LinechartWidget::stopLogging()
{
logging = false;
curvesWidget->setEnabled(true);
if (logFile->isOpen())
{
logFile->flush();
logFile->close();
// Postprocess log file
compressor = new LogCompressor(logFile->fileName());
compressor = new LogCompressor(logFile->fileName(), logFile->fileName());
connect(compressor, SIGNAL(finishedFile(QString)), this, SIGNAL(logfileWritten(QString)));
connect(compressor, SIGNAL(logProcessingStatusChanged(QString)), MainWindow::instance(), SLOT(showStatusMessage(QString)));
MainWindow::instance()->showInfoMessage("Logging ended", "QGroundControl is now compressing the logfile in a consistent CVS file. This may take a while, you can continue to use QGroundControl. Status updates appear at the bottom of the window.");
@ -432,47 +537,41 @@ void LinechartWidget::createActions() @@ -432,47 +537,41 @@ void LinechartWidget::createActions()
* @param curve The id-string of the curve
* @see removeCurve()
**/
void LinechartWidget::addCurve(QString curve)
void LinechartWidget::addCurve(const QString& curve, const QString& unit)
{
curvesWidgetLayout->addWidget(createCurveItem(curve));
}
intData.insert(curve+unit, 0);
QWidget* LinechartWidget::createCurveItem(QString curve)
{
LinechartPlot* plot = activePlot;
QWidget* form = new QWidget(this);
QHBoxLayout *horizontalLayout;
// QHBoxLayout *horizontalLayout;
QCheckBox *checkBox;
QLabel* label;
QLabel* value;
QLabel* unitLabel;
QLabel* mean;
QLabel* variance;
form->setAutoFillBackground(false);
horizontalLayout = new QHBoxLayout(form);
horizontalLayout->setSpacing(5);
horizontalLayout->setMargin(0);
horizontalLayout->setSizeConstraint(QLayout::SetMinimumSize);
checkBox = new QCheckBox(form);
int labelRow = curvesWidgetLayout->rowCount();
checkBox = new QCheckBox(this);
checkBox->setCheckable(true);
checkBox->setObjectName(curve);
checkBox->setObjectName(curve+unit);
checkBox->setToolTip(tr("Enable the curve in the graph window"));
checkBox->setWhatsThis(tr("Enable the curve in the graph window"));
horizontalLayout->addWidget(checkBox);
curvesWidgetLayout->addWidget(checkBox, labelRow, 0);
QWidget* colorIcon = new QWidget(form);
QWidget* colorIcon = new QWidget(this);
colorIcon->setMinimumSize(QSize(5, 14));
colorIcon->setMaximumSize(4, 14);
horizontalLayout->addWidget(colorIcon);
curvesWidgetLayout->addWidget(colorIcon, labelRow, 1);
label = new QLabel(form);
horizontalLayout->addWidget(label);
label = new QLabel(this);
curvesWidgetLayout->addWidget(label, labelRow, 2);
//checkBox->setText(QString());
label->setText(curve);
QColor color = plot->getColorForCurve(curve);
QColor color = plot->getColorForCurve(curve+unit);
if(color.isValid()) {
QString colorstyle;
colorstyle = colorstyle.sprintf("QWidget { background-color: #%X%X%X; }", color.red(), color.green(), color.blue());
@ -481,20 +580,30 @@ QWidget* LinechartWidget::createCurveItem(QString curve) @@ -481,20 +580,30 @@ QWidget* LinechartWidget::createCurveItem(QString curve)
}
// Value
value = new QLabel(form);
value = new QLabel(this);
value->setNum(0.00);
value->setStyleSheet(QString("QLabel {font-family:\"Courier\"; font-weight: bold;}"));
value->setToolTip(tr("Current value of ") + curve);
value->setWhatsThis(tr("Current value of ") + curve);
curveLabels->insert(curve, value);
horizontalLayout->addWidget(value);
curveLabels->insert(curve+unit, value);
curvesWidgetLayout->addWidget(value, labelRow, 3);
// Unit
unitLabel = new QLabel(this);
unitLabel->setText(unit);
unitLabel->setStyleSheet(QString("QLabel {color: %1;}").arg("#AAAAAA"));
qDebug() << "UNIT" << unit;
unitLabel->setToolTip(tr("Unit of ") + curve);
unitLabel->setWhatsThis(tr("Unit of ") + curve);
curvesWidgetLayout->addWidget(unitLabel, labelRow, 4);
// Mean
mean = new QLabel(form);
mean = new QLabel(this);
mean->setNum(0.00);
mean->setToolTip(tr("Arithmetic mean of ") + curve);
mean->setWhatsThis(tr("Arithmetic mean of ") + curve);
curveMeans->insert(curve, mean);
horizontalLayout->addWidget(mean);
curveMeans->insert(curve+unit, mean);
curvesWidgetLayout->addWidget(mean, labelRow, 5);
// // Median
// median = new QLabel(form);
@ -503,12 +612,12 @@ QWidget* LinechartWidget::createCurveItem(QString curve) @@ -503,12 +612,12 @@ QWidget* LinechartWidget::createCurveItem(QString curve)
// horizontalLayout->addWidget(median);
// Variance
variance = new QLabel(form);
variance = new QLabel(this);
variance->setNum(0.00);
variance->setToolTip(tr("Variance of ") + curve);
variance->setWhatsThis(tr("Variance of ") + curve);
curveVariances->insert(curve, variance);
horizontalLayout->addWidget(variance);
curveVariances->insert(curve+unit, variance);
curvesWidgetLayout->addWidget(variance, labelRow, 6);
/* Color picker
QColor color = QColorDialog::getColor(Qt::green, this);
@ -520,13 +629,6 @@ QWidget* LinechartWidget::createCurveItem(QString curve) @@ -520,13 +629,6 @@ QWidget* LinechartWidget::createCurveItem(QString curve)
*/
// Set stretch factors so that the label gets the whole space
horizontalLayout->setStretchFactor(checkBox, 0);
horizontalLayout->setStretchFactor(colorIcon, 0);
horizontalLayout->setStretchFactor(label, 80);
horizontalLayout->setStretchFactor(value, 50);
horizontalLayout->setStretchFactor(mean, 50);
// horizontalLayout->setStretchFactor(median, 50);
horizontalLayout->setStretchFactor(variance, 50);
// Connect actions
QObject::connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(takeButtonClick(bool)));
@ -534,9 +636,7 @@ QWidget* LinechartWidget::createCurveItem(QString curve) @@ -534,9 +636,7 @@ QWidget* LinechartWidget::createCurveItem(QString curve)
// Set UI components to initial state
checkBox->setChecked(false);
plot->setVisible(curve, false);
return form;
plot->setVisible(curve+unit, false);
}
/**

14
src/ui/linechart/LinechartWidget.h

@ -70,9 +70,14 @@ public: @@ -70,9 +70,14 @@ public:
static const int MAX_TIME_SCROLLBAR_VALUE = 16383; ///< The maximum scrollbar value
public slots:
void addCurve(QString curve);
void addCurve(const QString& curve, const QString& unit);
void removeCurve(QString curve);
/** @brief Append data without unit */
void appendData(int uasId, QString curve, double data, quint64 usec);
/** @brief Append data with unit */
void appendData(int uasId, const QString& curve, const QString& unit, double value, quint64 usec);
/** @brief Append data as int with unit */
void appendData(int uasId, const QString& curve, const QString& unit, int value, quint64 usec);
void takeButtonClick(bool checked);
void setPlotWindowPosition(int scrollBarValue);
void setPlotWindowPosition(quint64 position);
@ -95,7 +100,7 @@ protected: @@ -95,7 +100,7 @@ protected:
void addCurveToList(QString curve);
void removeCurveFromList(QString curve);
QToolButton* createButton(QWidget* parent);
QWidget* createCurveItem(QString curve);
void createCurveItem(QString curve);
void createLayout();
int sysid; ///< ID of the unmanned system this plot belongs to
@ -110,9 +115,10 @@ protected: @@ -110,9 +115,10 @@ protected:
QMap<QString, QLabel*>* curveMeans; ///< References to the curve means
QMap<QString, QLabel*>* curveMedians; ///< References to the curve medians
QMap<QString, QLabel*>* curveVariances; ///< References to the curve variances
QMap<QString, int> intData; ///< Current values for integer-valued curves
QWidget* curvesWidget; ///< The QWidget containing the curve selection button
QVBoxLayout* curvesWidgetLayout; ///< The layout for the curvesWidget QWidget
QGridLayout* curvesWidgetLayout; ///< The layout for the curvesWidget QWidget
QScrollBar* scrollbar; ///< The plot window scroll bar
QSpinBox* averageSpinBox; ///< Spin box to setup average window filter size
@ -130,9 +136,9 @@ protected: @@ -130,9 +136,9 @@ protected:
QFile* logFile;
unsigned int logindex;
bool logging;
quint64 logStartTime;
QTimer* updateTimer;
LogCompressor* compressor;
quint64 logStartTime;
static const int MAX_CURVE_MENUITEM_NUMBER = 8;
static const int PAGESTEP_TIME_SCROLLBAR_VALUE = (MAX_TIME_SCROLLBAR_VALUE - MIN_TIME_SCROLLBAR_VALUE) / 10;

7
src/ui/linechart/Linecharts.cc

@ -96,7 +96,12 @@ void Linecharts::addSystem(UASInterface* uas) @@ -96,7 +96,12 @@ void Linecharts::addSystem(UASInterface* uas)
addWidget(widget);
plots.insert(uas->getUASID(), widget);
#ifndef MAVLINK_ENABLED_SLUGS
connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), widget, SLOT(appendData(int,QString,double,quint64)));
// Values without unit
//connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), widget, SLOT(appendData(int,QString,double,quint64)));
// Values with unit as double
connect(uas, SIGNAL(valueChanged(int,QString,QString,double,quint64)), widget, SLOT(appendData(int,QString,QString,double,quint64)));
// Values with unit as integer
connect(uas, SIGNAL(valueChanged(int,QString,QString,double,quint64)), widget, SLOT(appendData(int,QString,QString,double,quint64)));
#endif
connect(widget, SIGNAL(logfileWritten(QString)), this, SIGNAL(logfileWritten(QString)));
// Set system active if this is the only system

8
src/ui/uas/UASControlWidget.cc

@ -114,18 +114,18 @@ void UASControlWidget::setUAS(UASInterface* uas) @@ -114,18 +114,18 @@ void UASControlWidget::setUAS(UASInterface* uas)
// Check if additional controls should be loaded
UAS* mav = dynamic_cast<UAS*>(uas);
if (mav)
{
{
QPushButton* startRecButton = new QPushButton(tr("Record"));
connect(startRecButton, SIGNAL(clicked()), mav, SLOT(startDataRecording()));
ui.gridLayout->addWidget(startRecButton, 10, 0, 0, 2);
ui.gridLayout->addWidget(startRecButton, 7, 1);
QPushButton* pauseRecButton = new QPushButton(tr("Pause"));
connect(pauseRecButton, SIGNAL(clicked()), mav, SLOT(pauseDataRecording()));
ui.gridLayout->addWidget(pauseRecButton, 10, 2, 0, 2);
ui.gridLayout->addWidget(pauseRecButton, 7, 3);
QPushButton* stopRecButton = new QPushButton(tr("Stop"));
connect(stopRecButton, SIGNAL(clicked()), mav, SLOT(stopDataRecording()));
ui.gridLayout->addWidget(stopRecButton, 10, 4, 0, 2);
ui.gridLayout->addWidget(stopRecButton, 7, 4);
}

Loading…
Cancel
Save