Commit f391ef7a authored by Valentin Platzgummer's avatar Valentin Platzgummer

Heartbeat handling added to WimaController

parent d0db1f13
...@@ -432,6 +432,7 @@ HEADERS += \ ...@@ -432,6 +432,7 @@ HEADERS += \
src/Wima/Geometry/GeoPoint3D.h \ src/Wima/Geometry/GeoPoint3D.h \
src/Wima/Geometry/Polygon2D.h \ src/Wima/Geometry/Polygon2D.h \
src/Wima/Geometry/PolygonArray.h \ src/Wima/Geometry/PolygonArray.h \
src/Wima/Snake/QNemoHeartbeat.h \
src/Wima/Snake/QNemoProgress.h \ src/Wima/Snake/QNemoProgress.h \
src/Wima/Snake/QtROSJsonFactory.h \ src/Wima/Snake/QtROSJsonFactory.h \
src/Wima/Snake/QtROSTypeFactory.h \ src/Wima/Snake/QtROSTypeFactory.h \
......
...@@ -244,19 +244,15 @@ FlightMap { ...@@ -244,19 +244,15 @@ FlightMap {
// Add Snake tiles center points to the map // Add Snake tiles center points to the map
MapItemView { MapItemView {
property bool _lengthMatching: wimaController.snakeTileCenterPoints.count
> 0
property bool _enable: wimaController.enableWimaController.value property bool _enable: wimaController.enableWimaController.value
&& wimaController.enableSnake.value && wimaController.enableSnake.value
&& _lengthMatching
model: _enable ? wimaController.snakeTileCenterPoints : 0 model: _enable ? wimaController.snakeTileCenterPoints : 0
delegate: MapCircle{ delegate: MapCircle{
center: modelData center: modelData
border.color: "transparent" border.color: "transparent"
color: getColor(wimaController.snakeProgress[index]) color: getColor(wimaController.nemoProgress[index])
radius: 0.6 radius: 0.6
opacity: 1 opacity: 1
z: 1 z: 1
......
...@@ -204,10 +204,9 @@ Item { ...@@ -204,10 +204,9 @@ Item {
// Snake connection status. // Snake connection status.
QGCLabel { QGCLabel {
property int _connectionStatus: wimaController.snakeConnectionStatus property int index: wimaController.nemoStatus
text: _connectionStatus === 1 ? property string statusString: wimaController.nemoStatusString
qsTr("Status: Connected") text: "Status: " + statusString
: qsTr("Status: Not Connected")
Layout.fillWidth: true Layout.fillWidth: true
} }
...@@ -370,7 +369,7 @@ Item { ...@@ -370,7 +369,7 @@ Item {
QGCButton { QGCButton {
id: buttonSmartRTL id: buttonSmartRTL
text: qsTr("Smart RTL") text: qsTr("Smart RTL")
onClicked: wimaController.initSmartRTL(); onClicked: wimaController.requestSmartRTL();
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
} }
......
#pragma once
#include "ros_bridge/include/GenericMessages.h"
using QNemoHeartbeat = ROSBridge::GenericMessages::NemoMsgs::Heartbeat;
...@@ -81,22 +81,28 @@ bool WaypointManager::RTLManager::reset() ...@@ -81,22 +81,28 @@ bool WaypointManager::RTLManager::reset()
return true; return true;
} }
QString WaypointManager::RTLManager::checkPrecondition() bool WaypointManager::RTLManager::checkPrecondition(QString &errorString)
{ {
// Be aware of the error message order!
Vehicle *managerVehicle = _settings->masterController()->managerVehicle(); Vehicle *managerVehicle = _settings->masterController()->managerVehicle();
if (!managerVehicle->flying()) {
return QString("Vehicle is not flying. Smart RTL not available."); if ( managerVehicle->isOfflineEditingVehicle() ) {
errorString.append("No vehicle connected. Smart RTL not available.");
return false;
} }
if (!managerVehicle->isOfflineEditingVehicle()) { if ( !managerVehicle->flying() ) {
return QString("Not connected to any vehicle. Smart RTL not available."); errorString.append("Vehicle is not flying. Smart RTL not available.");
return false;
} }
if (!_areaInterface->joinedArea()->containsCoordinate(managerVehicle->coordinate())) { if ( !_areaInterface->joinedArea()->containsCoordinate(
return QString("Vehicle not inside save area. Smart RTL not available."); managerVehicle->coordinate()) ) {
errorString.append("Vehicle not inside save area. Smart RTL not available.");
return false;
} }
return QString(); return true;
} }
bool WaypointManager::RTLManager::_insertMissionItem(const QGeoCoordinate &c, bool WaypointManager::RTLManager::_insertMissionItem(const QGeoCoordinate &c,
......
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
//! //!
virtual bool reset() override; virtual bool reset() override;
QString checkPrecondition(); bool checkPrecondition(QString &errorString);
protected: protected:
bool _insertMissionItem(const QGeoCoordinate &c, bool _insertMissionItem(const QGeoCoordinate &c,
......
This diff is collapsed.
...@@ -33,12 +33,15 @@ ...@@ -33,12 +33,15 @@
#include "Snake/SnakeTilesLocal.h" #include "Snake/SnakeTilesLocal.h"
#include "Geometry/GeoPoint3D.h" #include "Geometry/GeoPoint3D.h"
#include "Snake/QNemoProgress.h" #include "Snake/QNemoProgress.h"
#include "Snake/QNemoHeartbeat.h"
#include "ros_bridge/include/ROSBridge.h" #include "ros_bridge/include/ROSBridge.h"
#include "WaypointManager/DefaultManager.h" #include "WaypointManager/DefaultManager.h"
#include "WaypointManager/RTLManager.h" #include "WaypointManager/RTLManager.h"
#include <map>
#define CHECK_BATTERY_INTERVAL 1000 // ms #define CHECK_BATTERY_INTERVAL 1000 // ms
#define SMART_RTL_MAX_ATTEMPTS 3 // times #define SMART_RTL_MAX_ATTEMPTS 3 // times
#define SMART_RTL_ATTEMPT_INTERVAL 200 // ms #define SMART_RTL_ATTEMPT_INTERVAL 200 // ms
...@@ -60,8 +63,6 @@ class WimaController : public QObject ...@@ -60,8 +63,6 @@ class WimaController : public QObject
public: public:
enum SnakeConnectionStatus {Connected = 1, NotConnected = 0};
WimaController(QObject *parent = nullptr); WimaController(QObject *parent = nullptr);
...@@ -149,9 +150,13 @@ public: ...@@ -149,9 +150,13 @@ public:
READ enableSnake READ enableSnake
CONSTANT CONSTANT
) )
Q_PROPERTY(long snakeConnectionStatus Q_PROPERTY(int nemoStatus
READ snakeConnectionStatus READ nemoStatus
NOTIFY snakeConnectionStatusChanged NOTIFY nemoStatusChanged
)
Q_PROPERTY(QString nemoStatusString
READ nemoStatusString
NOTIFY nemoStatusStringChanged
) )
Q_PROPERTY(bool snakeCalcInProgress Q_PROPERTY(bool snakeCalcInProgress
READ snakeCalcInProgress READ snakeCalcInProgress
...@@ -224,8 +229,9 @@ public: ...@@ -224,8 +229,9 @@ public:
// Snake data. // Snake data.
QmlObjectListModel* snakeTiles (void) { return _snakeTiles.QmlObjectListModel();} QmlObjectListModel* snakeTiles (void) { return _snakeTiles.QmlObjectListModel();}
QVariantList snakeTileCenterPoints (void) { return _snakeTileCenterPoints;} QVariantList snakeTileCenterPoints (void) { return _snakeTileCenterPoints;}
QVector<int> nemoProgress (void) { return _nemoProgress.progress();} QVector<int> nemoProgress (void);
long snakeConnectionStatus (void) const; int nemoStatus (void) const;
QString nemoStatusString (void) const;
bool snakeCalcInProgress (void) const; bool snakeCalcInProgress (void) const;
// Smart RTL. // Smart RTL.
...@@ -303,6 +309,8 @@ signals: ...@@ -303,6 +309,8 @@ signals:
void snakeTilesChanged (void); void snakeTilesChanged (void);
void snakeTileCenterPointsChanged (void); void snakeTileCenterPointsChanged (void);
void nemoProgressChanged (void); void nemoProgressChanged (void);
void nemoStatusChanged (void);
void nemoStatusStringChanged (void);
private slots: private slots:
...@@ -325,11 +333,10 @@ private slots: ...@@ -325,11 +333,10 @@ private slots:
void _setPhaseDuration (double duration); void _setPhaseDuration (double duration);
// SMART RTL // SMART RTL
void _checkBatteryLevel (void); void _checkBatteryLevel (void);
QString _checkSmartRTLPreCondition (void); bool _checkSmartRTLPreCondition (QString &errorString);
void _initSmartRTL (); void _initSmartRTL ();
void _smartRTLCleanUp (bool flying); void _smartRTLCleanUp (bool flying);
// Snake. // Snake.
void _setSnakeConnectionStatus (SnakeConnectionStatus status);
void _setSnakeCalcInProgress (bool inProgress); void _setSnakeCalcInProgress (bool inProgress);
bool _isScenarioDefined (void); bool _isScenarioDefined (void);
bool _isScenarioDefinedErrorMessage (void); bool _isScenarioDefinedErrorMessage (void);
...@@ -343,6 +350,7 @@ private slots: ...@@ -343,6 +350,7 @@ private slots:
void _switchWaypointManager(WaypointManager::ManagerBase &manager); void _switchWaypointManager(WaypointManager::ManagerBase &manager);
private: private:
using StatusMap = std::map<int, QString>;
// Snake. // Snake.
void _progressFromJson (JsonDocUPtr pDoc, void _progressFromJson (JsonDocUPtr pDoc,
QNemoProgress &progress); QNemoProgress &progress);
...@@ -397,7 +405,6 @@ private: ...@@ -397,7 +405,6 @@ private:
// double _phaseDuration; // the phase duration in seconds // double _phaseDuration; // the phase duration in seconds
// Snake // Snake
SnakeConnectionStatus _snakeConnectionStatus;
bool _snakeCalcInProgress; bool _snakeCalcInProgress;
bool _snakeRecalcNecessary; bool _snakeRecalcNecessary;
bool _scenarioDefinedBool; bool _scenarioDefinedBool;
...@@ -408,7 +415,10 @@ private: ...@@ -408,7 +415,10 @@ private:
SnakeTilesLocal _snakeTilesLocal; // tiles local coordinate system SnakeTilesLocal _snakeTilesLocal; // tiles local coordinate system
QVariantList _snakeTileCenterPoints; QVariantList _snakeTileCenterPoints;
QNemoProgress _nemoProgress; // measurement progress QNemoProgress _nemoProgress; // measurement progress
QNemoHeartbeat _nemoHeartbeat; // measurement progress
int _fallbackStatus;
ROSBridgePtr _pRosBridge; ROSBridgePtr _pRosBridge;
static StatusMap _nemoStatusMap;
// Periodic tasks. // Periodic tasks.
QTimer _eventTimer; QTimer _eventTimer;
......
...@@ -343,6 +343,29 @@ protected: ...@@ -343,6 +343,29 @@ protected:
typedef GenericProgress<> Progress; typedef GenericProgress<> Progress;
// ==============================================================================
// class Heartbeat
// ==============================================================================
//! @brief C++ representation of nemo_msgs/Heartbeat message
class Heartbeat : public MessageBaseClass{
public:
typedef MessageGroups::HeartbeatGroup Group;
Heartbeat(){}
Heartbeat(int status) :_status(status){}
Heartbeat(const Heartbeat &heartbeat) :_status(heartbeat.status()){}
~Heartbeat() = default;
virtual Heartbeat *Clone() const override { return new Heartbeat(*this); }
virtual int status (void)const {return _status;}
virtual void setStatus (int status) {_status = status;}
protected:
int _status;
};
typedef GenericProgress<> Progress;
} // namespace NemoMsgs } // namespace NemoMsgs
} // namespace GenericMessages } // namespace GenericMessages
} // namespace ROSBridge } // namespace ROSBridge
...@@ -186,6 +186,20 @@ private: ...@@ -186,6 +186,20 @@ private:
return doc; return doc;
} }
// ===========================================================================
// HeartbeatGroup
// ===========================================================================
template<class U>
rapidjson::Document *_create(const U &msg, Type2Type<MessageGroups::HeartbeatGroup>){
using namespace ROSBridge;
rapidjson::Document *doc = new rapidjson::Document(rapidjson::kObjectType);
bool ret = JsonMethodes::NemoMsgs::Heartbeat::toJson(msg, *doc, doc->GetAllocator());
assert(ret);
(void)ret;
return doc;
}
}; };
class StdHeaderPolicy class StdHeaderPolicy
......
...@@ -643,7 +643,7 @@ namespace Progress { ...@@ -643,7 +643,7 @@ namespace Progress {
{ {
rapidjson::Value progressJson(rapidjson::kArrayType); rapidjson::Value progressJson(rapidjson::kArrayType);
for(unsigned long i=0; i < std::uint64_t(p.progress().size()); ++i){ for(unsigned long i=0; i < std::uint64_t(p.progress().size()); ++i){
progressJson.PushBack(rapidjson::Value().SetInt(std::int8_t(p.progress()[i])), allocator); progressJson.PushBack(rapidjson::Value().SetInt(std::int32_t(p.progress()[i])), allocator);
} }
value.AddMember("progress", progressJson, allocator); value.AddMember("progress", progressJson, allocator);
return true; return true;
...@@ -662,10 +662,32 @@ namespace Progress { ...@@ -662,10 +662,32 @@ namespace Progress {
p.progress().clear(); p.progress().clear();
p.progress().reserve(sz); p.progress().reserve(sz);
for (unsigned long i=0; i < sz; ++i) for (unsigned long i=0; i < sz; ++i)
p.progress().push_back(std::int8_t(jsonProgress[i].GetInt())); p.progress().push_back(std::int32_t(jsonProgress[i].GetInt()));
return true; return true;
} }
} // namespace Progress } // namespace Progress
//! @brief Namespace containing methodes for nemo_msgs/Heartbeat generation.
namespace Heartbeat {
template <class HeartbeatType>
bool toJson(const HeartbeatType &heartbeat, rapidjson::Value &value, rapidjson::Document::AllocatorType &allocator)
{
value.AddMember("status", std::int32_t(heartbeat.status()), allocator);
return true;
}
template <class HeartbeatType>
bool fromJson(const rapidjson::Value &value, HeartbeatType &heartbeat)
{
if (!value.HasMember("status") || !value["status"].IsInt()){
assert(false);
return false;
}
heartbeat.setStatus(value["status"].GetInt());
return true;
}
} // namespace Heartbeat
} // namespace NemoMsgs } // namespace NemoMsgs
} // namespace JsonMethodes } // namespace JsonMethodes
} // namespace ROSBridge } // namespace ROSBridge
......
...@@ -98,11 +98,15 @@ struct NemoMsgs { ...@@ -98,11 +98,15 @@ struct NemoMsgs {
//! //!
//! \brief The ProgressGroup struct is used the mark a class as a ROS nemo_msgs/Progress message. //! \brief The ProgressGroup struct is used the mark a class as a ROS nemo_msgs/Progress message.
//!
//! The ProgressGroup struct is used the mark a class as a ROS nemo_msgs/Progress message.
struct ProgressGroup { struct ProgressGroup {
static StringType label() {return "Progress";} static StringType label() {return "Progress";}
}; };
//!
//! \brief The HeartbeatGroup struct is used the mark a class as a ROS nemo_msgs/Heartbeat message.
struct HeartbeatGroup {
static StringType label() {return "Heartbeat";}
};
}; };
...@@ -134,6 +138,10 @@ typedef MessageGroups::MessageGroup<MessageGroups::NemoMsgs, ...@@ -134,6 +138,10 @@ typedef MessageGroups::MessageGroup<MessageGroups::NemoMsgs,
MessageGroups::NemoMsgs::ProgressGroup> MessageGroups::NemoMsgs::ProgressGroup>
ProgressGroup; ProgressGroup;
typedef MessageGroups::MessageGroup<MessageGroups::NemoMsgs,
MessageGroups::NemoMsgs::HeartbeatGroup>
HeartbeatGroup;
} // end namespace MessageGroups } // end namespace MessageGroups
} // end namespace ros_bridge } // end namespace ros_bridge
...@@ -120,6 +120,17 @@ private: ...@@ -120,6 +120,17 @@ private:
return ret; return ret;
} }
// ===========================================================================
// HeartbeatGroup
// ===========================================================================
template<class U>
bool _create(const rapidjson::Document &doc, U &type, Type2Type<MessageGroups::HeartbeatGroup>){
using namespace ROSBridge;
bool ret = JsonMethodes::NemoMsgs::Heartbeat::fromJson(doc, type);
assert(ret);
return ret;
}
}; };
......
...@@ -21,25 +21,25 @@ public: ...@@ -21,25 +21,25 @@ public:
//! //!
//! \brief EventTicker Constructor used for initilization. The function \fn must not be called if this constructor is used. //! \brief EventTicker Constructor used for initilization. The function \fn must not be called if this constructor is used.
//! \param timerInterval The timer interval of the timer provided by the user. //! \param timerInterval The timer interval of the timer provided by the user.
//! \param tickInterval The thick intervall (timerInterval <= tickInterval), see \fn ready(). //! \param targetTime The thick intervall (timerInterval <= targetTime), see \fn ready().
//! //!
EventTicker(double timerInterval, double tickInterval) { EventTicker(double timerInterval, double targetTime) {
_isInitialized = false; _isInitialized = false;
init(timerInterval, tickInterval); init(timerInterval, targetTime);
} }
//! //!
//! \brief init Used to init the EventTicker. //! \brief init Used to init the EventTicker.
//! \param timerInterval The timer interval of the timer provided by the user. //! \param timerInterval The timer interval of the timer provided by the user.
//! \param tickInterval The thick intervall (timerInterval <= tickInterval), see \fn ready(). //! \param targetTime The thick intervall (timerInterval <= targetTime), see \fn ready().
//! //!
void init(double timerInterval, double tickInterval){ void init(double timerInterval, double targetTime){
assert(_isInitialized == false); assert(_isInitialized == false);
assert(timerInterval > 0); assert(timerInterval > 0);
assert(tickInterval >= timerInterval); assert(targetTime >= timerInterval);
_timerInterval = timerInterval; _timerInterval = timerInterval;
_tickInerval = tickInterval; _targetTime = targetTime;
_tickCount = 0; _ticks = 0;
_isInitialized = true; _isInitialized = true;
} }
...@@ -48,22 +48,28 @@ public: ...@@ -48,22 +48,28 @@ public:
//! \return True if the event is ready to be executed, false either. //! \return True if the event is ready to be executed, false either.
//! //!
//! This function must be called by a user provided timer interrupt handler. A internal counter increases with every call. //! This function must be called by a user provided timer interrupt handler. A internal counter increases with every call.
//! If _tickInerval <= _timerInterval*_tickCount the counter gets reset and the function returns true. If the condition is not //! If _targetTime <= _timerInterval*_ticks the counter gets reset and the function returns true. If the condition is not
//! met the function returns false. //! met the function returns false.
//! //!
bool ready(void) { bool ready(void) {
assert(_isInitialized == true); assert(_isInitialized == true);
_tickCount++; _ticks++;
bool ready = _tickInerval <= _timerInterval*_tickCount; bool ready = _targetTime <= _timerInterval*_ticks;
if (ready) if (ready)
_tickCount = 0; _ticks = 0;
return ready; return ready;
} }
//!
//! \brief Resets the tick count.
void reset(void) {
_ticks = 0;
}
private: private:
double _timerInterval; double _timerInterval;
double _tickInerval; double _targetTime;
unsigned long _tickCount; unsigned long _ticks;
bool _isInitialized; bool _isInitialized;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment