9#include <QtCore/QTimer>
16 , _terrainFactGroup(terrainFactGroup)
17 , _terrainDataSendTimer(new QTimer(this))
21 _terrainDataSendTimer->setSingleShot(
false);
22 _terrainDataSendTimer->setInterval(1000.0/12.0);
23 (void) connect(_terrainDataSendTimer, &QTimer::timeout,
this, &TerrainProtocolHandler::_sendNextTerrainData);
33 switch (message.msgid) {
34 case MAVLINK_MSG_ID_TERRAIN_REQUEST:
35 _handleTerrainRequest(message);
37 case MAVLINK_MSG_ID_TERRAIN_REPORT:
38 _handleTerrainReport(message);
45void TerrainProtocolHandler::_handleTerrainRequest(
const mavlink_message_t &message)
47 mavlink_terrain_request_t terrainRequest;
48 mavlink_msg_terrain_request_decode(&message, &terrainRequest);
52 if (terrainRequest.lat == 0 && terrainRequest.lon == 0) {
53 qCDebug(TerrainProtocolHandlerLog) <<
"Ignoring TERRAIN_REQUEST with lat=0, lon=0";
57 _currentTerrainRequest = terrainRequest;
58 _terrainRequestActive =
true;
59 _sendNextTerrainData();
62void TerrainProtocolHandler::_handleTerrainReport(
const mavlink_message_t &message)
64 mavlink_terrain_report_t terrainReport;
65 mavlink_msg_terrain_report_decode(&message, &terrainReport);
70 if (TerrainProtocolHandlerLog().isDebugEnabled()) {
72 QList<double> altitudes;
73 QList<QGeoCoordinate> coordinates;
74 QGeoCoordinate coord(
static_cast<double>(terrainReport.lat) / 1e7,
static_cast<double>(terrainReport.lon) / 1e7);
75 (void) coordinates.append(coord);
77 const QString vehicleAlt = terrainReport.spacing ? QStringLiteral(
"%1").arg(terrainReport.terrain_height) : QStringLiteral(
"n/a");
80 qgcAlt = QStringLiteral(
"Error");
81 }
else if (altAvailable && !altitudes.isEmpty()) {
82 qgcAlt = QStringLiteral(
"%1").arg(altitudes[0]);
84 qgcAlt = QStringLiteral(
"N/A");
86 qCDebug(TerrainProtocolHandlerLog) <<
"TERRAIN_REPORT" << coord << QStringLiteral(
"Vehicle(%1) QGC(%2)").arg(vehicleAlt).arg(qgcAlt);
90void TerrainProtocolHandler::_sendNextTerrainData()
92 if (!_terrainRequestActive) {
96 QGeoCoordinate terrainRequestCoordSWCorner(
static_cast<double>(_currentTerrainRequest.lat) / 1e7,
static_cast<double>(_currentTerrainRequest.lon) / 1e7);
97 const int spacingBetweenGrids = _currentTerrainRequest.grid_spacing * 4;
103 bool bitFound =
false;
104 for (
int rowIndex=0; rowIndex<7; rowIndex++) {
105 for (
int colIndex=0; colIndex<8; colIndex++) {
106 const uint8_t gridBit = (rowIndex * 8) + colIndex;
107 const uint64_t checkBit = 1ull << gridBit;
108 if (_currentTerrainRequest.mask & checkBit) {
110 QGeoCoordinate swCorner = terrainRequestCoordSWCorner.atDistanceAndAzimuth(spacingBetweenGrids * colIndex, 90);
111 swCorner = swCorner.atDistanceAndAzimuth(spacingBetweenGrids * rowIndex, 0);
112 _sendTerrainData(swCorner, gridBit);
125 _terrainDataSendTimer->start();
127 _terrainRequestActive =
false;
131void TerrainProtocolHandler::_sendTerrainData(
const QGeoCoordinate &swCorner, uint8_t gridBit)
133 QList<QGeoCoordinate> coordinates;
134 for (
int rowIndex=0; rowIndex<4; rowIndex++) {
135 for (
int colIndex=0; colIndex<4; colIndex++) {
137 QGeoCoordinate coord = swCorner.atDistanceAndAzimuth(_currentTerrainRequest.grid_spacing * colIndex, 90);
138 coord = coord.atDistanceAndAzimuth(_currentTerrainRequest.grid_spacing * rowIndex, 0);
139 coordinates.append(coord);
145 QList<double> altitudes;
154 const uint64_t removeBit = ~(1ull << gridBit);
155 _currentTerrainRequest.mask &= removeBit;
158 qCDebug(TerrainProtocolHandlerLog) << Q_FUNC_INFO <<
"terrain data unavailable for gridBit" << gridBit;
162 int16_t terrainData[16];
163 for (
const double& altitude : altitudes) {
164 terrainData[altIndex++] =
static_cast<int16_t
>(altitude);
170 (void) mavlink_msg_terrain_data_pack_chan(
173 sharedLink->mavlinkChannel(),
175 _currentTerrainRequest.lat,
176 _currentTerrainRequest.lon,
177 _currentTerrainRequest.grid_spacing,
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void setRawValue(const QVariant &value)
static int getComponentId()
static MAVLinkProtocol * instance()
static bool getAltitudesForCoordinates(const QList< QGeoCoordinate > &coordinates, QList< double > &altitudes, bool &error)
bool mavlinkMessageReceived(const mavlink_message_t &message)
~TerrainProtocolHandler()
WeakLinkInterfacePtr primaryLink() const
VehicleLinkManager * vehicleLinkManager()
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)