Newer
Older
/*=====================================================================
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>
*
*/
#include "UASWaypointManager.h"
#include "UAS.h"
#define PROTOCOL_TIMEOUT_MS 2000 ///< maximum time to wait for pending messages until timeout
#define PROTOCOL_DELAY_MS 40 ///< minimum delay between sent messages
#define PROTOCOL_MAX_RETRIES 3 ///< maximum number of send retries (after timeout)
UASWaypointManager::UASWaypointManager(UAS &_uas)
current_retries(0),
current_wp_id(0),
current_count(0),
current_state(WP_IDLE),
current_partner_systemid(0),
current_partner_compid(0),
protocol_timer(this)
{
connect(&protocol_timer, SIGNAL(timeout()), this, SLOT(timeout()));
}
void UASWaypointManager::timeout()
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();
qDebug() << "Waypoint transaction (state=" << current_state << ") timed out going to state WP_IDLE";
emit updateStatusString("Operation timed out.");
current_state = WP_IDLE;
current_count = 0;
current_wp_id = 0;
current_partner_systemid = 0;
current_partner_compid = 0;
}
}
void UASWaypointManager::handleWaypointCount(quint8 systemId, quint8 compId, quint16 count)
{
if (current_state == WP_GETLIST && systemId == current_partner_systemid && compId == current_partner_compid)
{
protocol_timer.start(PROTOCOL_TIMEOUT_MS);
current_retries = PROTOCOL_MAX_RETRIES;
qDebug() << "got waypoint count (" << count << ") from ID " << systemId;
if (count > 0)
{
current_count = count;
current_wp_id = 0;
current_state = WP_GETLIST_GETWPS;
sendWaypointRequest(current_wp_id);
}
else
{
emit updateStatusString("done.");
qDebug() << "No waypoints on UAS " << systemId;
}
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)
{
protocol_timer.start(PROTOCOL_TIMEOUT_MS);
current_retries = PROTOCOL_MAX_RETRIES;
emit waypointUpdated(wp->seq, wp->x, wp->y, wp->z, wp->yaw, wp->autocontinue, wp->current, wp->param1, wp->param2);
//get next waypoint
current_wp_id++;
if(current_wp_id < current_count)
{
sendWaypointRequest(current_wp_id);
sendWaypointAck(0);
current_state = WP_IDLE;
current_count = 0;
current_wp_id = 0;
current_partner_systemid = 0;
current_partner_compid = 0;
emit updateStatusString("done.");
qDebug() << "got all waypoints from ID " << systemId;
void UASWaypointManager::handleWaypointAck(quint8 systemId, quint8 compId, mavlink_waypoint_ack_t *wpa)
{
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))
{
//all waypoints sent and ack received
protocol_timer.stop();
current_state = WP_IDLE;
emit updateStatusString("done.");
qDebug() << "sent all waypoints to ID " << systemId;
}
else if(current_state == WP_CLEARLIST)
{
protocol_timer.stop();
current_state = WP_IDLE;
emit updateStatusString("done.");
qDebug() << "cleared waypoint list of ID " << systemId;
}
void UASWaypointManager::handleWaypointRequest(quint8 systemId, quint8 compId, mavlink_waypoint_request_t *wpr)
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))))
protocol_timer.start(PROTOCOL_TIMEOUT_MS);
current_retries = PROTOCOL_MAX_RETRIES;
if (wpr->seq < waypoint_buffer.count())
current_state = WP_SENDLIST_SENDWPS;
current_wp_id = wpr->seq;
sendWaypoint(current_wp_id);
void UASWaypointManager::handleWaypointReached(quint8 systemId, quint8 compId, mavlink_waypoint_reached_t *wpr)
if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
{
emit updateStatusString(QString("Reached waypoint %1").arg(wpr->seq));
}
pixhawk
committed
void UASWaypointManager::handleWaypointCurrent(quint8 systemId, quint8 compId, mavlink_waypoint_current_t *wpc)
if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
{
if (current_state == WP_SETCURRENT)
{
protocol_timer.stop();
current_state = WP_IDLE;
emit updateStatusString(QString("New current waypoint %1").arg(wpc->seq));
}
pixhawk
committed
qDebug() << "new current waypoint" << wpc->seq;
emit currentWaypointChanged(wpc->seq);
if(current_state == WP_IDLE)
{
protocol_timer.start(PROTOCOL_TIMEOUT_MS);
current_retries = PROTOCOL_MAX_RETRIES;
current_state = WP_CLEARLIST;
current_wp_id = 0;
current_partner_systemid = uas.getUASID();
current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;
sendWaypointClearAll();
void UASWaypointManager::setCurrent(quint16 seq)
current_retries = PROTOCOL_MAX_RETRIES;
current_state = WP_SETCURRENT;
current_wp_id = seq;
current_partner_systemid = uas.getUASID();
current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;
sendWaypointSetCurrent(current_wp_id);
}
}
void UASWaypointManager::readWaypoints()
{
if(current_state == WP_IDLE)
{
protocol_timer.start(PROTOCOL_TIMEOUT_MS);
current_retries = PROTOCOL_MAX_RETRIES;
current_state = WP_GETLIST;
current_wp_id = 0;
current_partner_systemid = uas.getUASID();
current_partner_compid = MAV_COMP_ID_WAYPOINTPLANNER;
sendWaypointRequestList();
void UASWaypointManager::writeWaypoints()
if (current_state == WP_IDLE)
{
if (waypoints.count() > 0)
current_retries = PROTOCOL_MAX_RETRIES;
current_count = waypoints.count();
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();
}
//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
const Waypoint *cur_s = waypoints.at(i);
cur_d->autocontinue = cur_s->getAutoContinue();
cur_d->current = cur_s->getCurrent();
cur_d->param1 = cur_s->getOrbit();
cur_d->param2 = cur_s->getHoldTime();
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();
}
//send the waypoint count to UAS (this starts the send transaction)
sendWaypointCount();
}
else
{
//we're in another transaction, ignore command
qDebug() << "UASWaypointManager::sendWaypoints() doing something else ignoring command";
}
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
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);
usleep(PROTOCOL_DELAY_MS * 1000);
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);
usleep(PROTOCOL_DELAY_MS * 1000);
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);
usleep(PROTOCOL_DELAY_MS * 1000);
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);
usleep(PROTOCOL_DELAY_MS * 1000);
qDebug() << "sent waypoint list request to ID " << wprl.target_system;
}
void UASWaypointManager::sendWaypointRequest(quint16 seq)
mavlink_message_t message;
mavlink_waypoint_request_t wpr;
wpr.target_system = uas.getUASID();
wpr.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
wpr.seq = seq;
const QString str = QString("retrieving waypoint ID %1 of %2 total").arg(wpr.seq).arg(current_count);
emit updateStatusString(str);
mavlink_msg_waypoint_request_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpr);
uas.sendMessage(message);
usleep(PROTOCOL_DELAY_MS * 1000);
qDebug() << "sent waypoint request (" << wpr.seq << ") to ID " << wpr.target_system;
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);
usleep(PROTOCOL_DELAY_MS * 1000);
qDebug() << "sent waypoint (" << wp->seq << ") to ID " << wp->target_system;
}
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);
usleep(PROTOCOL_DELAY_MS * 1000);
qDebug() << "sent waypoint ack (" << wpa.type << ") to ID " << wpa.target_system;
}