UASWaypointManager.cc 28.5 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2
/*=====================================================================

lm's avatar
lm committed
3
QGroundControl Open Source Ground Control Station
pixhawk's avatar
pixhawk committed
4

lm's avatar
lm committed
5
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
6

lm's avatar
lm committed
7
This file is part of the QGROUNDCONTROL project
pixhawk's avatar
pixhawk committed
8

lm's avatar
lm committed
9
    QGROUNDCONTROL is free software: you can redistribute it and/or modify
pixhawk's avatar
pixhawk committed
10 11 12 13
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

lm's avatar
lm committed
14
    QGROUNDCONTROL is distributed in the hope that it will be useful,
pixhawk's avatar
pixhawk committed
15 16 17 18 19
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
lm's avatar
lm committed
20
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
pixhawk's avatar
pixhawk committed
21 22 23 24 25 26 27 28 29 30 31

======================================================================*/

/**
 * @file
 *   @brief Implementation of the waypoint protocol handler
 *
 *   @author Petri Tanskanen <mavteam@student.ethz.ch>
 *
 */

32 33
#include "UASWaypointManager.h"
#include "UAS.h"
34
#include "mavlink_types.h"
35

36
#define PROTOCOL_TIMEOUT_MS 2000    ///< maximum time to wait for pending messages until timeout
37
#define PROTOCOL_DELAY_MS 40        ///< minimum delay between sent messages
38
#define PROTOCOL_MAX_RETRIES 3      ///< maximum number of send retries (after timeout)
pixhawk's avatar
pixhawk committed
39

40
UASWaypointManager::UASWaypointManager(UAS &_uas)
41 42 43 44 45 46 47
    : uas(_uas),
      current_retries(0),
      current_wp_id(0),
      current_count(0),
      current_state(WP_IDLE),
      current_partner_systemid(0),
      current_partner_compid(0),
48 49
      protocol_timer(this),
      currentWaypoint(NULL)
pixhawk's avatar
pixhawk committed
50 51
{
    connect(&protocol_timer, SIGNAL(timeout()), this, SLOT(timeout()));
52 53
    connect(&uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(handleLocalPositionChanged(UASInterface*,double,double,double,quint64)));
    connect(&uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(handleGlobalPositionChanged(UASInterface*,double,double,double,quint64)));
pixhawk's avatar
pixhawk committed
54 55 56
}

void UASWaypointManager::timeout()
57
{
58
    if (current_retries > 0) {
59 60
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries--;
61
        emit updateStatusString(tr("Timeout, retrying (retries left: %1)").arg(current_retries));
62
        // // qDebug() << "Timeout, retrying (retries left:" << current_retries << ")";
63
        if (current_state == WP_GETLIST) {
64
            sendWaypointRequestList();
65
        } else if (current_state == WP_GETLIST_GETWPS) {
66
            sendWaypointRequest(current_wp_id);
67
        } else if (current_state == WP_SENDLIST) {
68
            sendWaypointCount();
69
        } else if (current_state == WP_SENDLIST_SENDWPS) {
70
            sendWaypoint(current_wp_id);
71
        } else if (current_state == WP_CLEARLIST) {
72
            sendWaypointClearAll();
73
        } else if (current_state == WP_SETCURRENT) {
74 75
            sendWaypointSetCurrent(current_wp_id);
        }
76
    } else {
77
        protocol_timer.stop();
pixhawk's avatar
pixhawk committed
78

79
        // // qDebug() << "Waypoint transaction (state=" << current_state << ") timed out going to state WP_IDLE";
pixhawk's avatar
pixhawk committed
80

81
        emit updateStatusString("Operation timed out.");
pixhawk's avatar
pixhawk committed
82

83 84 85 86 87 88
        current_state = WP_IDLE;
        current_count = 0;
        current_wp_id = 0;
        current_partner_systemid = 0;
        current_partner_compid = 0;
    }
89 90
}

91 92 93 94
void UASWaypointManager::handleLocalPositionChanged(UASInterface* mav, double x, double y, double z, quint64 time)
{
    Q_UNUSED(mav);
    Q_UNUSED(time);
95
    if (waypoints.count() > 0 && currentWaypoint && (currentWaypoint->getFrame() == MAV_FRAME_LOCAL_NED || currentWaypoint->getFrame() == MAV_FRAME_LOCAL_ENU))
96
    {
97 98 99
        double xdiff = x-currentWaypoint->getX();
        double ydiff = y-currentWaypoint->getY();
        double zdiff = z-currentWaypoint->getZ();
100 101 102 103 104 105 106 107 108 109
        double dist = sqrt(xdiff*xdiff + ydiff*ydiff + zdiff*zdiff);
        emit waypointDistanceChanged(dist);
    }
}

void UASWaypointManager::handleGlobalPositionChanged(UASInterface* mav, double lat, double lon, double alt, quint64 time)
{

}

110 111
void UASWaypointManager::handleWaypointCount(quint8 systemId, quint8 compId, quint16 count)
{
112
    if (current_state == WP_GETLIST && systemId == current_partner_systemid && compId == current_partner_compid) {
113 114 115
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;

116
        // // qDebug() << "got waypoint count (" << count << ") from ID " << systemId;
pixhawk's avatar
pixhawk committed
117

118
        if (count > 0) {
pixhawk's avatar
pixhawk committed
119 120 121
            current_count = count;
            current_wp_id = 0;
            current_state = WP_GETLIST_GETWPS;
122

pixhawk's avatar
pixhawk committed
123
            sendWaypointRequest(current_wp_id);
124
        } else {
125
            protocol_timer.stop();
pixhawk's avatar
pixhawk committed
126
            emit updateStatusString("done.");
127
            // // qDebug() << "No waypoints on UAS " << systemId;
128 129 130 131 132
            current_state = WP_IDLE;
            current_count = 0;
            current_wp_id = 0;
            current_partner_systemid = 0;
            current_partner_compid = 0;
pixhawk's avatar
pixhawk committed
133
        }
134 135
    } else {
        qDebug("Rejecting message, check mismatch: current_state: %d == %d, system id %d == %d, comp id %d == %d", current_state, WP_GETLIST, current_partner_systemid, systemId, current_partner_compid, compId);
136
    }
137 138
}

lm's avatar
lm committed
139
void UASWaypointManager::handleWaypoint(quint8 systemId, quint8 compId, mavlink_mission_item_t *wp)
pixhawk's avatar
pixhawk committed
140
{
141
    if (systemId == current_partner_systemid && compId == current_partner_compid && current_state == WP_GETLIST_GETWPS && wp->seq == current_wp_id) {
142 143 144
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;

145
        if(wp->seq == current_wp_id) {
146
            //// // qDebug() << "Got WP: " << wp->seq << wp->x <<  wp->y << wp->z << wp->param4 << "auto:" << wp->autocontinue << "curr:" << wp->current << wp->param1 << wp->param2 << "Frame:"<< (MAV_FRAME) wp->frame << "Command:" << (MAV_CMD) wp->command;
lm's avatar
lm committed
147
            Waypoint *lwp = new Waypoint(wp->seq, wp->x, wp->y, wp->z, wp->param1, wp->param2, wp->param3, wp->param4, wp->autocontinue, wp->current, (MAV_FRAME) wp->frame, (MAV_CMD) wp->command);
pixhawk's avatar
pixhawk committed
148
            addWaypoint(lwp, false);
149
            if (wp->current == 1) currentWaypoint = lwp;
pixhawk's avatar
pixhawk committed
150 151 152 153

            //get next waypoint
            current_wp_id++;

154
            if(current_wp_id < current_count) {
155
                sendWaypointRequest(current_wp_id);
156
            } else {
157 158
                sendWaypointAck(0);

pixhawk's avatar
pixhawk committed
159
                // all waypoints retrieved, change state to idle
pixhawk's avatar
pixhawk committed
160 161 162 163 164
                current_state = WP_IDLE;
                current_count = 0;
                current_wp_id = 0;
                current_partner_systemid = 0;
                current_partner_compid = 0;
165

pixhawk's avatar
pixhawk committed
166
                protocol_timer.stop();
167
                emit readGlobalWPFromUAS(false);
168
                if (currentWaypoint) emit currentWaypointChanged(currentWaypoint->getId());
169 170
                emit updateStatusString("done.");

171
                // // qDebug() << "got all waypoints from ID " << systemId;
pixhawk's avatar
pixhawk committed
172
            }
173
        } else {
174
            emit updateStatusString(tr("Waypoint ID mismatch, rejecting waypoint"));
pixhawk's avatar
pixhawk committed
175
        }
176 177
    } else {
        qDebug("Rejecting message, check mismatch: current_state: %d == %d, system id %d == %d, comp id %d == %d", current_state, WP_GETLIST, current_partner_systemid, systemId, current_partner_compid, compId);
178
    }
pixhawk's avatar
pixhawk committed
179 180
}

lm's avatar
lm committed
181
void UASWaypointManager::handleWaypointAck(quint8 systemId, quint8 compId, mavlink_mission_ack_t *wpa)
182
{
183 184
    if (systemId == current_partner_systemid && compId == current_partner_compid) {
        if((current_state == WP_SENDLIST || current_state == WP_SENDLIST_SENDWPS) && (current_wp_id == waypoint_buffer.count()-1 && wpa->type == 0)) {
185 186
            //all waypoints sent and ack received
            protocol_timer.stop();
187
            current_state = WP_IDLE;
188
            emit updateStatusString("done.");
189
            // // qDebug() << "sent all waypoints to ID " << systemId;
190
        } else if(current_state == WP_CLEARLIST) {
191 192 193
            protocol_timer.stop();
            current_state = WP_IDLE;
            emit updateStatusString("done.");
194
            // // qDebug() << "cleared waypoint list of ID " << systemId;
195
        }
196 197 198
    }
}

lm's avatar
lm committed
199
void UASWaypointManager::handleWaypointRequest(quint8 systemId, quint8 compId, mavlink_mission_request_t *wpr)
200
{
201
    if (systemId == current_partner_systemid && compId == current_partner_compid && ((current_state == WP_SENDLIST && wpr->seq == 0) || (current_state == WP_SENDLIST_SENDWPS && (wpr->seq == current_wp_id || wpr->seq == current_wp_id + 1)))) {
202 203
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;
204

205
        if (wpr->seq < waypoint_buffer.count()) {
pixhawk's avatar
pixhawk committed
206 207 208
            current_state = WP_SENDLIST_SENDWPS;
            current_wp_id = wpr->seq;
            sendWaypoint(current_wp_id);
209
        } else {
pixhawk's avatar
pixhawk committed
210 211
            //TODO: Error message or something
        }
212 213
    } else {
        qDebug("Rejecting message, check mismatch: current_state: %d == %d, system id %d == %d, comp id %d == %d", current_state, WP_GETLIST, current_partner_systemid, systemId, current_partner_compid, compId);
214
    }
215 216
}

lm's avatar
lm committed
217
void UASWaypointManager::handleWaypointReached(quint8 systemId, quint8 compId, mavlink_mission_item_reached_t *wpr)
218
{
lm's avatar
lm committed
219
    if (systemId == uas.getUASID()) {
pixhawk's avatar
pixhawk committed
220 221
        emit updateStatusString(QString("Reached waypoint %1").arg(wpr->seq));
    }
pixhawk's avatar
pixhawk committed
222 223
}

lm's avatar
lm committed
224
void UASWaypointManager::handleWaypointCurrent(quint8 systemId, quint8 compId, mavlink_mission_current_t *wpc)
pixhawk's avatar
pixhawk committed
225
{
lm's avatar
lm committed
226
    if (systemId == uas.getUASID()) {
227
        // FIXME Petri
228
        if (current_state == WP_SETCURRENT) {
229 230
            protocol_timer.stop();
            current_state = WP_IDLE;
231 232

            // update the local main storage
233 234 235
            if (wpc->seq < waypoints.size()) {
                for(int i = 0; i < waypoints.size(); i++) {
                    if (waypoints[i]->getId() == wpc->seq) {
236
                        waypoints[i]->setCurrent(true);
237 238
                        currentWaypoint = waypoints[i];

239
                    } else {
240 241 242 243
                        waypoints[i]->setCurrent(false);
                    }
                }
            }
244
        }
245 246 247
        emit updateStatusString(QString("New current waypoint %1").arg(wpc->seq));
        //emit update to UI widgets
        emit currentWaypointChanged(wpc->seq);
pixhawk's avatar
pixhawk committed
248
    }
pixhawk's avatar
pixhawk committed
249 250
}

251 252
void UASWaypointManager::notifyOfChange(Waypoint* wp)
{
253
    // // qDebug() << "WAYPOINT CHANGED: ID:" << wp->getId();
254
    // If only one waypoint was changed, emit only WP signal
255
    if (wp != NULL) {
256
        emit waypointChanged(uas.getUASID(), wp);
257
    } else {
258 259 260
        emit waypointListChanged();
        emit waypointListChanged(uas.getUASID());
    }
261 262
}

263
int UASWaypointManager::setCurrentWaypoint(quint16 seq)
pixhawk's avatar
pixhawk committed
264
{
265 266
    if (seq < waypoints.size()) {
        if(current_state == WP_IDLE) {
267
            //update local main storage
268 269
            for(int i = 0; i < waypoints.size(); i++) {
                if (waypoints[i]->getId() == seq) {
270
                    waypoints[i]->setCurrent(true);
271
                    currentWaypoint = waypoints[i];
272
                } else {
273 274 275
                    waypoints[i]->setCurrent(false);
                }
            }
276

277
            //TODO: signal changed waypoint list
278

279 280 281 282 283 284 285
            //send change to UAS - important to note: if the transmission fails, we have inconsistencies
            protocol_timer.start(PROTOCOL_TIMEOUT_MS);
            current_retries = PROTOCOL_MAX_RETRIES;

            current_state = WP_SETCURRENT;
            current_wp_id = seq;
            current_partner_systemid = uas.getUASID();
lm's avatar
lm committed
286
            current_partner_compid = MAV_COMP_ID_MISSIONPLANNER;
287 288 289 290 291 292 293 294 295 296 297

            sendWaypointSetCurrent(current_wp_id);

            //emit waypointListChanged();

            return 0;
        }
    }
    return -1;
}

pixhawk's avatar
pixhawk committed
298
/**
299
 * @warning Make sure the waypoint stays valid for the whole application lifecycle!
pixhawk's avatar
pixhawk committed
300
 * @param enforceFirstActive Enforces that the first waypoint is set as active
301
 * @see createWaypoint() is more suitable for most use cases
pixhawk's avatar
pixhawk committed
302 303
 */
void UASWaypointManager::addWaypoint(Waypoint *wp, bool enforceFirstActive)
304
{
lm's avatar
lm committed
305 306
    if (wp)
    {
307
        wp->setId(waypoints.size());
308 309 310 311 312
        if (enforceFirstActive && waypoints.size() == 0)
        {
            wp->setCurrent(true);
            currentWaypoint = wp;
        }
313
        waypoints.insert(waypoints.size(), wp);
314
        connect(wp, SIGNAL(changed(Waypoint*)), this, SLOT(notifyOfChange(Waypoint*)));
315

lm's avatar
lm committed
316
        emit waypointListChanged();
317
        emit waypointListChanged(uas.getUASID());
318
    }
pixhawk's avatar
pixhawk committed
319 320
}

321 322 323 324 325 326 327
/**
 * @param enforceFirstActive Enforces that the first waypoint is set as active
 */
Waypoint* UASWaypointManager::createWaypoint(bool enforceFirstActive)
{
    Waypoint* wp = new Waypoint();
    wp->setId(waypoints.size());
328 329 330 331 332
    if (enforceFirstActive && waypoints.size() == 0)
    {
        wp->setCurrent(true);
        currentWaypoint = wp;
    }
333 334 335 336 337 338 339 340
    waypoints.insert(waypoints.size(), wp);
    connect(wp, SIGNAL(changed(Waypoint*)), this, SLOT(notifyOfChange(Waypoint*)));

    emit waypointListChanged();
    emit waypointListChanged(uas.getUASID());
    return wp;
}

341
int UASWaypointManager::removeWaypoint(quint16 seq)
342
{
343 344
    if (seq < waypoints.size())
    {
345 346 347
        Waypoint *t = waypoints[seq];
        waypoints.remove(seq);
        delete t;
348
        t = NULL;
349

350 351
        for(int i = seq; i < waypoints.size(); i++)
        {
352 353
            waypoints[i]->setId(i);
        }
Alejandro's avatar
Alejandro committed
354

355
        emit waypointListChanged();
356
        emit waypointListChanged(uas.getUASID());
357 358 359 360 361
        return 0;
    }
    return -1;
}

362
void UASWaypointManager::moveWaypoint(quint16 cur_seq, quint16 new_seq)
363
{
364 365
    if (cur_seq != new_seq && cur_seq < waypoints.size() && new_seq < waypoints.size())
    {
366
        Waypoint *t = waypoints[cur_seq];
367
        if (cur_seq < new_seq) {
368 369
            for (int i = cur_seq; i < new_seq; i++)
            {
370 371
                waypoints[i] = waypoints[i+1];
            }
372 373 374 375 376
        }
        else
        {
            for (int i = cur_seq; i > new_seq; i--)
            {
377 378 379 380 381 382
                waypoints[i] = waypoints[i-1];
            }
        }
        waypoints[new_seq] = t;

        emit waypointListChanged();
383
        emit waypointListChanged(uas.getUASID());
384 385 386
    }
}

387
void UASWaypointManager::saveWaypoints(const QString &saveFile)
388 389 390 391 392 393
{
    QFile file(saveFile);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;

    QTextStream out(&file);
394 395

    //write the waypoint list version to the first line for compatibility check
lm's avatar
lm committed
396
    out << "QGC WPL 110\r\n";
397

398 399
    for (int i = 0; i < waypoints.size(); i++)
    {
400
        waypoints[i]->setId(i);
401 402 403 404 405
        waypoints[i]->save(out);
    }
    file.close();
}

406
void UASWaypointManager::loadWaypoints(const QString &loadFile)
407 408 409 410 411
{
    QFile file(loadFile);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

412
    while(waypoints.size()>0) {
413 414 415 416 417 418
        Waypoint *t = waypoints[0];
        waypoints.remove(0);
        delete t;
    }

    QTextStream in(&file);
419 420 421

    const QStringList &version = in.readLine().split(" ");

422 423
    if (!(version.size() == 3 && version[0] == "QGC" && version[1] == "WPL" && version[2] == "110"))
    {
424
        emit updateStatusString(tr("The waypoint file is not compatible with the current version of QGroundControl."));
425 426 427 428 429
    }
    else
    {
        while (!in.atEnd())
        {
430
            Waypoint *t = new Waypoint();
431 432
            if(t->load(in))
            {
433 434
                t->setId(waypoints.size());
                waypoints.insert(waypoints.size(), t);
435 436 437
            }
            else
            {
438 439
                emit updateStatusString(tr("The waypoint file is corrupted. Load operation only partly succesful."));
                //MainWindow::instance()->showCriticalMessage(tr("Error loading waypoint file"),);
440 441
                break;
            }
442 443
        }
    }
444

445 446
    file.close();

447
    emit loadWPFile();
448
    emit waypointListChanged();
449
    emit waypointListChanged(uas.getUASID());
450 451 452
}

void UASWaypointManager::clearWaypointList()
pixhawk's avatar
pixhawk committed
453
{
454 455
    if(current_state == WP_IDLE)
    {
pixhawk's avatar
pixhawk committed
456
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
457
        current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
458

459 460
        current_state = WP_CLEARLIST;
        current_wp_id = 0;
461
        current_partner_systemid = uas.getUASID();
lm's avatar
lm committed
462
        current_partner_compid = MAV_COMP_ID_MISSIONPLANNER;
pixhawk's avatar
pixhawk committed
463

464
        sendWaypointClearAll();
465 466 467
    }
}

468 469 470 471 472 473
const QVector<Waypoint *> UASWaypointManager::getGlobalFrameWaypointList()
{
    // TODO Keep this global frame list up to date
    // with complete waypoint list
    // instead of filtering on each request
    QVector<Waypoint*> wps;
474 475 476 477
    foreach (Waypoint* wp, waypoints)
    {
        if (wp->getFrame() == MAV_FRAME_GLOBAL || wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT)
        {
478 479 480 481 482 483
            wps.append(wp);
        }
    }
    return wps;
}

lm's avatar
lm committed
484 485 486 487 488 489
const QVector<Waypoint *> UASWaypointManager::getGlobalFrameAndNavTypeWaypointList()
{
    // TODO Keep this global frame list up to date
    // with complete waypoint list
    // instead of filtering on each request
    QVector<Waypoint*> wps;
490 491 492 493
    foreach (Waypoint* wp, waypoints)
    {
        if ((wp->getFrame() == MAV_FRAME_GLOBAL || wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) && wp->isNavigationType())
        {
lm's avatar
lm committed
494 495 496 497 498 499
            wps.append(wp);
        }
    }
    return wps;
}

LM's avatar
LM committed
500 501 502 503 504 505
const QVector<Waypoint *> UASWaypointManager::getNavTypeWaypointList()
{
    // TODO Keep this global frame list up to date
    // with complete waypoint list
    // instead of filtering on each request
    QVector<Waypoint*> wps;
506 507 508 509
    foreach (Waypoint* wp, waypoints)
    {
        if (wp->isNavigationType())
        {
LM's avatar
LM committed
510 511 512 513 514 515
            wps.append(wp);
        }
    }
    return wps;
}

516 517 518 519 520
int UASWaypointManager::getIndexOf(Waypoint* wp)
{
    return waypoints.indexOf(wp);
}

521 522 523 524 525
int UASWaypointManager::getGlobalFrameIndexOf(Waypoint* wp)
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
526
    foreach (Waypoint* p, waypoints) {
527 528 529 530
        if (p->getFrame() == MAV_FRAME_GLOBAL || wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT)
        {
            if (p == wp)
            {
531 532 533 534 535 536 537 538 539
                return i;
            }
            i++;
        }
    }

    return -1;
}

lm's avatar
lm committed
540 541 542 543 544
int UASWaypointManager::getGlobalFrameAndNavTypeIndexOf(Waypoint* wp)
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
545
    foreach (Waypoint* p, waypoints) {
546
        if ((p->getFrame() == MAV_FRAME_GLOBAL || wp->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) && p->isNavigationType())
547 548 549
        {
            if (p == wp)
            {
lm's avatar
lm committed
550 551 552 553 554 555 556 557 558
                return i;
            }
            i++;
        }
    }

    return -1;
}

LM's avatar
LM committed
559 560 561 562 563
int UASWaypointManager::getNavTypeIndexOf(Waypoint* wp)
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
564 565 566 567 568 569
    foreach (Waypoint* p, waypoints)
    {
        if (p->isNavigationType())
        {
            if (p == wp)
            {
LM's avatar
LM committed
570 571 572 573 574 575 576 577 578
                return i;
            }
            i++;
        }
    }

    return -1;
}

579 580 581 582 583
int UASWaypointManager::getGlobalFrameCount()
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
584 585
    foreach (Waypoint* p, waypoints)
    {
586 587
        if (p->getFrame() == MAV_FRAME_GLOBAL || p->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT)
        {
588 589 590 591 592 593 594
            i++;
        }
    }

    return i;
}

lm's avatar
lm committed
595 596 597 598 599
int UASWaypointManager::getGlobalFrameAndNavTypeCount()
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
600
    foreach (Waypoint* p, waypoints) {
601
        if ((p->getFrame() == MAV_FRAME_GLOBAL || p->getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) && p->isNavigationType())
602
        {
lm's avatar
lm committed
603 604 605 606 607 608 609
            i++;
        }
    }

    return i;
}

LM's avatar
LM committed
610 611 612 613 614 615 616 617 618 619 620 621 622 623
int UASWaypointManager::getNavTypeCount()
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
    foreach (Waypoint* p, waypoints) {
        if (p->isNavigationType()) {
            i++;
        }
    }

    return i;
}

624 625 626 627 628
int UASWaypointManager::getLocalFrameCount()
{
    // Search through all waypoints,
    // counting only those in global frame
    int i = 0;
lm's avatar
lm committed
629 630
    foreach (Waypoint* p, waypoints)
    {
631
        if (p->getFrame() == MAV_FRAME_LOCAL_NED || p->getFrame() == MAV_FRAME_LOCAL_ENU)
lm's avatar
lm committed
632
        {
633 634 635 636 637 638 639 640 641 642 643 644
            i++;
        }
    }

    return i;
}

int UASWaypointManager::getLocalFrameIndexOf(Waypoint* wp)
{
    // Search through all waypoints,
    // counting only those in local frame
    int i = 0;
lm's avatar
lm committed
645 646 647 648
    foreach (Waypoint* p, waypoints)
    {
        if (p->getFrame() == MAV_FRAME_LOCAL_NED || p->getFrame() == MAV_FRAME_LOCAL_ENU)
        {
649 650
            if (p == wp)
            {
651 652 653 654 655 656 657 658 659 660 661 662 663 664
                return i;
            }
            i++;
        }
    }

    return -1;
}

int UASWaypointManager::getMissionFrameIndexOf(Waypoint* wp)
{
    // Search through all waypoints,
    // counting only those in mission frame
    int i = 0;
lm's avatar
lm committed
665 666
    foreach (Waypoint* p, waypoints)
    {
667 668 669 670
        if (p->getFrame() == MAV_FRAME_MISSION)
        {
            if (p == wp)
            {
671 672 673 674 675 676 677 678 679
                return i;
            }
            i++;
        }
    }

    return -1;
}

680 681
void UASWaypointManager::readWaypoints()
{
682
    emit readGlobalWPFromUAS(true);
683 684
    if(current_state == WP_IDLE) {
        while(waypoints.size()>0) {
685
            delete waypoints.back();
686
            waypoints.pop_back();
687

688 689
        }

690 691
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
692 693 694 695

        current_state = WP_GETLIST;
        current_wp_id = 0;
        current_partner_systemid = uas.getUASID();
lm's avatar
lm committed
696
        current_partner_compid = MAV_COMP_ID_MISSIONPLANNER;
pixhawk's avatar
pixhawk committed
697

698
        sendWaypointRequestList();
699

pixhawk's avatar
pixhawk committed
700 701 702
    }
}

703
void UASWaypointManager::writeWaypoints()
pixhawk's avatar
pixhawk committed
704
{
705
    if (current_state == WP_IDLE) {
pixhawk's avatar
pixhawk committed
706
        // Send clear all if count == 0
707
        if (waypoints.count() > 0) {
pixhawk's avatar
pixhawk committed
708
            protocol_timer.start(PROTOCOL_TIMEOUT_MS);
709
            current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
710

711
            current_count = waypoints.count();
pixhawk's avatar
pixhawk committed
712 713 714
            current_state = WP_SENDLIST;
            current_wp_id = 0;
            current_partner_systemid = uas.getUASID();
lm's avatar
lm committed
715
            current_partner_compid = MAV_COMP_ID_MISSIONPLANNER;
pixhawk's avatar
pixhawk committed
716 717

            //clear local buffer
pixhawk's avatar
pixhawk committed
718 719 720
            // Why not replace with waypoint_buffer.clear() ?
            // because this will lead to memory leaks, the waypoint-structs
            // have to be deleted, clear() would only delete the pointers.
721
            while(!waypoint_buffer.empty()) {
pixhawk's avatar
pixhawk committed
722 723 724
                delete waypoint_buffer.back();
                waypoint_buffer.pop_back();
            }
pixhawk's avatar
pixhawk committed
725

726 727
            bool noCurrent = true;

pixhawk's avatar
pixhawk committed
728
            //copy waypoint data to local buffer
729
            for (int i=0; i < current_count; i++) {
lm's avatar
lm committed
730 731 732
                waypoint_buffer.push_back(new mavlink_mission_item_t);
                mavlink_mission_item_t *cur_d = waypoint_buffer.back();
                memset(cur_d, 0, sizeof(mavlink_mission_item_t));   //initialize with zeros
733
                const Waypoint *cur_s = waypoints.at(i);
pixhawk's avatar
pixhawk committed
734 735

                cur_d->autocontinue = cur_s->getAutoContinue();
736
                cur_d->current = cur_s->getCurrent() & noCurrent;   //make sure only one current waypoint is selected, the first selected will be chosen
737 738
                cur_d->param1 = cur_s->getParam1();
                cur_d->param2 = cur_s->getParam2();
lm's avatar
lm committed
739 740
                cur_d->param3 = cur_s->getParam3();
                cur_d->param4 = cur_s->getParam4();
741
                cur_d->frame = cur_s->getFrame();
lm's avatar
lm committed
742
                cur_d->command = cur_s->getAction();
743
                cur_d->seq = i;     // don't read out the sequence number of the waypoint class
pixhawk's avatar
pixhawk committed
744 745 746
                cur_d->x = cur_s->getX();
                cur_d->y = cur_s->getY();
                cur_d->z = cur_s->getZ();
747 748 749

                if (cur_s->getCurrent() && noCurrent)
                    noCurrent = false;
750 751
                if (i == (current_count - 1) && noCurrent == true) //not a single waypoint was set as "current"
                    cur_d->current = true; // set the last waypoint as current. Or should it better be the first waypoint ?
pixhawk's avatar
pixhawk committed
752
            }
753

754 755 756



pixhawk's avatar
pixhawk committed
757
            //send the waypoint count to UAS (this starts the send transaction)
758
            sendWaypointCount();
pixhawk's avatar
pixhawk committed
759
        }
760
    } else if (waypoints.count() == 0) {
761
        sendWaypointClearAll();
762
    } else {
763
        //we're in another transaction, ignore command
764
        // // qDebug() << "UASWaypointManager::sendWaypoints() doing something else ignoring command";
765
    }
pixhawk's avatar
pixhawk committed
766 767
}

768 769 770
void UASWaypointManager::sendWaypointClearAll()
{
    mavlink_message_t message;
lm's avatar
lm committed
771
    mavlink_mission_clear_all_t wpca;
772 773

    wpca.target_system = uas.getUASID();
lm's avatar
lm committed
774
    wpca.target_component = MAV_COMP_ID_MISSIONPLANNER;
775

776
    emit updateStatusString(QString("Clearing waypoint list..."));
777

lm's avatar
lm committed
778
    mavlink_msg_mission_clear_all_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpca);
779
    uas.sendMessage(message);
780
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
781

782
    // // qDebug() << "sent waypoint clear all to ID " << wpca.target_system;
783 784 785 786 787
}

void UASWaypointManager::sendWaypointSetCurrent(quint16 seq)
{
    mavlink_message_t message;
lm's avatar
lm committed
788
    mavlink_mission_set_current_t wpsc;
789 790

    wpsc.target_system = uas.getUASID();
lm's avatar
lm committed
791
    wpsc.target_component = MAV_COMP_ID_MISSIONPLANNER;
792 793
    wpsc.seq = seq;

794
    emit updateStatusString(QString("Updating target waypoint..."));
795

lm's avatar
lm committed
796
    mavlink_msg_mission_set_current_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpsc);
797
    uas.sendMessage(message);
798
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
799

800
    // // qDebug() << "sent waypoint set current (" << wpsc.seq << ") to ID " << wpsc.target_system;
801 802 803 804 805
}

void UASWaypointManager::sendWaypointCount()
{
    mavlink_message_t message;
lm's avatar
lm committed
806
    mavlink_mission_count_t wpc;
807 808

    wpc.target_system = uas.getUASID();
lm's avatar
lm committed
809
    wpc.target_component = MAV_COMP_ID_MISSIONPLANNER;
810 811
    wpc.count = current_count;

812
    // // qDebug() << "sent waypoint count (" << wpc.count << ") to ID " << wpc.target_system;
813
    emit updateStatusString(QString("Starting to transmit waypoints..."));
814

lm's avatar
lm committed
815
    mavlink_msg_mission_count_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpc);
816
    uas.sendMessage(message);
817
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
818

819
    // // qDebug() << "sent waypoint count (" << wpc.count << ") to ID " << wpc.target_system;
820 821 822 823 824
}

void UASWaypointManager::sendWaypointRequestList()
{
    mavlink_message_t message;
lm's avatar
lm committed
825
    mavlink_mission_request_list_t wprl;
826 827

    wprl.target_system = uas.getUASID();
lm's avatar
lm committed
828
    wprl.target_component = MAV_COMP_ID_MISSIONPLANNER;
829

830
    emit updateStatusString(QString("Requesting waypoint list..."));
831

lm's avatar
lm committed
832
    mavlink_msg_mission_request_list_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wprl);
833
    uas.sendMessage(message);
834
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
835

836
    // // qDebug() << "sent waypoint list request to ID " << wprl.target_system;
837 838


839 840
}

841
void UASWaypointManager::sendWaypointRequest(quint16 seq)
pixhawk's avatar
pixhawk committed
842
{
843
    mavlink_message_t message;
lm's avatar
lm committed
844
    mavlink_mission_request_t wpr;
845 846

    wpr.target_system = uas.getUASID();
lm's avatar
lm committed
847
    wpr.target_component = MAV_COMP_ID_MISSIONPLANNER;
848 849
    wpr.seq = seq;

850
    emit updateStatusString(QString("Retrieving waypoint ID %1 of %2 total").arg(wpr.seq).arg(current_count));
pixhawk's avatar
pixhawk committed
851

lm's avatar
lm committed
852
    mavlink_msg_mission_request_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpr);
853
    uas.sendMessage(message);
854
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
855

856
    // // qDebug() << "sent waypoint request (" << wpr.seq << ") to ID " << wpr.target_system;
pixhawk's avatar
pixhawk committed
857
}
pixhawk's avatar
pixhawk committed
858

pixhawk's avatar
pixhawk committed
859 860 861
void UASWaypointManager::sendWaypoint(quint16 seq)
{
    mavlink_message_t message;
862
    // // qDebug() <<" WP Buffer count: "<<waypoint_buffer.count();
pixhawk's avatar
pixhawk committed
863

864
    if (seq < waypoint_buffer.count()) {
865

lm's avatar
lm committed
866
        mavlink_mission_item_t *wp;
pixhawk's avatar
pixhawk committed
867

868

pixhawk's avatar
pixhawk committed
869 870
        wp = waypoint_buffer.at(seq);
        wp->target_system = uas.getUASID();
lm's avatar
lm committed
871
        wp->target_component = MAV_COMP_ID_MISSIONPLANNER;
pixhawk's avatar
pixhawk committed
872

873
        emit updateStatusString(QString("Sending waypoint ID %1 of %2 total").arg(wp->seq).arg(current_count));
pixhawk's avatar
pixhawk committed
874

875
        // // qDebug() << "sent waypoint (" << wp->seq << ") to ID " << wp->target_system<<" WP Buffer count: "<<waypoint_buffer.count();
876

lm's avatar
lm committed
877
        mavlink_msg_mission_item_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, wp);
pixhawk's avatar
pixhawk committed
878
        uas.sendMessage(message);
879
        MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
pixhawk's avatar
pixhawk committed
880 881

    }
pixhawk's avatar
pixhawk committed
882
}
883 884 885 886

void UASWaypointManager::sendWaypointAck(quint8 type)
{
    mavlink_message_t message;
lm's avatar
lm committed
887
    mavlink_mission_ack_t wpa;
888 889

    wpa.target_system = uas.getUASID();
lm's avatar
lm committed
890
    wpa.target_component = MAV_COMP_ID_MISSIONPLANNER;
891 892
    wpa.type = type;

lm's avatar
lm committed
893
    mavlink_msg_mission_ack_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpa);
894
    uas.sendMessage(message);
895
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
896

897
    // // qDebug() << "sent waypoint ack (" << wpa.type << ") to ID " << wpa.target_system;
898
}