Skip to content
Snippets Groups Projects
UASWaypointManager.cc 9.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • pixhawk's avatar
    pixhawk committed
    /*=====================================================================
    
    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"
    
    
    pixhawk's avatar
    pixhawk committed
    #define PROTOCOL_TIMEOUT_MS 2000
    
    
    UASWaypointManager::UASWaypointManager(UAS &_uas)
    
    pixhawk's avatar
    pixhawk committed
            : uas(_uas),
            current_wp_id(0),
            current_count(0),
            current_state(WP_IDLE),
            current_partner_systemid(0),
    
    pixhawk's avatar
    pixhawk committed
            current_partner_compid(0),
            protocol_timer(this)
    {
        connect(&protocol_timer, SIGNAL(timeout()), this, SLOT(timeout()));
    }
    
    void UASWaypointManager::timeout()
    
    pixhawk's avatar
    pixhawk committed
        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)
    {
    
    pixhawk's avatar
    pixhawk committed
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
    
    
        if (current_state == WP_GETLIST && systemId == current_partner_systemid && compId == current_partner_compid)
        {
    
            qDebug() << "got waypoint count (" << count << ") from ID " << systemId;
    
    pixhawk's avatar
    pixhawk committed
    
    
    pixhawk's avatar
    pixhawk committed
            if (count > 0)
            {
                current_count = count;
                current_wp_id = 0;
                current_state = WP_GETLIST_GETWPS;
    
    pixhawk's avatar
    pixhawk committed
                sendWaypointRequest(current_wp_id);
            }
            else
            {
                emit updateStatusString("done.");
                qDebug() << "No waypoints on UAS " << systemId;
            }
    
    pixhawk's avatar
    pixhawk committed
    void UASWaypointManager::handleWaypoint(quint8 systemId, quint8 compId, mavlink_waypoint_t *wp)
    {
    
    pixhawk's avatar
    pixhawk committed
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
    
    
    pixhawk's avatar
    pixhawk committed
        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
    
                emit waypointUpdated(wp->seq, wp->x, wp->y, wp->z, wp->yaw, wp->autocontinue, wp->current, wp->orbit, wp->hold_time);
    
    pixhawk's avatar
    pixhawk committed
    
                //get next waypoint
                current_wp_id++;
    
                if(current_wp_id < current_count)
                {
    
                    sendWaypointRequest(current_wp_id);
    
    pixhawk's avatar
    pixhawk committed
                }
                else
                {
    
    pixhawk's avatar
    pixhawk committed
                    // all waypoints retrieved, change state to idle
    
    pixhawk's avatar
    pixhawk committed
                    current_state = WP_IDLE;
                    current_count = 0;
                    current_wp_id = 0;
                    current_partner_systemid = 0;
                    current_partner_compid = 0;
    
    pixhawk's avatar
    pixhawk committed
                    protocol_timer.stop();
    
                    emit updateStatusString("done.");
    
    
    pixhawk's avatar
    pixhawk committed
                    qDebug() << "got all waypoints from ID " << systemId;
    
    pixhawk's avatar
    pixhawk committed
                }
            }
            else
            {
    
    pixhawk's avatar
    pixhawk committed
                //TODO: error handling
    
    pixhawk's avatar
    pixhawk committed
    void UASWaypointManager::handleWaypointRequest(quint8 systemId, quint8 compId, mavlink_waypoint_request_t *wpr)
    
    pixhawk's avatar
    pixhawk committed
        protocol_timer.start(PROTOCOL_TIMEOUT_MS);
    
    
    pixhawk's avatar
    pixhawk committed
        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
        {
            qDebug() << "handleWaypointRequest";
    
            if (wpr->seq < waypoint_buffer.count())
    
    pixhawk's avatar
    pixhawk committed
            {
    
    pixhawk's avatar
    pixhawk committed
                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
                    protocol_timer.stop();
    
    pixhawk's avatar
    pixhawk committed
                    emit updateStatusString("done.");
    
                    qDebug() << "send all waypoints to ID " << systemId;
                }
    
    pixhawk's avatar
    pixhawk committed
            }
            else
            {
                //TODO: Error message or something
            }
        }
    
    pixhawk's avatar
    pixhawk committed
    void UASWaypointManager::handleWaypointReached(quint8 systemId, quint8 compId, mavlink_waypoint_reached_t *wpr)
    
    pixhawk's avatar
    pixhawk committed
        if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
        {
            emit updateStatusString(QString("Reached waypoint %1").arg(wpr->seq));
        }
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void UASWaypointManager::handleWaypointSetCurrent(quint8 systemId, quint8 compId, mavlink_waypoint_set_current_t *wpr)
    
    pixhawk's avatar
    pixhawk committed
    {
    
    pixhawk's avatar
    pixhawk committed
        if (systemId == uas.getUASID() && compId == MAV_COMP_ID_WAYPOINTPLANNER)
        {
            qDebug() << "new current waypoint" << wpr->seq;
            emit currentWaypointChanged(wpr->seq);
        }
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void UASWaypointManager::clearWaypointList()
    
    pixhawk's avatar
    pixhawk committed
    {
    
    }
    
    void UASWaypointManager::requestWaypoints()
    {
        if(current_state == WP_IDLE)
        {
    
    pixhawk's avatar
    pixhawk committed
            protocol_timer.start(PROTOCOL_TIMEOUT_MS);
    
    
    pixhawk's avatar
    pixhawk committed
            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;
    
    
            const QString str = QString("requesting waypoint list...");
            emit updateStatusString(str);
    
    
    pixhawk's avatar
    pixhawk committed
            mavlink_msg_waypoint_request_list_encode(uas.mavlink->getSystemId(), uas.mavlink->getComponentId(), &message, &wprl);
    
    pixhawk's avatar
    pixhawk committed
            uas.sendMessage(message);
    
            qDebug() << "sent waypoint list request to ID " << wprl.target_system;
    
    pixhawk's avatar
    pixhawk committed
        }
    }
    
    
    void UASWaypointManager::sendWaypoints()
    
    pixhawk's avatar
    pixhawk committed
    {
    
        if (current_state == WP_IDLE)
        {
    
            if (waypoints.count() > 0)
    
    pixhawk's avatar
    pixhawk committed
                protocol_timer.start(PROTOCOL_TIMEOUT_MS);
    
    
                current_count = waypoints.count();
    
    pixhawk's avatar
    pixhawk committed
                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
    
    
    pixhawk's avatar
    pixhawk committed
                //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);
    
    pixhawk's avatar
    pixhawk committed
    
                    cur_d->autocontinue = cur_s->getAutoContinue();
                    cur_d->current = cur_s->getCurrent();
    
    pixhawk's avatar
    pixhawk committed
                    cur_d->orbit = cur_s->getOrbit();
                    cur_d->hold_time = cur_s->getHoldTime();
    
    pixhawk's avatar
    pixhawk committed
                    cur_d->type = 1;        //FIXME
    
    pixhawk's avatar
    pixhawk committed
                    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();
                }
    
    pixhawk's avatar
    pixhawk committed
                //send the waypoint count to UAS (this starts the send transaction)
                mavlink_message_t message;
                mavlink_waypoint_count_t wpc;
    
    pixhawk's avatar
    pixhawk committed
                wpc.target_system = uas.getUASID();
                wpc.target_component = MAV_COMP_ID_WAYPOINTPLANNER;
                wpc.count = current_count;
    
    pixhawk's avatar
    pixhawk committed
                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);
    
    pixhawk's avatar
    pixhawk committed
                qDebug() << "sent waypoint count (" << wpc.count << ") to ID " << wpc.target_system;
            }
    
        }
        else
        {
            //we're in another transaction, ignore command
            qDebug() << "UASWaypointManager::sendWaypoints() doing something else ignoring command";
        }
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    void UASWaypointManager::sendWaypointRequest(quint16 seq)
    
    pixhawk's avatar
    pixhawk committed
    {
    
        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
        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);
    
        qDebug() << "sent waypoint request (" << wpr.seq << ") to ID " << wpr.target_system;
    
    pixhawk's avatar
    pixhawk committed
    }
    
    pixhawk's avatar
    pixhawk committed
    
    
    pixhawk's avatar
    pixhawk committed
    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
    }