Skip to content

Commit

Permalink
Fix HIL link reconnect issues due to missing threading flag usage, wa…
Browse files Browse the repository at this point in the history
…rn user about missing config and take him to config view if necessary
  • Loading branch information
LorenzMeier committed Jun 20, 2014
1 parent 52be49a commit a6fae6b
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 54 deletions.
6 changes: 4 additions & 2 deletions qgroundcontrol.pro
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,8 @@ HEADERS += \
src/uas/QGCUASFileManager.h \
src/ui/QGCUASFileView.h \
src/uas/QGCUASWorker.h \
src/CmdLineOptParser.h
src/CmdLineOptParser.h \
src/uas/QGXPX4UAS.h

SOURCES += \
src/main.cc \
Expand Down Expand Up @@ -755,4 +756,5 @@ SOURCES += \
src/uas/QGCUASFileManager.cc \
src/ui/QGCUASFileView.cc \
src/uas/QGCUASWorker.cc \
src/CmdLineOptParser.cc
src/CmdLineOptParser.cc \
src/uas/QGXPX4UAS.cc
114 changes: 62 additions & 52 deletions src/comm/QGCXPlaneLink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ QGCXPlaneLink::QGCXPlaneLink(UASInterface* mav, QString remoteHost, QHostAddress
// http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
moveToThread(this);

setTerminationEnabled(false);

this->localHost = localHost;
this->localPort = localPort/*+mav->getUASID()*/;
this->connectState = false;
connectState = false;

this->name = tr("X-Plane Link (localPort:%1)").arg(localPort);
setRemoteHost(remoteHost);
loadSettings();
Expand Down Expand Up @@ -151,13 +154,27 @@ void QGCXPlaneLink::setVersion(unsigned int version)
**/
void QGCXPlaneLink::run()
{
if (!mav) return;
if (connectState) return;
if (!mav) {
emit statusMessage("No MAV present");
return;
}

if (connectState) {
emit statusMessage("Already connected");
return;
}

socket = new QUdpSocket(this);
socket->moveToThread(this);
connectState = socket->bind(localHost, localPort);
if (!connectState) return;
if (!connectState) {

emit statusMessage("Binding socket failed!");

delete socket;
socket = NULL;
return;
}

QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readBytes()));

Expand Down Expand Up @@ -208,19 +225,43 @@ void QGCXPlaneLink::run()
}
}

//qDebug() << "REQ SEND TO:" << localAddrStr << localPortStr;

ip.index = 0;
strncpy(ip.str_ipad_them, localAddrStr.toAscii(), qMin((int)sizeof(ip.str_ipad_them), 16));
strncpy(ip.str_port_them, localPortStr.toAscii(), qMin((int)sizeof(ip.str_port_them), 6));
ip.use_ip = 1;

writeBytes((const char*)&ip, sizeof(ip));

_should_exit = false;

while(!_should_exit) {
QCoreApplication::processEvents();
QGC::SLEEP::msleep(5);
}

if (mav)
{
disconnect(mav, SIGNAL(hilControlsChanged(quint64, float, float, float, float, quint8, quint8)), this, SLOT(updateControls(quint64,float,float,float,float,quint8,quint8)));
disconnect(mav, SIGNAL(hilActuatorsChanged(quint64, float, float, float, float, float, float, float, float)), this, SLOT(updateActuators(quint64,float,float,float,float,float,float,float,float)));

disconnect(this, SIGNAL(hilGroundTruthChanged(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float)), mav, SLOT(sendHilGroundTruth(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)));

// Do not toggle HIL state on the UAS - this is not the job of this link, but of the
// UAS object
}

connectState = false;

socket->close();
delete socket;
socket = NULL;

emit simulationDisconnected();
emit simulationConnected(false);
emit finished();
}

void QGCXPlaneLink::setPort(int localPort)
Expand Down Expand Up @@ -839,50 +880,15 @@ qint64 QGCXPlaneLink::bytesAvailable()
**/
bool QGCXPlaneLink::disconnectSimulation()
{
if (!connectState) return true;

connectState = false;

if (process) disconnect(process, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(processError(QProcess::ProcessError)));
if (mav)
if (connectState)
{
disconnect(mav, SIGNAL(hilControlsChanged(quint64, float, float, float, float, quint8, quint8)), this, SLOT(updateControls(quint64,float,float,float,float,quint8,quint8)));
disconnect(mav, SIGNAL(hilActuatorsChanged(quint64, float, float, float, float, float, float, float, float)), this, SLOT(updateActuators(quint64,float,float,float,float,float,float,float,float)));

disconnect(this, SIGNAL(hilGroundTruthChanged(quint64,float,float,float,float,float,float,double,double,double,float,float,float,float,float,float,float,float)), mav, SLOT(sendHilGroundTruth(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)));

UAS* uas = dynamic_cast<UAS*>(mav);
if (uas)
{
uas->stopHil();
}
_should_exit = true;
wait();
} else {
emit simulationDisconnected();
emit simulationConnected(false);
}

if (process)
{
process->close();
delete process;
process = NULL;
}
if (terraSync)
{
terraSync->close();
delete terraSync;
terraSync = NULL;
}
if (socket)
{
socket->close();
delete socket;
socket = NULL;
}

emit simulationDisconnected();
emit simulationConnected(false);
return !connectState;
}

Expand Down Expand Up @@ -1017,11 +1023,15 @@ void QGCXPlaneLink::setRandomAttitude()
**/
bool QGCXPlaneLink::connectSimulation()
{
qDebug() << "STARTING X-PLANE LINK, CONNECTING TO" << remoteHost << ":" << remotePort;
// XXX Hack
storeSettings();

start(HighPriority);
if (connectState) {
qDebug() << "Simulation already active";
} else {
qDebug() << "STARTING X-PLANE LINK, CONNECTING TO" << remoteHost << ":" << remotePort;
// XXX Hack
storeSettings();

start(HighPriority);
}

return true;
}
Expand Down
15 changes: 15 additions & 0 deletions src/uas/QGCMAVLinkUASFactory.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "QGCMAVLinkUASFactory.h"
#include "UASManager.h"
#include "QGCUASWorker.h"
#include "QGXPX4UAS.h"

QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) :
QObject(parent)
Expand Down Expand Up @@ -58,6 +59,20 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte
uas = mav;
}
break;
case MAV_AUTOPILOT_PX4:
{
QGXPX4UAS* px4 = new QGXPX4UAS(mavlink, worker, sysid);
// Set the system type
px4->setSystemType((int)heartbeat->type);

// Connect this robot to the UAS object
// it is IMPORTANT here to use the right object type,
// else the slot of the parent object is called (and thus the special
// packets never reach their goal)
connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), px4, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
uas = px4;
}
break;
case MAV_AUTOPILOT_SLUGS:
{
SlugsMAV* mav = new SlugsMAV(mavlink, worker, sysid);
Expand Down
37 changes: 37 additions & 0 deletions src/uas/QGXPX4UAS.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "QGXPX4UAS.h"

QGXPX4UAS::QGXPX4UAS(MAVLinkProtocol* mavlink, QThread* thread, int id) :
UAS(mavlink, thread, id)
{
}

/**
* This function is called by MAVLink once a complete, uncorrupted (CRC check valid)
* mavlink packet is received.
*
* @param link Hardware link the message came from (e.g. /dev/ttyUSB0 or UDP port).
* messages can be sent back to the system via this link
* @param message MAVLink message, as received from the MAVLink protocol stack
*/
void QGXPX4UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
{
UAS::receiveMessage(link, message);
}

void QGXPX4UAS::processParamValueMsgHook(mavlink_message_t& msg, const QString& paramName,const mavlink_param_value_t& rawValue, mavlink_param_union_t& paramValue)
{
int compId = msg.compid;
if (paramName == "SYS_AUTOSTART") {

bool ok;

int val = parameters.value(compId)->value(paramName).toInt(&ok);

if (ok && val == 0) {
emit misconfigurationDetected(this);
qDebug() << "HINTING MISCONFIGURATION";
}

qDebug() << "SYS_AUTOSTART FOUND WITH VAL: " << val;
}
}
21 changes: 21 additions & 0 deletions src/uas/QGXPX4UAS.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef QGXPX4UAS_H
#define QGXPX4UAS_H

#include "UAS.h"

class QGXPX4UAS : public UAS
{
Q_OBJECT
Q_INTERFACES(UASInterface)
public:
QGXPX4UAS(MAVLinkProtocol* mavlink, QThread* thread, int id);

public slots:
/** @brief Receive a MAVLink message from this MAV */
void receiveMessage(LinkInterface* link, mavlink_message_t message);

virtual void processParamValueMsgHook(mavlink_message_t& msg, const QString& paramName,const mavlink_param_value_t& rawValue, mavlink_param_union_t& paramValue);

};

#endif // QGXPX4UAS_H
1 change: 1 addition & 0 deletions src/uas/UAS.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
paramVal.type = rawValue.param_type;

processParamValueMsg(message, parameterName,rawValue,paramVal);
processParamValueMsgHook(message, parameterName,rawValue,paramVal);

}
break;
Expand Down
1 change: 1 addition & 0 deletions src/uas/UAS.h
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ public slots:
quint64 getUnixReferenceTime(quint64 time);

virtual void processParamValueMsg(mavlink_message_t& msg, const QString& paramName,const mavlink_param_value_t& rawValue, mavlink_param_union_t& paramValue);
virtual void processParamValueMsgHook(mavlink_message_t& msg, const QString& paramName,const mavlink_param_value_t& rawValue, mavlink_param_union_t& paramValue) {};

int componentID[256];
bool componentMulti[256];
Expand Down
5 changes: 5 additions & 0 deletions src/uas/UASInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ public slots:
void poiFound(UASInterface* uas, int type, int colorIndex, QString message, float x, float y, float z);
void poiConnectionFound(UASInterface* uas, int type, int colorIndex, QString message, float x1, float y1, float z1, float x2, float y2, float z2);

/**
* @brief A misconfiguration has been detected by the UAS
*/
void misconfigurationDetected(UASInterface* uas);

/** @brief A text message from the system has been received */
void textMessageReceived(int uasid, int componentid, int severity, QString text);

Expand Down
21 changes: 21 additions & 0 deletions src/ui/MainWindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,7 @@ void MainWindow::UASCreated(UASInterface* uas)

connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
connect(uas, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
connect(uas, SIGNAL(misconfigurationDetected(UASInterface*)), this, SLOT(handleMisconfiguration(UASInterface*)));

// HIL
showHILConfigurationWidget(uas);
Expand Down Expand Up @@ -1981,6 +1982,26 @@ void MainWindow::setAdvancedMode(bool isAdvancedMode)
settings.setValue("ADVANCED_MODE",isAdvancedMode);
}

void MainWindow::handleMisconfiguration(UASInterface* uas) {

// Ask user if he wants to handle this now
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("Missing or Invalid Onboard Configuration"));
msgBox.setInformativeText(tr("The onboard system configuration is missing or incomplete. Do you want to resolve this now?"));
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Ok);
int val = msgBox.exec();

if (val == QMessageBox::Ok) {
// He wants to handle it, make sure this system is selected
UASManager::instance()->setActiveUAS(uas);

// Flick to config view
loadHardwareConfigView();
}
}

void MainWindow::loadEngineerView()
{
if (currentView != VIEW_ENGINEER)
Expand Down
1 change: 1 addition & 0 deletions src/ui/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public slots:

/** @brief Sets advanced mode, allowing for editing of tool widget locations */
void setAdvancedMode(bool isAdvancedMode);
void handleMisconfiguration(UASInterface* uas);
/** @brief Load configuration views */
void loadHardwareConfigView();
void loadSoftwareConfigView();
Expand Down

0 comments on commit a6fae6b

Please sign in to comment.