UASWaypointManager.cc 10 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"

pixhawk's avatar
pixhawk committed
35 36
#define PROTOCOL_TIMEOUT_MS 2000

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

void UASWaypointManager::timeout()
50
{
pixhawk's avatar
pixhawk committed
51 52 53 54 55 56 57 58 59 60 61
    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;
62 63 64 65
}

void UASWaypointManager::handleWaypointCount(quint8 systemId, quint8 compId, quint16 count)
{
pixhawk's avatar
pixhawk committed
66 67
    protocol_timer.start(PROTOCOL_TIMEOUT_MS);

68 69
    if (current_state == WP_GETLIST && systemId == current_partner_systemid && compId == current_partner_compid)
    {
70
        qDebug() << "got waypoint count (" << count << ") from ID " << systemId;
pixhawk's avatar
pixhawk committed
71

pixhawk's avatar
pixhawk committed
72 73 74 75 76
        if (count > 0)
        {
            current_count = count;
            current_wp_id = 0;
            current_state = WP_GETLIST_GETWPS;
77

pixhawk's avatar
pixhawk committed
78 79 80 81 82 83 84
            sendWaypointRequest(current_wp_id);
        }
        else
        {
            emit updateStatusString("done.");
            qDebug() << "No waypoints on UAS " << systemId;
        }
85 86 87
    }
}

pixhawk's avatar
pixhawk committed
88 89
void UASWaypointManager::handleWaypoint(quint8 systemId, quint8 compId, mavlink_waypoint_t *wp)
{
pixhawk's avatar
pixhawk committed
90 91
    protocol_timer.start(PROTOCOL_TIMEOUT_MS);

pixhawk's avatar
pixhawk committed
92 93 94 95 96
    if (systemId == current_partner_systemid && compId == current_partner_compid && current_state == WP_GETLIST_GETWPS && wp->seq == current_wp_id)
    {
        if(wp->seq == current_wp_id)
        {
            //update the UI FIXME
pixhawk's avatar
pixhawk committed
97
            emit waypointUpdated(uas.getUASID(), wp->seq, wp->x, wp->y, wp->z, wp->yaw, wp->autocontinue, wp->current, wp->orbit, wp->hold_time);
pixhawk's avatar
pixhawk committed
98 99 100 101 102 103

            //get next waypoint
            current_wp_id++;

            if(current_wp_id < current_count)
            {
104
                sendWaypointRequest(current_wp_id);
pixhawk's avatar
pixhawk committed
105 106 107
            }
            else
            {
pixhawk's avatar
pixhawk committed
108
                // all waypoints retrieved, change state to idle
pixhawk's avatar
pixhawk committed
109 110 111 112 113
                current_state = WP_IDLE;
                current_count = 0;
                current_wp_id = 0;
                current_partner_systemid = 0;
                current_partner_compid = 0;
114

pixhawk's avatar
pixhawk committed
115
                protocol_timer.stop();
116 117
                emit updateStatusString("done.");

pixhawk's avatar
pixhawk committed
118
                qDebug() << "got all waypoints from ID " << systemId;
pixhawk's avatar
pixhawk committed
119 120 121 122
            }
        }
        else
        {
pixhawk's avatar
pixhawk committed
123
            //TODO: error handling
pixhawk's avatar
pixhawk committed
124 125 126 127
        }
    }
}

pixhawk's avatar
pixhawk committed
128
void UASWaypointManager::handleWaypointRequest(quint8 systemId, quint8 compId, mavlink_waypoint_request_t *wpr)
129
{
pixhawk's avatar
pixhawk committed
130 131
    protocol_timer.start(PROTOCOL_TIMEOUT_MS);

pixhawk's avatar
pixhawk committed
132
    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)) || (current_state == WP_IDLE && wpr->seq == current_count-1)))
pixhawk's avatar
pixhawk committed
133 134
    {
        qDebug() << "handleWaypointRequest";
135

136
        if (wpr->seq < waypoint_buffer.count())
pixhawk's avatar
pixhawk committed
137
        {
pixhawk's avatar
pixhawk committed
138 139 140 141 142 143 144 145 146
            current_state = WP_SENDLIST_SENDWPS;
            current_wp_id = wpr->seq;
            sendWaypoint(current_wp_id);

            if(current_wp_id == waypoint_buffer.count()-1)
            {
                //all waypoints sent, but we still have to wait for a possible rerequest of the last waypoint
                current_state = WP_IDLE;

pixhawk's avatar
pixhawk committed
147
                protocol_timer.stop();
pixhawk's avatar
pixhawk committed
148 149 150 151
                emit updateStatusString("done.");

                qDebug() << "send all waypoints to ID " << systemId;
            }
pixhawk's avatar
pixhawk committed
152 153 154 155 156 157
        }
        else
        {
            //TODO: Error message or something
        }
    }
158 159
}

pixhawk's avatar
pixhawk committed
160
void UASWaypointManager::handleWaypointReached(quint8 systemId, quint8 compId, mavlink_waypoint_reached_t *wpr)
161
{
pixhawk's avatar
pixhawk committed
162 163 164 165
    if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
    {
        emit updateStatusString(QString("Reached waypoint %1").arg(wpr->seq));
    }
pixhawk's avatar
pixhawk committed
166 167
}

pixhawk's avatar
pixhawk committed
168
void UASWaypointManager::handleWaypointSetCurrent(quint8 systemId, quint8 compId, mavlink_waypoint_set_current_t *wpr)
pixhawk's avatar
pixhawk committed
169
{
pixhawk's avatar
pixhawk committed
170 171 172 173 174
    if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
    {
        qDebug() << "new current waypoint" << wpr->seq;
        emit currentWaypointChanged(wpr->seq);
    }
pixhawk's avatar
pixhawk committed
175 176
}

pixhawk's avatar
pixhawk committed
177
void UASWaypointManager::clearWaypointList()
pixhawk's avatar
pixhawk committed
178 179 180 181 182 183 184 185
{

}

void UASWaypointManager::requestWaypoints()
{
    if(current_state == WP_IDLE)
    {
pixhawk's avatar
pixhawk committed
186 187
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);

pixhawk's avatar
pixhawk committed
188 189 190 191 192 193 194 195 196 197 198
        mavlink_message_t message;
        mavlink_waypoint_request_list_t wprl;

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

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

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

pixhawk's avatar
pixhawk committed
202
        mavlink_msg_waypoint_request_list_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wprl);
pixhawk's avatar
pixhawk committed
203 204 205
        uas.sendMessage(message);

        qDebug() << "sent waypoint list request to ID " << wprl.target_system;
pixhawk's avatar
pixhawk committed
206 207 208
    }
}

209
void UASWaypointManager::sendWaypoints(const QVector<Waypoint*> &list)
pixhawk's avatar
pixhawk committed
210
{
211 212
    if (current_state == WP_IDLE)
    {
pixhawk's avatar
pixhawk committed
213
        if (list.count() > 0)
214
        {
pixhawk's avatar
pixhawk committed
215 216
            protocol_timer.start(PROTOCOL_TIMEOUT_MS);

pixhawk's avatar
pixhawk committed
217 218 219 220 221 222 223 224 225 226 227 228
            current_count = list.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();
            }
pixhawk's avatar
pixhawk committed
229

pixhawk's avatar
pixhawk committed
230 231 232 233 234 235 236 237 238 239
            //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 = list.at(i);

                cur_d->autocontinue = cur_s->getAutoContinue();
                cur_d->current = cur_s->getCurrent();
pixhawk's avatar
pixhawk committed
240 241
                cur_d->orbit = cur_s->getOrbit();
                cur_d->hold_time = cur_s->getHoldTime();
pixhawk's avatar
pixhawk committed
242
                cur_d->type = 1;        //FIXME
pixhawk's avatar
pixhawk committed
243 244 245 246 247 248
                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();
            }
249

pixhawk's avatar
pixhawk committed
250 251 252
            //send the waypoint count to UAS (this starts the send transaction)
            mavlink_message_t message;
            mavlink_waypoint_count_t wpc;
253

pixhawk's avatar
pixhawk committed
254 255 256
            wpc.target_system = uas.getUASID();
            wpc.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
            wpc.count = current_count;
257

pixhawk's avatar
pixhawk committed
258 259 260 261 262
            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);
263

pixhawk's avatar
pixhawk committed
264 265
            qDebug() << "sent waypoint count (" << wpc.count << ") to ID " << wpc.target_system;
        }
266 267 268 269 270 271
    }
    else
    {
        //we're in another transaction, ignore command
        qDebug() << "UASWaypointManager::sendWaypoints() doing something else ignoring command";
    }
pixhawk's avatar
pixhawk committed
272 273
}

274
void UASWaypointManager::sendWaypointRequest(quint16 seq)
pixhawk's avatar
pixhawk committed
275
{
276 277 278 279 280 281 282
    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
283 284 285
    const QString str = QString("retrieving waypoint ID %1 of %2 total").arg(wpr.seq).arg(current_count);
    emit updateStatusString(str);

286 287 288 289
    mavlink_msg_waypoint_request_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wpr);
    uas.sendMessage(message);

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

pixhawk's avatar
pixhawk committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
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);

        qDebug() << "sent waypoint (" << wp->seq << ") to ID " << wp->target_system;
    }
pixhawk's avatar
pixhawk committed
312
}