UASWaypointManager.cc 14.8 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*=====================================================================

PIXHAWK Micro Air Vehicle Flying Robotics Toolkit

(c) 2009, 2010 PIXHAWK PROJECT  <http://pixhawk.ethz.ch>

This file is part of the PIXHAWK project

    PIXHAWK is free software: you can redistribute it and/or modify
    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.

    PIXHAWK is distributed in the hope that it will be useful,
    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
    along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.

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

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

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

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

39
UASWaypointManager::UASWaypointManager(UAS &_uas)
pixhawk's avatar
pixhawk committed
40
        : uas(_uas),
41
        current_retries(0),
pixhawk's avatar
pixhawk committed
42 43 44 45
        current_wp_id(0),
        current_count(0),
        current_state(WP_IDLE),
        current_partner_systemid(0),
pixhawk's avatar
pixhawk committed
46 47 48 49 50 51 52
        current_partner_compid(0),
        protocol_timer(this)
{
    connect(&protocol_timer, SIGNAL(timeout()), this, SLOT(timeout()));
}

void UASWaypointManager::timeout()
53
{
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    if (current_retries > 0)
    {
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries--;
        qDebug() << "Timeout, retrying (retries left:" << current_retries << ")";
        if (current_state == WP_GETLIST)
        {
            sendWaypointRequestList();
        }
        else if (current_state == WP_GETLIST_GETWPS)
        {
            sendWaypointRequest(current_wp_id);
        }
        else if (current_state == WP_SENDLIST)
        {
            sendWaypointCount();
        }
        else if (current_state == WP_SENDLIST_SENDWPS)
        {
            sendWaypoint(current_wp_id);
        }
        else if (current_state == WP_CLEARLIST)
        {
            sendWaypointClearAll();
        }
        else if (current_state == WP_SETCURRENT)
        {
            sendWaypointSetCurrent(current_wp_id);
        }
    }
    else
    {
        protocol_timer.stop();
pixhawk's avatar
pixhawk committed
87

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

90
        emit updateStatusString("Operation timed out.");
pixhawk's avatar
pixhawk committed
91

92 93 94 95 96 97
        current_state = WP_IDLE;
        current_count = 0;
        current_wp_id = 0;
        current_partner_systemid = 0;
        current_partner_compid = 0;
    }
98 99 100 101 102 103
}

void UASWaypointManager::handleWaypointCount(quint8 systemId, quint8 compId, quint16 count)
{
    if (current_state == WP_GETLIST && systemId == current_partner_systemid && compId == current_partner_compid)
    {
104 105 106
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;

107
        qDebug() << "got waypoint count (" << count << ") from ID " << systemId;
pixhawk's avatar
pixhawk committed
108

pixhawk's avatar
pixhawk committed
109 110 111 112 113
        if (count > 0)
        {
            current_count = count;
            current_wp_id = 0;
            current_state = WP_GETLIST_GETWPS;
114

pixhawk's avatar
pixhawk committed
115 116 117 118 119 120 121
            sendWaypointRequest(current_wp_id);
        }
        else
        {
            emit updateStatusString("done.");
            qDebug() << "No waypoints on UAS " << systemId;
        }
122 123 124
    }
}

pixhawk's avatar
pixhawk committed
125 126 127 128
void UASWaypointManager::handleWaypoint(quint8 systemId, quint8 compId, mavlink_waypoint_t *wp)
{
    if (systemId == current_partner_systemid && compId == current_partner_compid && current_state == WP_GETLIST_GETWPS && wp->seq == current_wp_id)
    {
129 130 131
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;

pixhawk's avatar
pixhawk committed
132 133 134
        if(wp->seq == current_wp_id)
        {
            //update the UI FIXME
135
            emit waypointUpdated(wp->seq, wp->x, wp->y, wp->z, wp->yaw, wp->autocontinue, wp->current, wp->param1, wp->param2);
pixhawk's avatar
pixhawk committed
136 137 138 139 140 141

            //get next waypoint
            current_wp_id++;

            if(current_wp_id < current_count)
            {
142
                sendWaypointRequest(current_wp_id);
pixhawk's avatar
pixhawk committed
143 144 145
            }
            else
            {
146 147
                sendWaypointAck(0);

pixhawk's avatar
pixhawk committed
148
                // all waypoints retrieved, change state to idle
pixhawk's avatar
pixhawk committed
149 150 151 152 153
                current_state = WP_IDLE;
                current_count = 0;
                current_wp_id = 0;
                current_partner_systemid = 0;
                current_partner_compid = 0;
154

pixhawk's avatar
pixhawk committed
155
                protocol_timer.stop();
156 157
                emit updateStatusString("done.");

pixhawk's avatar
pixhawk committed
158
                qDebug() << "got all waypoints from ID " << systemId;
pixhawk's avatar
pixhawk committed
159 160 161 162
            }
        }
        else
        {
pixhawk's avatar
pixhawk committed
163
            //TODO: error handling
pixhawk's avatar
pixhawk committed
164 165 166 167
        }
    }
}

168 169
void UASWaypointManager::handleWaypointAck(quint8 systemId, quint8 compId, mavlink_waypoint_ack_t *wpa)
{
170
    if (systemId == current_partner_systemid && compId == current_partner_compid)
171
    {
172
        if((current_state == WP_SENDLIST || current_state == WP_SENDLIST_SENDWPS) && (current_wp_id == waypoint_buffer.count()-1 && wpa->type == 0))
173 174 175
        {
            //all waypoints sent and ack received
            protocol_timer.stop();
176
            current_state = WP_IDLE;
177 178 179
            emit updateStatusString("done.");
            qDebug() << "sent all waypoints to ID " << systemId;
        }
180 181 182 183 184 185 186
        else if(current_state == WP_CLEARLIST)
        {
            protocol_timer.stop();
            current_state = WP_IDLE;
            emit updateStatusString("done.");
            qDebug() << "cleared waypoint list of ID " << systemId;
        }
187 188 189
    }
}

pixhawk's avatar
pixhawk committed
190
void UASWaypointManager::handleWaypointRequest(quint8 systemId, quint8 compId, mavlink_waypoint_request_t *wpr)
191
{
192
    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))))
pixhawk's avatar
pixhawk committed
193
    {
194 195
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;
196

197
        if (wpr->seq < waypoint_buffer.count())
pixhawk's avatar
pixhawk committed
198
        {
pixhawk's avatar
pixhawk committed
199 200 201
            current_state = WP_SENDLIST_SENDWPS;
            current_wp_id = wpr->seq;
            sendWaypoint(current_wp_id);
pixhawk's avatar
pixhawk committed
202 203 204 205 206 207
        }
        else
        {
            //TODO: Error message or something
        }
    }
208 209
}

pixhawk's avatar
pixhawk committed
210
void UASWaypointManager::handleWaypointReached(quint8 systemId, quint8 compId, mavlink_waypoint_reached_t *wpr)
211
{
pixhawk's avatar
pixhawk committed
212 213 214 215
    if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
    {
        emit updateStatusString(QString("Reached waypoint %1").arg(wpr->seq));
    }
pixhawk's avatar
pixhawk committed
216 217
}

218
void UASWaypointManager::handleWaypointCurrent(quint8 systemId, quint8 compId, mavlink_waypoint_current_t *wpc)
pixhawk's avatar
pixhawk committed
219
{
pixhawk's avatar
pixhawk committed
220 221
    if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
    {
222 223 224 225 226 227
        if (current_state == WP_SETCURRENT)
        {
            protocol_timer.stop();
            current_state = WP_IDLE;
            emit updateStatusString(QString("New current waypoint %1").arg(wpc->seq));
        }
228 229
        qDebug() << "new current waypoint" << wpc->seq;
        emit currentWaypointChanged(wpc->seq);
pixhawk's avatar
pixhawk committed
230
    }
pixhawk's avatar
pixhawk committed
231 232
}

pixhawk's avatar
pixhawk committed
233
void UASWaypointManager::clearWaypointList()
pixhawk's avatar
pixhawk committed
234
{
235 236 237
    if(current_state == WP_IDLE)
    {
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
238
        current_retries = PROTOCOL_MAX_RETRIES;
239 240 241 242 243 244

        current_state = WP_CLEARLIST;
        current_wp_id = 0;
        current_partner_systemid = uas.getUASID();
        current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;

245
        sendWaypointClearAll();
246
    }
pixhawk's avatar
pixhawk committed
247 248
}

249
void UASWaypointManager::setCurrent(quint16 seq)
pixhawk's avatar
pixhawk committed
250 251 252
{
    if(current_state == WP_IDLE)
    {
pixhawk's avatar
pixhawk committed
253
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
254
        current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
255

256 257 258 259
        current_state = WP_SETCURRENT;
        current_wp_id = seq;
        current_partner_systemid = uas.getUASID();
        current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;
pixhawk's avatar
pixhawk committed
260

261 262 263 264 265 266 267 268 269 270
        sendWaypointSetCurrent(current_wp_id);
    }
}

void UASWaypointManager::readWaypoints()
{
    if(current_state == WP_IDLE)
    {
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
        current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
271 272 273 274 275 276

        current_state = WP_GETLIST;
        current_wp_id = 0;
        current_partner_systemid = uas.getUASID();
        current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;

277
        sendWaypointRequestList();
pixhawk's avatar
pixhawk committed
278 279 280
    }
}

281
void UASWaypointManager::writeWaypoints()
pixhawk's avatar
pixhawk committed
282
{
283 284
    if (current_state == WP_IDLE)
    {
285
        if (waypoints.count() > 0)
286
        {
pixhawk's avatar
pixhawk committed
287
            protocol_timer.start(PROTOCOL_TIMEOUT_MS);
288
            current_retries = PROTOCOL_MAX_RETRIES;
pixhawk's avatar
pixhawk committed
289

290
            current_count = waypoints.count();
pixhawk's avatar
pixhawk committed
291 292 293 294 295 296 297 298 299 300 301
            current_state = WP_SENDLIST;
            current_wp_id = 0;
            current_partner_systemid = uas.getUASID();
            current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;

            //clear local buffer
            while(!waypoint_buffer.empty())
            {
                delete waypoint_buffer.back();
                waypoint_buffer.pop_back();
            }
pixhawk's avatar
pixhawk committed
302

pixhawk's avatar
pixhawk committed
303 304 305 306 307 308
            //copy waypoint data to local buffer
            for (int i=0; i < current_count; i++)
            {
                waypoint_buffer.push_back(new mavlink_waypoint_t);
                mavlink_waypoint_t *cur_d = waypoint_buffer.back();
                memset(cur_d, 0, sizeof(mavlink_waypoint_t));   //initialize with zeros
309
                const Waypoint *cur_s = waypoints.at(i);
pixhawk's avatar
pixhawk committed
310 311 312

                cur_d->autocontinue = cur_s->getAutoContinue();
                cur_d->current = cur_s->getCurrent();
lm's avatar
lm committed
313 314
                cur_d->orbit = 0;
                cur_d->orbit_direction = 0;
315 316
                cur_d->param1 = cur_s->getOrbit();
                cur_d->param2 = cur_s->getHoldTime();
pixhawk's avatar
pixhawk committed
317
                cur_d->type = 1;        //FIXME
pixhawk's avatar
pixhawk committed
318 319 320 321 322 323
                cur_d->seq = i;
                cur_d->x = cur_s->getX();
                cur_d->y = cur_s->getY();
                cur_d->z = cur_s->getZ();
                cur_d->yaw = cur_s->getYaw();
            }
324

pixhawk's avatar
pixhawk committed
325
            //send the waypoint count to UAS (this starts the send transaction)
326
            sendWaypointCount();
pixhawk's avatar
pixhawk committed
327
        }
328 329 330 331 332 333
    }
    else
    {
        //we're in another transaction, ignore command
        qDebug() << "UASWaypointManager::sendWaypoints() doing something else ignoring command";
    }
pixhawk's avatar
pixhawk committed
334 335
}

336 337 338 339 340 341 342 343 344 345 346 347 348
void UASWaypointManager::sendWaypointClearAll()
{
    mavlink_message_t message;
    mavlink_waypoint_clear_all_t wpca;

    wpca.target_system = uas.getUASID();
    wpca.target_component = MAV_COMP_ID_WAYPOINTPLANNER;

    const QString str = QString("clearing waypoint list...");
    emit updateStatusString(str);

    mavlink_msg_waypoint_clear_all_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpca);
    uas.sendMessage(message);
349
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367

    qDebug() << "sent waypoint clear all to ID " << wpca.target_system;
}

void UASWaypointManager::sendWaypointSetCurrent(quint16 seq)
{
    mavlink_message_t message;
    mavlink_waypoint_set_current_t wpsc;

    wpsc.target_system = uas.getUASID();
    wpsc.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
    wpsc.seq = seq;

    const QString str = QString("Updating target waypoint...");
    emit updateStatusString(str);

    mavlink_msg_waypoint_set_current_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpsc);
    uas.sendMessage(message);
368
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

    qDebug() << "sent waypoint set current (" << wpsc.seq << ") to ID " << wpsc.target_system;
}

void UASWaypointManager::sendWaypointCount()
{
    mavlink_message_t message;
    mavlink_waypoint_count_t wpc;

    wpc.target_system = uas.getUASID();
    wpc.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
    wpc.count = current_count;

    const QString str = QString("start transmitting waypoints...");
    emit updateStatusString(str);

    mavlink_msg_waypoint_count_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpc);
    uas.sendMessage(message);
387
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

    qDebug() << "sent waypoint count (" << wpc.count << ") to ID " << wpc.target_system;
}

void UASWaypointManager::sendWaypointRequestList()
{
    mavlink_message_t message;
    mavlink_waypoint_request_list_t wprl;

    wprl.target_system = uas.getUASID();
    wprl.target_component = MAV_COMP_ID_WAYPOINTPLANNER;

    const QString str = QString("requesting waypoint list...");
    emit updateStatusString(str);

    mavlink_msg_waypoint_request_list_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wprl);
    uas.sendMessage(message);
405
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
406 407 408 409

    qDebug() << "sent waypoint list request to ID " << wprl.target_system;
}

410
void UASWaypointManager::sendWaypointRequest(quint16 seq)
pixhawk's avatar
pixhawk committed
411
{
412 413 414 415 416 417 418
    mavlink_message_t message;
    mavlink_waypoint_request_t wpr;

    wpr.target_system = uas.getUASID();
    wpr.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
    wpr.seq = seq;

pixhawk's avatar
pixhawk committed
419 420 421
    const QString str = QString("retrieving waypoint ID %1 of %2 total").arg(wpr.seq).arg(current_count);
    emit updateStatusString(str);

422 423
    mavlink_msg_waypoint_request_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpr);
    uas.sendMessage(message);
424
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
425 426

    qDebug() << "sent waypoint request (" << wpr.seq << ") to ID " << wpr.target_system;
pixhawk's avatar
pixhawk committed
427
}
pixhawk's avatar
pixhawk committed
428

pixhawk's avatar
pixhawk committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
void UASWaypointManager::sendWaypoint(quint16 seq)
{
    mavlink_message_t message;

    if (seq < waypoint_buffer.count())
    {
        mavlink_waypoint_t *wp;

        wp = waypoint_buffer.at(seq);
        wp->target_system = uas.getUASID();
        wp->target_component = MAV_COMP_ID_WAYPOINTPLANNER;

        const QString str = QString("sending waypoint ID %1 of %2 total").arg(wp->seq).arg(current_count);
        emit updateStatusString(str);

        mavlink_msg_waypoint_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, wp);
        uas.sendMessage(message);
446
        MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
pixhawk's avatar
pixhawk committed
447 448 449

        qDebug() << "sent waypoint (" << wp->seq << ") to ID " << wp->target_system;
    }
pixhawk's avatar
pixhawk committed
450
}
451 452 453 454 455 456 457 458 459 460 461 462

void UASWaypointManager::sendWaypointAck(quint8 type)
{
    mavlink_message_t message;
    mavlink_waypoint_ack_t wpa;

    wpa.target_system = uas.getUASID();
    wpa.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
    wpa.type = type;

    mavlink_msg_waypoint_ack_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpa);
    uas.sendMessage(message);
463
    MG::SLEEP::usleep(PROTOCOL_DELAY_MS * 1000);
464 465 466

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