Skip to content
Snippets Groups Projects
FollowMe.cc 5.32 KiB
Newer Older
  • Learn to ignore specific revisions
  • /****************************************************************************
     *
     *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
     *
     * QGroundControl is licensed according to the terms in the file
     * COPYING.md in the root of the source code directory.
     *
     ****************************************************************************/
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
    #include <QElapsedTimer>
    #include <cmath>
    
    #include "MultiVehicleManager.h"
    
    #include "FirmwarePlugin.h"
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    #include "MAVLinkProtocol.h"
    #include "FollowMe.h"
    #include "Vehicle.h"
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    #include "PositionManager.h"
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
    FollowMe::FollowMe(QGCApplication* app)
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        : QGCTool(app), estimatation_capabilities(0)
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    {
        memset(&_motionReport, 0, sizeof(motionReport_s));
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        runTime.start();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        _gcsMotionReportTimer.setSingleShot(false);
        connect(&_gcsMotionReportTimer, &QTimer::timeout, this, &FollowMe::_sendGCSMotionReport);
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    }
    
    FollowMe::~FollowMe()
    {
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        _disable();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    }
    
    void FollowMe::followMeHandleManager(const QString&)
    {
        QmlObjectListModel & vehicles = *_toolbox->multiVehicleManager()->vehicles();
    
        for (int i=0; i< vehicles.count(); i++) {
            Vehicle* vehicle = qobject_cast<Vehicle*>(vehicles[i]);
    
            if (vehicle->px4Firmware() && vehicle->flightMode().compare(FirmwarePlugin::px4FollowMeFlightMode, Qt::CaseInsensitive) == 0) {
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
                _enable();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
                return;
            }
        }
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        _disable();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    }
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    void FollowMe::_enable()
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    {
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        connect(_toolbox->qgcPositionManager(),
                SIGNAL(positionInfoUpdated(QGeoPositionInfo)),
                this,
                SLOT(_setGPSLocation(QGeoPositionInfo)));
    
        _gcsMotionReportTimer.setInterval(_toolbox->qgcPositionManager()->updateInterval());
        _gcsMotionReportTimer.start();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    }
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    void FollowMe::_disable()
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    {
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        disconnect(_toolbox->qgcPositionManager(),
                   SIGNAL(positionInfoUpdated(QGeoPositionInfo)),
                   this,
                   SLOT(_setGPSLocation(QGeoPositionInfo)));
    
        _gcsMotionReportTimer.stop();
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    }
    
    void FollowMe::_setGPSLocation(QGeoPositionInfo geoPositionInfo)
    {
        if (geoPositionInfo.isValid())
        {
            // get the current location coordinates
    
            QGeoCoordinate geoCoordinate = geoPositionInfo.coordinate();
    
            _motionReport.lat_int = geoCoordinate.latitude()*1e7;
            _motionReport.lon_int = geoCoordinate.longitude()*1e7;
            _motionReport.alt = geoCoordinate.altitude();
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
            estimatation_capabilities |= (1 << POS);
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
            // get the current eph and epv
    
            if(geoPositionInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) == true) {
                _motionReport.pos_std_dev[0] = _motionReport.pos_std_dev[1] = geoPositionInfo.attribute(QGeoPositionInfo::HorizontalAccuracy);
            }
    
            if(geoPositionInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy) == true) {
                _motionReport.pos_std_dev[2] = geoPositionInfo.attribute(QGeoPositionInfo::VerticalAccuracy);
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
    
    Ricardo de Almeida Gonzaga's avatar
    Ricardo de Almeida Gonzaga committed
            // calculate z velocity if it's available
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
            if(geoPositionInfo.hasAttribute(QGeoPositionInfo::VerticalSpeed)) {
                _motionReport.vz = geoPositionInfo.attribute(QGeoPositionInfo::VerticalSpeed);
            }
    
    
    Ricardo de Almeida Gonzaga's avatar
    Ricardo de Almeida Gonzaga committed
            // calculate x,y velocity if it's available
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
            if((geoPositionInfo.hasAttribute(QGeoPositionInfo::Direction)   == true) &&
               (geoPositionInfo.hasAttribute(QGeoPositionInfo::GroundSpeed) == true)) {
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
                estimatation_capabilities |= (1 << VEL);
    
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
                qreal direction = _degreesToRadian(geoPositionInfo.attribute(QGeoPositionInfo::Direction));
                qreal velocity = geoPositionInfo.attribute(QGeoPositionInfo::GroundSpeed);
    
                _motionReport.vx = cos(direction)*velocity;
                _motionReport.vy = sin(direction)*velocity;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
            } else {
                _motionReport.vx = 0.0f;
                _motionReport.vy = 0.0f;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
            }
        }
    }
    
    void FollowMe::_sendGCSMotionReport(void)
    {
        QmlObjectListModel & vehicles = *_toolbox->multiVehicleManager()->vehicles();
        MAVLinkProtocol* mavlinkProtocol = _toolbox->mavlinkProtocol();
        mavlink_follow_target_t follow_target;
    
        memset(&follow_target, 0, sizeof(mavlink_follow_target_t));
    
        follow_target.timestamp = runTime.nsecsElapsed()*1e-6;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        follow_target.est_capabilities = estimatation_capabilities;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        follow_target.position_cov[0] = _motionReport.pos_std_dev[0];
        follow_target.position_cov[2] = _motionReport.pos_std_dev[2];
        follow_target.alt = _motionReport.alt;
        follow_target.lat = _motionReport.lat_int;
        follow_target.lon = _motionReport.lon_int;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
        follow_target.vel[0] = _motionReport.vx;
        follow_target.vel[1] = _motionReport.vy;
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
    
        for (int i=0; i< vehicles.count(); i++) {
            Vehicle* vehicle = qobject_cast<Vehicle*>(vehicles[i]);
    
            if(vehicle->flightMode().compare(FirmwarePlugin::px4FollowMeFlightMode, Qt::CaseInsensitive) == 0) {
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
                mavlink_message_t message;
    
                mavlink_msg_follow_target_encode_chan(mavlinkProtocol->getSystemId(),
                                                      mavlinkProtocol->getComponentId(),
                                                      vehicle->priorityLink()->mavlinkChannel(),
                                                      &message,
                                                      &follow_target);
                vehicle->sendMessageOnLink(vehicle->priorityLink(), message);
    
    Jimmy Johnson's avatar
    Jimmy Johnson committed
            }
        }
    }
    
    double FollowMe::_degreesToRadian(double deg)
    {
        return deg * M_PI / 180.0;
    }