diff --git a/files/flightgear/Protocol/qgroundcontrol-fixed-wing.xml b/files/flightgear/Protocol/qgroundcontrol-fixed-wing.xml index 94a60ded590e9c6d832220ba3c9639265702c04c..5fe0ad2b0c7832f49055f15962e6837604fe040f 100644 --- a/files/flightgear/Protocol/qgroundcontrol-fixed-wing.xml +++ b/files/flightgear/Protocol/qgroundcontrol-fixed-wing.xml @@ -141,6 +141,49 @@ /velocities/airspeed-kt 0.514444444444444 + + + airspeed-indicated-mps + float + %.8f + /instrumentation/indicated-speed-kt + 0.514444444444444 + + + + + Magnetic Variation (rad) + float + %.8f + /environment/magnetic-variation-deg + 0.01745329251994329576 + + + + Magnetic Dip (rad) + float + %.8f + /environment/magnetic-dip-deg + 0.01745329251994329576 + + + + + Temperature (deg C) + float + %.8f + /environment/temperature-degc + 1 + + + + + Pressure (hPa) + float + %.8f + /environment/pressure-inhg + 33.86389 + @@ -184,4 +227,4 @@ - \ No newline at end of file + diff --git a/src/comm/QGCFlightGearLink.cc b/src/comm/QGCFlightGearLink.cc index 61341b048839ba72b215c3a52f32b31a3cf27ddb..d8bc240ee37a962a29466bd2c310abf368004dd0 100644 --- a/src/comm/QGCFlightGearLink.cc +++ b/src/comm/QGCFlightGearLink.cc @@ -26,6 +26,7 @@ This file is part of the QGROUNDCONTROL project * @brief Definition of UDP connection (server) for unmanned vehicles * @see Flightgear Manual http://mapserver.flightgear.org/getstart.pdf * @author Lorenz Meier + * @author Thomas Gubler * */ @@ -44,7 +45,8 @@ QGCFlightGearLink::QGCFlightGearLink(UASInterface* mav, QString startupArguments process(NULL), terraSync(NULL), flightGearVersion(0), - startupArguments(startupArguments) + startupArguments(startupArguments), + _sensorHilEnabled(true) { this->host = host; this->port = port+mav->getUASID(); @@ -172,6 +174,7 @@ void QGCFlightGearLink::updateControls(uint64_t time, float rollAilerons, float QString state("%1\t%2\t%3\t%4\t%5\n"); state = state.arg(rollAilerons).arg(pitchElevator).arg(yawRudder).arg(true).arg(throttle); writeBytes(state.toAscii().constData(), state.length()); +// qDebug() << "updated controls" << rollAilerons << pitchElevator << yawRudder << throttle; } else { @@ -227,49 +230,133 @@ void QGCFlightGearLink::readBytes() // Print string QString state(b); - //qDebug() << "FG LINK GOT:" << state; +// qDebug() << "FG LINK GOT:" << state; QStringList values = state.split("\t"); // Check length - if (values.size() != 17) + if (values.size() != 22) { - qDebug() << "RETURN LENGTH MISMATCHING EXPECTED" << 17 << "BUT GOT" << values.size(); + qDebug() << "RETURN LENGTH MISMATCHING EXPECTED" << 22 << "BUT GOT" << values.size(); qDebug() << state; return; } // Parse string float roll, pitch, yaw, rollspeed, pitchspeed, yawspeed; - double lat, lon, alt; + double lat, lon, alt; + float ind_airspeed; + float true_airspeed; + float vx, vy, vz, xacc, yacc, zacc; + float diff_pressure; + float temperature; + float abs_pressure; + float mag_variation, mag_dip, xmag_ned, ymag_ned, zmag_ned, xmag_body, ymag_body, zmag_body; - // XXX add - float ind_airspeed = 0.0f; - float true_airspeed = 0.0f; - double vx, vy, vz, xacc, yacc, zacc; lat = values.at(1).toDouble(); lon = values.at(2).toDouble(); alt = values.at(3).toDouble(); - roll = values.at(4).toDouble(); - pitch = values.at(5).toDouble(); - yaw = values.at(6).toDouble(); - rollspeed = values.at(7).toDouble(); - pitchspeed = values.at(8).toDouble(); - yawspeed = values.at(9).toDouble(); + roll = values.at(4).toFloat(); + pitch = values.at(5).toFloat(); + yaw = values.at(6).toFloat(); + rollspeed = values.at(7).toFloat(); + pitchspeed = values.at(8).toFloat(); + yawspeed = values.at(9).toFloat(); - xacc = values.at(10).toDouble(); - yacc = values.at(11).toDouble(); - zacc = values.at(12).toDouble(); + xacc = values.at(10).toFloat(); + yacc = values.at(11).toFloat(); + zacc = values.at(12).toFloat(); - vx = values.at(13).toDouble(); - vy = values.at(14).toDouble(); - vz = values.at(15).toDouble(); + vx = values.at(13).toFloat(); + vy = values.at(14).toFloat(); + vz = values.at(15).toFloat(); + + true_airspeed = values.at(16).toFloat(); + ind_airspeed = values.at(17).toFloat(); + + mag_variation = values.at(18).toFloat(); + mag_dip = values.at(19).toFloat(); + + temperature = values.at(20).toFloat(); + abs_pressure = values.at(21).toFloat(); // Send updated state - emit hilStateChanged(QGC::groundTimeUsecs(), roll, pitch, yaw, rollspeed, + //qDebug() << "sensorHilEnabled: " << sensorHilEnabled; + if (_sensorHilEnabled) + { + quint16 fields_changed = 0xFFF; //set all 12 used bits + + //calculate differential pressure + const float air_gas_constant = 287.1f; // J/(kg * K) + const float absolute_null_celsius = -273.15f; // °C + float density = abs_pressure / (air_gas_constant * (temperature - absolute_null_celsius)); + diff_pressure = true_airspeed * true_airspeed * density / 2.0f; + + float pressure_alt = alt; + + xmag_ned = cosf(mag_variation); + ymag_ned = sinf(mag_variation); + zmag_ned = sinf(mag_dip); + float tempMagLength = sqrtf(xmag_ned*xmag_ned + ymag_ned*ymag_ned + zmag_ned*zmag_ned); + xmag_ned = xmag_ned / tempMagLength; + ymag_ned = ymag_ned / tempMagLength; + zmag_ned = zmag_ned / tempMagLength; + + //transform magnetic measurement to body frame coordinates + double cosPhi = cos(roll); + double sinPhi = sin(roll); + double cosThe = cos(pitch); + double sinThe = sin(pitch); + double cosPsi = cos(yaw); + double sinPsi = sin(yaw); + + float R_B_N[3][3]; + + R_B_N[0][0] = cosThe * cosPsi; + R_B_N[0][1] = -cosPhi * sinPsi + sinPhi * sinThe * cosPsi; + R_B_N[0][2] = sinPhi * sinPsi + cosPhi * sinThe * cosPsi; + + R_B_N[1][0] = cosThe * sinPsi; + R_B_N[1][1] = cosPhi * cosPsi + sinPhi * sinThe * sinPsi; + R_B_N[1][2] = -sinPhi * cosPsi + cosPhi * sinThe * sinPsi; + + R_B_N[2][0] = -sinThe; + R_B_N[2][1] = sinPhi * cosThe; + R_B_N[2][2] = cosPhi * cosThe; + + Eigen::Matrix3f R_B_N_M = Eigen::Map((float*)R_B_N).eval(); + + Eigen::Vector3f mag_ned(xmag_ned, ymag_ned, zmag_ned); + + Eigen::Vector3f mag_body = R_B_N_M * mag_ned; + + xmag_body = mag_body(0); + ymag_body = mag_body(1); + zmag_body = mag_body(2); + + emit sensorHilRawImuChanged(QGC::groundTimeUsecs(), xacc, yacc, zacc, rollspeed, pitchspeed, yawspeed, + xmag_body, ymag_body, zmag_body, abs_pressure, diff_pressure, pressure_alt, temperature, fields_changed); + +// qDebug() << "sensorHilRawImuChanged " << xacc << yacc << zacc << rollspeed << pitchspeed << yawspeed << xmag << ymag << zmag << abs_pressure << diff_pressure << pressure_alt << temperature; + int gps_fix_type = 3; + float eph = 0.3; + float epv = 0.6; + float vel = sqrt(vx*vx + vy*vy + vz*vz); + float cog = yaw; + int satellites = 8; + + emit sensorHilGpsChanged(QGC::groundTimeUsecs(), lat, lon, alt, gps_fix_type, eph, epv, vel, vx, vy, vz, cog, satellites); + +// qDebug() << "sensorHilGpsChanged " << lat << lon << alt << vel; + } else { + emit hilStateChanged(QGC::groundTimeUsecs(), roll, pitch, yaw, rollspeed, pitchspeed, yawspeed, lat, lon, alt, - vx, vy, vz, ind_airspeed, true_airspeed, xacc, yacc, zacc); + vx, vy, vz, + ind_airspeed, true_airspeed, + xacc, yacc, zacc); + //qDebug() << "hilStateChanged " << (int32_t)lat << (int32_t)lon << (int32_t)alt; + } // // Echo data for debugging purposes // std::cerr << __FILE__ << __LINE__ << "Received datagram:" << std::endl; @@ -303,7 +390,9 @@ bool QGCFlightGearLink::disconnectSimulation() disconnect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); disconnect(mav, SIGNAL(hilControlsChanged(uint64_t, float, float, float, float, uint8_t, uint8_t)), this, SLOT(updateControls(uint64_t,float,float,float,float,uint8_t,uint8_t))); - disconnect(this, SIGNAL(hilStateChanged(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float)), mav, SLOT(sendHilState(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float))); + disconnect(this, SIGNAL(hilStateChanged(quint64, float, float, float, float,float, float, double, double, double, float, float, float, float, float, float, float, float)), mav, SLOT(sendHilState(quint64, float, float, float, float,float, float, double, double, double, float, float, float, float, float, float, float, float))); + disconnect(this, SIGNAL(sensorHilGpsChanged(quint64, double, double, double, int, float, float, float, float, float, float, float, int)), mav, SLOT(sendHilGps(quint64, double, double, double, int, float, float, float, float, float, float, float, int))); + disconnect(this, SIGNAL(sensorHilRawImuChanged(quint64,float,float,float,float,float,float,float,float,float,float,float,float,float,quint32)), mav, SLOT(sendHilSensors(quint64,float,float,float,float,float,float,float,float,float,float,float,float,float,quint32))); if (process) { @@ -350,8 +439,9 @@ bool QGCFlightGearLink::connectSimulation() terraSync = new QProcess(this); connect(mav, SIGNAL(hilControlsChanged(uint64_t, float, float, float, float, uint8_t, uint8_t)), this, SLOT(updateControls(uint64_t,float,float,float,float,uint8_t,uint8_t))); - connect(this, SIGNAL(hilStateChanged(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float)), mav, SLOT(sendHilState(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float))); - + connect(this, SIGNAL(hilStateChanged(quint64, float, float, float, float,float, float, double, double, double, float, float, float, float, float, float, float, float)), mav, SLOT(sendHilState(quint64, float, float, float, float,float, float, double, double, double, float, float, float, float, float, float, float, float))); + connect(this, SIGNAL(sensorHilGpsChanged(quint64, double, double, double, int, float, float, float, float, float, float, float, int)), mav, SLOT(sendHilGps(quint64, double, double, double, int, float, float, float, float, float, float, float, int))); + connect(this, SIGNAL(sensorHilRawImuChanged(quint64,float,float,float,float,float,float,float,float,float,float,float,float,float,quint32)), mav, SLOT(sendHilSensors(quint64,float,float,float,float,float,float,float,float,float,float,float,float,float,quint32))); UAS* uas = dynamic_cast(mav); if (uas) diff --git a/src/comm/QGCFlightGearLink.h b/src/comm/QGCFlightGearLink.h index 9bdda2e5d53c32b6aa635a321675f2c0a408afe2..d043d3c63ba9c9ab60b186b3c0a7a633fe82f747 100644 --- a/src/comm/QGCFlightGearLink.h +++ b/src/comm/QGCFlightGearLink.h @@ -83,6 +83,10 @@ public: return _sensorHilEnabled; } + void sensorHilEnabled(bool sensorHilEnabled) { + _sensorHilEnabled = sensorHilEnabled; + } + void run(); public slots: diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 1c727cd5bbc855c413b8c156ad00b89342972e1e..94d73f1edc6615f267852253216e457fce986ac6 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -2930,7 +2930,7 @@ bool UAS::emergencyKILL() /** * If enabled, connect the flight gear link. */ -void UAS::enableHilFlightGear(bool enable, QString options) +void UAS::enableHilFlightGear(bool enable, QString options, bool sensorHil) { QGCFlightGearLink* link = dynamic_cast(simulation); if (!link || !simulation) { @@ -2944,6 +2944,7 @@ void UAS::enableHilFlightGear(bool enable, QString options) // Connect Flight Gear Link link = dynamic_cast(simulation); link->setStartupArguments(options); + link->sensorHilEnabled(sensorHil); if (enable) { startHil(); diff --git a/src/uas/UAS.h b/src/uas/UAS.h index 8a60d343ea7d0de0a6e46552f2ab69265216057b..e30946a67cfffbef2c173bbea7f9dfe651241ffa 100644 --- a/src/uas/UAS.h +++ b/src/uas/UAS.h @@ -730,7 +730,7 @@ public slots: void go(); /** @brief Enable / disable HIL */ - void enableHilFlightGear(bool enable, QString options); + void enableHilFlightGear(bool enable, QString options, bool sensorHil); void enableHilJSBSim(bool enable, QString options); void enableHilXPlane(bool enable); diff --git a/src/ui/QGCHilConfiguration.cc b/src/ui/QGCHilConfiguration.cc index 37467fb1378711a5229cda49248d367d7d340017..e501e8c6aaf7d16252fbd65b74e3c7599324953f 100644 --- a/src/ui/QGCHilConfiguration.cc +++ b/src/ui/QGCHilConfiguration.cc @@ -64,7 +64,7 @@ void QGCHilConfiguration::on_simComboBox_currentIndexChanged(int index) if(1 == index) { // Ensure the sim exists and is disabled - mav->enableHilFlightGear(false, ""); + mav->enableHilFlightGear(false, "", true); QGCHilFlightGearConfiguration* hfgconf = new QGCHilFlightGearConfiguration(mav, this); hfgconf->show(); ui->simulatorConfigurationLayout->addWidget(hfgconf); diff --git a/src/ui/QGCHilFlightGearConfiguration.cc b/src/ui/QGCHilFlightGearConfiguration.cc index 6a39a257e92c81343ae1741c1ba935aa8ca9affe..ddbccb7c7fa94edb6d6a0caa3dd08796e0f25e1a 100644 --- a/src/ui/QGCHilFlightGearConfiguration.cc +++ b/src/ui/QGCHilFlightGearConfiguration.cc @@ -40,7 +40,7 @@ void QGCHilFlightGearConfiguration::on_startButton_clicked() //XXX check validity of inputs QString options = ui->optionsPlainTextEdit->toPlainText(); options.append(" --aircraft=" + ui->aircraftComboBox->currentText()); - mav->enableHilFlightGear(true, options); + mav->enableHilFlightGear(true, options, ui->sensorHilCheckBox->isChecked()); } void QGCHilFlightGearConfiguration::on_stopButton_clicked() diff --git a/src/ui/QGCHilFlightGearConfiguration.ui b/src/ui/QGCHilFlightGearConfiguration.ui index 2a4cb315b18d0b0ef530b02e9611c2f1a569694a..d06f174223349217bae9244cc3cabe096c03700b 100644 --- a/src/ui/QGCHilFlightGearConfiguration.ui +++ b/src/ui/QGCHilFlightGearConfiguration.ui @@ -25,8 +25,17 @@ false - - + + + 0 + + + 0 + + + 0 + + 0 @@ -52,14 +61,14 @@ - + <html><head/><body><p>Additional Options:</p></body></html> - + @@ -72,7 +81,7 @@ - + @@ -85,13 +94,23 @@ - + Stop + + + + Sensor HIL + + + true + + +