diff --git a/images/style-outdoor.css b/images/style-outdoor.css new file mode 100644 index 0000000..d765aa3 --- /dev/null +++ b/images/style-outdoor.css @@ -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; +} diff --git a/qgroundcontrol.pri b/qgroundcontrol.pri index b124c23..f972573 100644 --- a/qgroundcontrol.pri +++ b/qgroundcontrol.pri @@ -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 diff --git a/src/LogCompressor.cc b/src/LogCompressor.cc index 1085354..84acff2 100644 --- a/src/LogCompressor.cc +++ b/src/LogCompressor.cc @@ -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() // 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() } } - 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() // 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 diff --git a/src/QGC.cc b/src/QGC.cc index 14da6ac..087c488 100644 --- a/src/QGC.cc +++ b/src/QGC.cc @@ -34,4 +34,9 @@ quint64 groundTimeUsecs() return static_cast(microseconds + (time.time().msec()*1000)); } +int applicationVersion() +{ + return APPLICATIONVERSION; +} + } diff --git a/src/QGC.h b/src/QGC.h index e21a17d..44305dd 100644 --- a/src/QGC.h +++ b/src/QGC.h @@ -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 diff --git a/src/comm/MAVLinkSimulationLink.cc b/src/comm/MAVLinkSimulationLink.cc index d697dab..a8043d8 100644 --- a/src/comm/MAVLinkSimulationLink.cc +++ b/src/comm/MAVLinkSimulationLink.cc @@ -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() 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() // 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() 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 diff --git a/src/comm/MAVLinkXMLParser.cc b/src/comm/MAVLinkXMLParser.cc index cca4466..34b830f 100644 --- a/src/comm/MAVLinkXMLParser.cc +++ b/src/comm/MAVLinkXMLParser.cc @@ -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)); diff --git a/src/uas/PxQuadMAV.cc b/src/uas/PxQuadMAV.cc index bde4e9e..ff06c5c 100644 --- a/src/uas/PxQuadMAV.cc +++ b/src/uas/PxQuadMAV.cc @@ -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) 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) 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) 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: diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 3988225..867e8f3 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -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) 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(raw.xgyro), time); - emit valueChanged(uasId, "Gyro Theta", static_cast(raw.ygyro), time); - emit valueChanged(uasId, "Gyro Psi", static_cast(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(raw.xgyro), time); + emit valueChanged(uasId, "gyro pitch", "raw", static_cast(raw.ygyro), time); + emit valueChanged(uasId, "gyro yaw", "raw", static_cast(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) // 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) 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) 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) // 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) 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) { 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) } 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) 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) 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) 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 diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index 0b00419..a35dd96 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -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); diff --git a/src/ui/DebugConsole.cc b/src/ui/DebugConsole.cc index 6da73bf..f5af15c 100644 --- a/src/ui/DebugConsole.cc +++ b/src/ui/DebugConsole.cc @@ -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("%2").arg(QGC::colorRed.name(), tr("Could not connect link %1 ! Please check link hardware.").arg(currLink->getName()))); - } + currLink->connect(); } } } diff --git a/src/ui/HDDisplay.cc b/src/ui/HDDisplay.cc index 2d73917..eb34a5a 100644 --- a/src/ui/HDDisplay.cc +++ b/src/ui/HDDisplay.cc @@ -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() acceptList->removeAt(index); minValues.remove(item); maxValues.remove(item); + symmetric.remove(item); + adjustGaugeAspectRatio(); } } @@ -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() 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 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 goodRange, QPair 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 goodRange, QPair 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 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) diff --git a/src/ui/HDDisplay.h b/src/ui/HDDisplay.h index 02de21d..4dc24a6 100644 --- a/src/ui/HDDisplay.h +++ b/src/ui/HDDisplay.h @@ -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 goodRange, QPair 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 goodRange, QPair 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: QMap lastUpdate; ///< The last update time for this variable QMap minValues; ///< The minimum value this variable is assumed to have QMap maxValues; ///< The maximum value this variable is assumed to have + QMap symmetric; ///< Draw the gauge / dial symmetric bool = yes QMap > goodRanges; ///< The range of good values QMap > critRanges; ///< The range of critical values double scalingFactor; ///< Factor used to scale all absolute values to screen coordinates diff --git a/src/ui/HUD.cc b/src/ui/HUD.cc index 2d57262..9a57336 100644 --- a/src/ui/HUD.cc +++ b/src/ui/HUD.cc @@ -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) 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 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() // 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() 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() 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) 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) diff --git a/src/ui/HUD.h b/src/ui/HUD.h index 70e5572..1797b77 100644 --- a/src/ui/HUD.h +++ b/src/ui/HUD.h @@ -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: float roll; float pitch; float yaw; + float yawDiff; void paintEvent(QPaintEvent *event); }; diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 3fba2a6..88e9aa6 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -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): // 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): 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): 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() } +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() QAction* temp = qobject_cast(sender()); int tool = temp->data().toInt(); - if (temp && dockWidgets[tool]) { if (temp->isChecked()) @@ -565,9 +639,6 @@ void MainWindow::showToolWidget() { removeDockWidget(qobject_cast(dockWidgets[tool])); } - QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast(tool), currentView); - settings.setValue(chKey,temp->isChecked()); - settings.sync(); } } @@ -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 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() void MainWindow::arrangeCommonCenterStack() { centerStack = new QStackedWidget(this); + centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); if (!centerStack) return; @@ -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() } 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() 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() 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() 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() 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) 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) } } - // 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) 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) */ 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(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() 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() // 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() if (headUpDockWidget) { HUD* tmpHud = dynamic_cast( 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 (settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()), hsiDockWidget); headUpDockWidget->show(); - } else { + } + else + { headUpDockWidget->hide(); } } @@ -1347,52 +1483,12 @@ void MainWindow::presentView() // HORIZONTAL SITUATION INDICATOR showTheWidget(MENU_HSI, currentView); - // if (hsiDockWidget) - // { - // HSIDisplay* hsi = dynamic_cast( hsiDockWidget->widget() ); - // if (hsi){ - // if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HSI,currentView)).toBool()){ - // addDockWidget(static_cast (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(headDown1DockWidget->widget()); - // if (hdd) { - // if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HDD_1,currentView)).toBool()) { - // addDockWidget(static_cast (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(headDown2DockWidget->widget()); - // if (hdd){ - // if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HDD_2,currentView)).toBool()){ - // addDockWidget(static_cast (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 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 } } -void MainWindow::loadWidgets() -{ - loadOperatorView(); - //loadMAVLinkView(); - //loadPilotView(); -} - void MainWindow::loadDataView(QString fileName) { - // DATAPLOT - if (dataplotWidget) - { - QStackedWidget *centerStack = dynamic_cast(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(centralWidget()); - if (centerStack) - { - //map3DWidget->setActive(true); - centerStack->setCurrentWidget(_3DMapWidget); - } - } -#endif -} + // Unload line chart + QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast(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(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(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(centralWidget()); - if (centerStack) - { - //map3DWidget->setActive(true); - centerStack->setCurrentWidget(_3DWidget); - } + dataplotWidget->loadFile(fileName); } -#endif +// QStackedWidget *centerStack = dynamic_cast(centralWidget()); +// if (centerStack) +// { +// centerStack->setCurrentWidget(dataplotWidget); +// dataplotWidget->loadFile(fileName); +// } +// } } + diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 1d9e61d..43a0230 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -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: Ui::MainWindow ui; QString buildMenuKey (SETTINGS_SECTIONS section , TOOLS_WIDGET_NAMES tool, VIEW_SECTIONS view); + QString getWindowStateKey(); + QString getWindowGeometryKey(); }; diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index 5eafe8d..2b904d9 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -50,6 +50,7 @@ + @@ -100,7 +101,6 @@ - @@ -179,33 +179,6 @@ Open UAS Preferences - - - - :/images/apps/utilities-system-monitor.svg:/images/apps/utilities-system-monitor.svg - - - Show engineer view - - - - - - :/images/status/weather-overcast.svg:/images/status/weather-overcast.svg - - - Show pilot view - - - - - - :/images/categories/applications-internet.svg:/images/categories/applications-internet.svg - - - Reload visual style - - @@ -218,30 +191,6 @@ true - - - - :/images/status/network-wireless-encrypted.svg:/images/status/network-wireless-encrypted.svg - - - Show operator view - - - Shop the 2D map and system status - - - - - - :/images/categories/preferences-system.svg:/images/categories/preferences-system.svg - - - Show 3D Local View - - - Show 3D view - - true @@ -257,87 +206,6 @@ Simulate one vehicle to test and evaluate this application - - - - :/images/status/network-transmit-receive.svg:/images/status/network-transmit-receive.svg - - - Show full view - - - - - - :/images/devices/network-wired.svg:/images/devices/network-wired.svg - - - Show MAVLink view - - - - - - :/images/categories/applications-internet.svg:/images/categories/applications-internet.svg - - - Online documentation - - - - - - :/images/apps/utilities-system-monitor.svg:/images/apps/utilities-system-monitor.svg - - - Show data analysis view - - - - - - :/images/status/software-update-available.svg:/images/status/software-update-available.svg - - - Project Roadmap - - - - - - :/images/categories/preferences-system.svg:/images/categories/preferences-system.svg - - - Credits / Developers - - - - - - :/images/categories/applications-internet.svg:/images/categories/applications-internet.svg - - - Show 2D Map View - - - - - - :/images/categories/applications-internet.svg:/images/categories/applications-internet.svg - - - Show 3D Global View - - - - - - :/images/mapproviders/googleearth.svg:/images/mapproviders/googleearth.svg - - - Google Earth View - - @@ -387,6 +255,9 @@ + + true + :/images/status/weather-overcast.svg:/images/status/weather-overcast.svg @@ -396,6 +267,9 @@ + + true + :/images/apps/utilities-system-monitor.svg:/images/apps/utilities-system-monitor.svg @@ -405,6 +279,9 @@ + + true + :/images/devices/network-wired.svg:/images/devices/network-wired.svg @@ -419,10 +296,13 @@ :/images/categories/applications-internet.svg:/images/categories/applications-internet.svg - Reload Style + Reload Stylesheet + + true + :/images/status/network-wireless-encrypted.svg:/images/status/network-wireless-encrypted.svg diff --git a/src/ui/QGCRemoteControlView.cc b/src/ui/QGCRemoteControlView.cc index a00c83f..519598a 100644 --- a/src/ui/QGCRemoteControlView.cc +++ b/src/ui/QGCRemoteControlView.cc @@ -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 diff --git a/src/ui/UASControl.ui b/src/ui/UASControl.ui index 1dfe786..d1a6f6c 100644 --- a/src/ui/UASControl.ui +++ b/src/ui/UASControl.ui @@ -6,8 +6,8 @@ 0 0 - 210 - 141 + 222 + 172 @@ -18,14 +18,23 @@ - 210 - 130 + 222 + 172 + + + + + 267 + 194 Form - + + Control widget to send basic control actions to the micro air vehicle + + @@ -93,7 +102,7 @@ - Liftoff + Start diff --git a/src/ui/designer/QGCActionButton.cc b/src/ui/designer/QGCActionButton.cc index 3bb9671..461e3a9 100644 --- a/src/ui/designer/QGCActionButton.cc +++ b/src/ui/designer/QGCActionButton.cc @@ -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() void QGCActionButton::sendAction() { - if (uas) + if (QGCToolWidgetItem::uas) { MAV_ACTION action = static_cast( 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() ui->editActionComboBox->show(); ui->editActionsRefreshButton->show(); ui->editFinishButton->show(); + ui->editNameLabel->show(); + ui->editButtonName->show(); isInEditMode = true; } @@ -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; } diff --git a/src/ui/designer/QGCActionButton.h b/src/ui/designer/QGCActionButton.h index 9f21b73..b018514 100644 --- a/src/ui/designer/QGCActionButton.h +++ b/src/ui/designer/QGCActionButton.h @@ -23,9 +23,6 @@ public slots: void startEditMode(); void endEditMode(); -private slots: - void setActiveUAS(UASInterface* uas); - private: Ui::QGCActionButton *ui; UASInterface* uas; diff --git a/src/ui/designer/QGCParamSlider.cc b/src/ui/designer/QGCParamSlider.cc index 3b8435e..e76c69a 100644 --- a/src/ui/designer/QGCParamSlider.cc +++ b/src/ui/designer/QGCParamSlider.cc @@ -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() 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); diff --git a/src/ui/designer/QGCParamSlider.h b/src/ui/designer/QGCParamSlider.h index dadc288..97e0e8e 100644 --- a/src/ui/designer/QGCParamSlider.h +++ b/src/ui/designer/QGCParamSlider.h @@ -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: diff --git a/src/ui/designer/QGCToolWidget.cc b/src/ui/designer/QGCToolWidget.cc index ff52d6a..4a3992b 100644 --- a/src/ui/designer/QGCToolWidget.cc +++ b/src/ui/designer/QGCToolWidget.cc @@ -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()); diff --git a/src/ui/designer/QGCToolWidgetItem.cc b/src/ui/designer/QGCToolWidgetItem.cc index b1f9559..e66ab0b 100644 --- a/src/ui/designer/QGCToolWidgetItem.cc +++ b/src/ui/designer/QGCToolWidgetItem.cc @@ -3,16 +3,25 @@ #include #include -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) } menu.exec(event->globalPos()); } + +void QGCToolWidgetItem::setActiveUAS(UASInterface *uas) +{ + this->uas = uas; +} diff --git a/src/ui/designer/QGCToolWidgetItem.h b/src/ui/designer/QGCToolWidgetItem.h index 2577f43..a3ee5b6 100644 --- a/src/ui/designer/QGCToolWidgetItem.h +++ b/src/ui/designer/QGCToolWidgetItem.h @@ -4,11 +4,13 @@ #include #include +#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: 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); diff --git a/src/ui/linechart/LinechartPlot.cc b/src/ui/linechart/LinechartPlot.cc index 606c3bd..85af32f 100644 --- a/src/ui/linechart/LinechartPlot.cc +++ b/src/ui/linechart/LinechartPlot.cc @@ -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); } diff --git a/src/ui/linechart/LinechartWidget.cc b/src/ui/linechart/LinechartWidget.cc index 395fe36..6e157ff 100644 --- a/src/ui/linechart/LinechartWidget.cc +++ b/src/ui/linechart/LinechartWidget.cc @@ -35,6 +35,7 @@ This file is part of the PIXHAWK project #include #include #include +#include #include #include #include @@ -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()) // 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() 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 { 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 void LinechartWidget::refresh() { QString str; - + // Value QMap::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(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() QMap::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::iterator k; @@ -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() 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() 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() * @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) } // 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) // 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) */ // 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) // Set UI components to initial state checkBox->setChecked(false); - plot->setVisible(curve, false); - - return form; + plot->setVisible(curve+unit, false); } /** diff --git a/src/ui/linechart/LinechartWidget.h b/src/ui/linechart/LinechartWidget.h index dbffd69..af76a4b 100644 --- a/src/ui/linechart/LinechartWidget.h +++ b/src/ui/linechart/LinechartWidget.h @@ -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: 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: QMap* curveMeans; ///< References to the curve means QMap* curveMedians; ///< References to the curve medians QMap* curveVariances; ///< References to the curve variances + QMap 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: 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; diff --git a/src/ui/linechart/Linecharts.cc b/src/ui/linechart/Linecharts.cc index aba663f..6fc3665 100644 --- a/src/ui/linechart/Linecharts.cc +++ b/src/ui/linechart/Linecharts.cc @@ -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 diff --git a/src/ui/uas/UASControlWidget.cc b/src/ui/uas/UASControlWidget.cc index 88dd3dd..842c150 100644 --- a/src/ui/uas/UASControlWidget.cc +++ b/src/ui/uas/UASControlWidget.cc @@ -114,18 +114,18 @@ void UASControlWidget::setUAS(UASInterface* uas) // Check if additional controls should be loaded UAS* mav = dynamic_cast(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); }