Skip to content
Snippets Groups Projects
UAS.cc 127 KiB
Newer Older
  • Learn to ignore specific revisions
  •         {
                mavlink_rc_channels_scaled_t channels;
                mavlink_msg_rc_channels_scaled_decode(&message, &channels);
    
    
                const unsigned int portWidth = 8; // XXX magic number
    
    
                emit remoteControlRSSIChanged(channels.rssi/255.0f);
    
                if (static_cast<uint16_t>(channels.chan1_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 0, channels.chan1_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan2_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 1, channels.chan2_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan3_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 2, channels.chan3_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan4_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 3, channels.chan4_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan5_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 4, channels.chan5_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan6_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 5, channels.chan6_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan7_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 6, channels.chan7_scaled/10000.0f);
    
                if (static_cast<uint16_t>(channels.chan8_scaled) != UINT16_MAX)
    
                    emit remoteControlChannelScaledChanged(channels.port * portWidth + 7, channels.chan8_scaled/10000.0f);
    
            }
                break;
            case MAVLINK_MSG_ID_PARAM_VALUE:
            {
    
                mavlink_param_value_t rawValue;
                mavlink_msg_param_value_decode(&message, &rawValue);
                QByteArray bytes(rawValue.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
    
                // Construct a string stopping at the first NUL (0) character, else copy the whole
                // byte array (max MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN, so safe)
                QString parameterName(bytes);
    
                mavlink_param_union_t paramVal;
                paramVal.param_float = rawValue.param_value;
                paramVal.type = rawValue.param_type;
    
                processParamValueMsg(message, parameterName,rawValue,paramVal);
    
                processParamValueMsgHook(message, parameterName,rawValue,paramVal);
    
                break;
            case MAVLINK_MSG_ID_COMMAND_ACK:
            {
                mavlink_command_ack_t ack;
                mavlink_msg_command_ack_decode(&message, &ack);
                switch (ack.result)
                {
                case MAV_RESULT_ACCEPTED:
                {
    
                    emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_INFO, tr("SUCCESS: Executed CMD: %1").arg(ack.command));
    
                }
                    break;
                case MAV_RESULT_TEMPORARILY_REJECTED:
                {
    
                    emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_WARNING, tr("FAILURE: Temporarily rejected CMD: %1").arg(ack.command));
    
                    emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_ERROR, tr("FAILURE: Denied CMD: %1").arg(ack.command));
    
                }
                    break;
                case MAV_RESULT_UNSUPPORTED:
                {
    
                    emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_WARNING, tr("FAILURE: Unsupported CMD: %1").arg(ack.command));
    
                    emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_ERROR, tr("FAILURE: Failed CMD: %1").arg(ack.command));
    
                mavlink_attitude_target_t out;
                mavlink_msg_attitude_target_decode(&message, &out);
                float roll, pitch, yaw;
                mavlink_quaternion_to_euler(out.q, &roll, &pitch, &yaw);
    
                quint64 time = getUnixTimeFromMs(out.time_boot_ms);
    
                emit attitudeThrustSetPointChanged(this, roll, pitch, yaw, out.thrust, time);
    
    
                // For plotting emit roll sp, pitch sp and yaw sp values
    
                emit valueChanged(uasId, "roll sp", "rad", roll, time);
                emit valueChanged(uasId, "pitch sp", "rad", pitch, time);
                emit valueChanged(uasId, "yaw sp", "rad", yaw, time);
    
            }
                break;
            case MAVLINK_MSG_ID_MISSION_COUNT:
            {
    
                mavlink_mission_count_t mc;
                mavlink_msg_mission_count_decode(&message, &mc);
    
                // Special case a 0 for the target system or component, it means that anyone is the target, so we should process this.
                if (mc.target_system == 0) {
                    mc.target_system = mavlink->getSystemId();
                }
                if (mc.target_component == 0) {
                    mc.target_component = mavlink->getComponentId();
                }
    
                // Check that this message applies to the UAS.
    
                if(mc.target_system == mavlink->getSystemId())
    
    
                    if (mc.target_component != mavlink->getComponentId()) {
                        qDebug() << "The target component ID is not set correctly. This is currently only a warning, but will be turned into an error.";
                        qDebug() << "Expecting" << mavlink->getComponentId() << "but got" << mc.target_component;
                    }
    
    
                    waypointManager.handleWaypointCount(message.sysid, message.compid, mc.count);
    
                    qDebug() << QString("Received mission count message, but was wrong system id. Expected %1, received %2").arg(mavlink->getSystemId()).arg(mc.target_system);
    
                mavlink_mission_item_t mi;
                mavlink_msg_mission_item_decode(&message, &mi);
    
                // Special case a 0 for the target system or component, it means that anyone is the target, so we should process this.
                if (mi.target_system == 0) {
                    mi.target_system = mavlink->getSystemId();
                }
                if (mi.target_component == 0) {
                    mi.target_component = mavlink->getComponentId();
                }
    
                // Check that the item pertains to this UAS.
    
                if(mi.target_system == mavlink->getSystemId())
    
    
                    if (mi.target_component != mavlink->getComponentId()) {
                        qDebug() << "The target component ID is not set correctly. This is currently only a warning, but will be turned into an error.";
                        qDebug() << "Expecting" << mavlink->getComponentId() << "but got" << mi.target_component;
                    }
    
    
                    waypointManager.handleWaypoint(message.sysid, message.compid, &mi);
    
                    qDebug() << QString("Received mission item message, but was wrong system id. Expected %1, received %2").arg(mavlink->getSystemId()).arg(mi.target_system);
    
                mavlink_mission_ack_t ma;
                mavlink_msg_mission_ack_decode(&message, &ma);
    
                // Special case a 0 for the target system or component, it means that anyone is the target, so we should process this.
                if (ma.target_system == 0) {
                    ma.target_system = mavlink->getSystemId();
                }
                if (ma.target_component == 0) {
                    ma.target_component = mavlink->getComponentId();
                }
    
                // Check that the ack pertains to this UAS.
    
                if(ma.target_system == mavlink->getSystemId())
    
    
                    if (ma.target_component != mavlink->getComponentId()) {
                        qDebug() << tr("The target component ID is not set correctly. This is currently only a warning, but will be turned into an error.");
                        qDebug() << "Expecting" << mavlink->getComponentId() << "but got" << ma.target_component;
                    }
    
    
                    waypointManager.handleWaypointAck(message.sysid, message.compid, &ma);
                }
                else
    
                    qDebug() << QString("Received mission ack message, but was wrong system id. Expected %1, received %2").arg(mavlink->getSystemId()).arg(ma.target_system);
    
                }
            }
                break;
    
            case MAVLINK_MSG_ID_MISSION_REQUEST:
            {
    
                mavlink_mission_request_t mr;
                mavlink_msg_mission_request_decode(&message, &mr);
    
                // Special case a 0 for the target system or component, it means that anyone is the target, so we should process this.
                if (mr.target_system == 0) {
                    mr.target_system = mavlink->getSystemId();
                }
                if (mr.target_component == 0) {
                    mr.target_component = mavlink->getComponentId();
                }
    
                // Check that the request pertains to this UAS.
    
                if(mr.target_system == mavlink->getSystemId())
    
    
                    if (mr.target_component != mavlink->getComponentId()) {
                        qDebug() << QString("The target component ID is not set correctly. This is currently only a warning, but will be turned into an error.");
                        qDebug() << "Expecting" << mavlink->getComponentId() << "but got" << mr.target_component;
                    }
    
    
                    waypointManager.handleWaypointRequest(message.sysid, message.compid, &mr);
    
                    qDebug() << QString("Received mission request message, but was wrong system id. Expected %1, received %2").arg(mavlink->getSystemId()).arg(mr.target_system);
    
                }
            }
                break;
    
            case MAVLINK_MSG_ID_MISSION_ITEM_REACHED:
            {
                mavlink_mission_item_reached_t wpr;
                mavlink_msg_mission_item_reached_decode(&message, &wpr);
                waypointManager.handleWaypointReached(message.sysid, message.compid, &wpr);
                QString text = QString("System %1 reached waypoint %2").arg(getUASName()).arg(wpr.seq);
                GAudioOutput::instance()->say(text);
    
                emit textMessageReceived(message.sysid, message.compid, MAV_SEVERITY_INFO, text);
    
            }
                break;
    
            case MAVLINK_MSG_ID_MISSION_CURRENT:
            {
                mavlink_mission_current_t wpc;
                mavlink_msg_mission_current_decode(&message, &wpc);
                waypointManager.handleWaypointCurrent(message.sysid, message.compid, &wpc);
            }
                break;
    
    
            case MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED:
    
            {
                if (multiComponentSourceDetected && wrongComponent)
                {
                    break;
                }
    
                mavlink_position_target_local_ned_t p;
                mavlink_msg_position_target_local_ned_decode(&message, &p);
                quint64 time = getUnixTimeFromMs(p.time_boot_ms);
                emit positionSetPointsChanged(uasId, p.x, p.y, p.z, 0/* XXX remove yaw and move it to attitude */, time);
    
            case MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED:
    
                mavlink_set_position_target_local_ned_t p;
                mavlink_msg_set_position_target_local_ned_decode(&message, &p);
                emit userPositionSetPointsChanged(uasId, p.x, p.y, p.z, 0/* XXX remove yaw and move it to attitude */);
    
            }
                break;
            case MAVLINK_MSG_ID_STATUSTEXT:
            {
                QByteArray b;
    
                b.resize(MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN+1);
    
                mavlink_msg_statustext_get_text(&message, b.data());
    
                // Ensure NUL-termination
                b[b.length()-1] = '\0';
    
                QString text = QString(b);
                int severity = mavlink_msg_statustext_get_severity(&message);
    
    
                if (text.startsWith("#") || severity <= MAV_SEVERITY_WARNING)
    
                    emit textMessageReceived(uasId, message.compid, severity, text);
    
                    GAudioOutput::instance()->say(text.toLower(), severity);
    
                }
                else
                {
                    emit textMessageReceived(uasId, message.compid, severity, text);
                }
            }
                break;
    
            case MAVLINK_MSG_ID_SERVO_OUTPUT_RAW:
            {
                mavlink_servo_output_raw_t raw;
                mavlink_msg_servo_output_raw_decode(&message, &raw);
    
    
                if (hilEnabled && raw.port == 0)
    
    Lorenz Meier's avatar
    Lorenz Meier committed
                    emit hilActuatorsChanged(static_cast<uint64_t>(getUnixTimeFromMs(raw.time_usec)), static_cast<float>(raw.servo1_raw),
    
                                         static_cast<float>(raw.servo2_raw), static_cast<float>(raw.servo3_raw),
                                         static_cast<float>(raw.servo4_raw), static_cast<float>(raw.servo5_raw), static_cast<float>(raw.servo6_raw),
                                         static_cast<float>(raw.servo7_raw), static_cast<float>(raw.servo8_raw));
                }
            }
            break;
    
            case MAVLINK_MSG_ID_DATA_TRANSMISSION_HANDSHAKE:
            {
                mavlink_data_transmission_handshake_t p;
                mavlink_msg_data_transmission_handshake_decode(&message, &p);
                imageSize = p.size;
                imagePackets = p.packets;
                imagePayload = p.payload;
                imageQuality = p.jpg_quality;
                imageType = p.type;
                imageWidth = p.width;
                imageHeight = p.height;
                imageStart = QGC::groundTimeMilliseconds();
    
                imagePacketsArrived = 0;
    
    
            }
                break;
    
            case MAVLINK_MSG_ID_ENCAPSULATED_DATA:
            {
                mavlink_encapsulated_data_t img;
                mavlink_msg_encapsulated_data_decode(&message, &img);
                int seq = img.seqnr;
                int pos = seq * imagePayload;
    
                // Check if we have a valid transaction
                if (imagePackets == 0)
                {
                    // NO VALID TRANSACTION - ABORT
                    // Restart statemachine
                    imagePacketsArrived = 0;
    
    Don Gagne's avatar
    Don Gagne committed
                    break;
    
                }
    
                for (int i = 0; i < imagePayload; ++i)
                {
                    if (pos <= imageSize) {
                        imageRecBuffer[pos] = img.data[i];
                    }
                    ++pos;
                }
    
                ++imagePacketsArrived;
    
                // emit signal if all packets arrived
    
                if (imagePacketsArrived >= imagePackets)
    
    Don Gagne's avatar
    Don Gagne committed
                    imagePackets = 0;
                    imagePacketsArrived = 0;
    
                    emit imageReady(this);
                }
            }
                break;
    
            case MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT:
    
            {
                mavlink_nav_controller_output_t p;
                mavlink_msg_nav_controller_output_decode(&message,&p);
                setDistToWaypoint(p.wp_dist);
    
                setBearingToWaypoint(p.nav_bearing);
                emit navigationControllerErrorsChanged(this, p.alt_error, p.aspd_error, p.xtrack_error);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            // Messages to ignore
            case MAVLINK_MSG_ID_RAW_IMU:
            case MAVLINK_MSG_ID_SCALED_IMU:
    
            case MAVLINK_MSG_ID_RAW_PRESSURE:
            case MAVLINK_MSG_ID_SCALED_PRESSURE:
            case MAVLINK_MSG_ID_OPTICAL_FLOW:
            case MAVLINK_MSG_ID_DEBUG_VECT:
            case MAVLINK_MSG_ID_DEBUG:
            case MAVLINK_MSG_ID_NAMED_VALUE_FLOAT:
            case MAVLINK_MSG_ID_NAMED_VALUE_INT:
            case MAVLINK_MSG_ID_MANUAL_CONTROL:
            case MAVLINK_MSG_ID_HIGHRES_IMU:
    
            case MAVLINK_MSG_ID_DISTANCE_SENSOR:
    
                break;
            default:
            {
                if (!unknownPackets.contains(message.msgid))
                {
                    unknownPackets.append(message.msgid);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
                    emit unknownPacketReceived(uasId, message.compid, message.msgid);
    
                    qDebug() << "Unknown message from system:" << uasId << "message:" << message.msgid;
    
                }
            }
                break;
            }
        }
    }
    
    /**
    * Set the home position of the UAS.
    * @param lat The latitude fo the home position
    
    * @param lon The longitude of the home position
    
    * @param alt The altitude of the home position
    */
    void UAS::setHomePosition(double lat, double lon, double alt)
    {
    
        if (blockHomePositionChanges)
            return;
    
    
        QString uasName = (getUASName() == "")?
                    tr("UAS") + QString::number(getUASID())
                  : getUASName();
    
    
    Don Gagne's avatar
    Don Gagne committed
        QMessageBox::StandardButton button = QGCMessageBox::question(tr("Set a new home position for vehicle %1").arg(uasName),
                                                                     tr("Do you want to set a new origin? Waypoints defined in the local frame will be shifted in their physical location"),
                                                                     QMessageBox::Yes | QMessageBox::Cancel,
                                                                     QMessageBox::Cancel);
        if (button == QMessageBox::Yes)
    
        {
            mavlink_message_t msg;
            mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, this->getUASID(), 0, MAV_CMD_DO_SET_HOME, 1, 0, 0, 0, 0, lat, lon, alt);
            // Send message twice to increase chance that it reaches its goal
            sendMessage(msg);
    
            // Send new home position to UAS
            mavlink_set_gps_global_origin_t home;
            home.target_system = uasId;
            home.latitude = lat*1E7;
            home.longitude = lon*1E7;
            home.altitude = alt*1000;
            qDebug() << "lat:" << home.latitude << " lon:" << home.longitude;
            mavlink_msg_set_gps_global_origin_encode(mavlink->getSystemId(), mavlink->getComponentId(), &msg, &home);
            sendMessage(msg);
    
        } else {
            blockHomePositionChanges = true;
    
        }
    }
    
    /**
    * Set the origin to the current GPS location.
    **/
    void UAS::setLocalOriginAtCurrentGPSPosition()
    {
    
    Don Gagne's avatar
    Don Gagne committed
        QMessageBox::StandardButton button = QGCMessageBox::question(tr("Set the home position at the current GPS position?"),
                                                                     tr("Do you want to set a new origin? Waypoints defined in the local frame will be shifted in their physical location"),
                                                                     QMessageBox::Yes | QMessageBox::Cancel,
                                                                     QMessageBox::Cancel);
        if (button == QMessageBox::Yes)
    
        {
            mavlink_message_t msg;
            mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, this->getUASID(), 0, MAV_CMD_DO_SET_HOME, 1, 1, 0, 0, 0, 0, 0, 0);
            // Send message twice to increase chance that it reaches its goal
            sendMessage(msg);
        }
    }
    
    /**
    * Set a local position setpoint.
    * @param x postion
    * @param y position
    * @param z position
    
    void UAS::setLocalPositionSetpoint(float x, float y, float z, float yaw)
    {
        Q_UNUSED(x);
        Q_UNUSED(y);
        Q_UNUSED(z);
        Q_UNUSED(yaw);
    }
    
    /**
    * Set a offset of the local position.
    * @param x position
    * @param y position
    * @param z position
    
    */
    void UAS::setLocalPositionOffset(float x, float y, float z, float yaw)
    {
        Q_UNUSED(x);
        Q_UNUSED(y);
        Q_UNUSED(z);
        Q_UNUSED(yaw);
    }
    
    
    void UAS::startRadioControlCalibration(int param)
    
    {
        mavlink_message_t msg;
        // Param 1: gyro cal, param 2: mag cal, param 3: pressure cal, Param 4: radio
    
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_PREFLIGHT_CALIBRATION, 1, 0, 0, 0, param, 0, 0, 0);
    
        sendMessage(msg);
    }
    
    void UAS::endRadioControlCalibration()
    {
        mavlink_message_t msg;
        // Param 1: gyro cal, param 2: mag cal, param 3: pressure cal, Param 4: radio
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_PREFLIGHT_CALIBRATION, 1, 0, 0, 0, 0, 0, 0, 0);
    
        sendMessage(msg);
    }
    
    void UAS::startDataRecording()
    {
        mavlink_message_t msg;
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_DO_CONTROL_VIDEO, 1, -1, -1, -1, 2, 0, 0, 0);
        sendMessage(msg);
    }
    
    void UAS::stopDataRecording()
    {
        mavlink_message_t msg;
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_DO_CONTROL_VIDEO, 1, -1, -1, -1, 0, 0, 0, 0);
        sendMessage(msg);
    }
    
    void UAS::startMagnetometerCalibration()
    {
        mavlink_message_t msg;
        // Param 1: gyro cal, param 2: mag cal, param 3: pressure cal, Param 4: radio
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, MAV_COMP_ID_IMU, MAV_CMD_PREFLIGHT_CALIBRATION, 1, 0, 1, 0, 0, 0, 0, 0);
        sendMessage(msg);
    }
    
    void UAS::startGyroscopeCalibration()
    {
        mavlink_message_t msg;
        // Param 1: gyro cal, param 2: mag cal, param 3: pressure cal, Param 4: radio
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, MAV_COMP_ID_IMU, MAV_CMD_PREFLIGHT_CALIBRATION, 1, 1, 0, 0, 0, 0, 0, 0);
        sendMessage(msg);
    }
    
    void UAS::startPressureCalibration()
    {
        mavlink_message_t msg;
        // Param 1: gyro cal, param 2: mag cal, param 3: pressure cal, Param 4: radio
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, MAV_COMP_ID_IMU, MAV_CMD_PREFLIGHT_CALIBRATION, 1, 0, 0, 1, 0, 0, 0, 0);
        sendMessage(msg);
    }
    
    
    /**
    * Check if time is smaller than 40 years, assuming no system without Unix
    
    * timestamp runs longer than 40 years continuously without reboot. In worst case
    * this will add/subtract the communication delay between GCS and MAV, it will
    * never alter the timestamp in a safety critical way.
    */
    quint64 UAS::getUnixReferenceTime(quint64 time)
    {
        // Same as getUnixTime, but does not react to attitudeStamped mode
        if (time == 0)
        {
            //        qDebug() << "XNEW time:" <<QGC::groundTimeMilliseconds();
            return QGC::groundTimeMilliseconds();
        }
        // Check if time is smaller than 40 years,
        // assuming no system without Unix timestamp
        // runs longer than 40 years continuously without
        // reboot. In worst case this will add/subtract the
        // communication delay between GCS and MAV,
        // it will never alter the timestamp in a safety
        // critical way.
        //
        // Calculation:
        // 40 years
        // 365 days
        // 24 hours
        // 60 minutes
        // 60 seconds
        // 1000 milliseconds
        // 1000 microseconds
    #ifndef _MSC_VER
        else if (time < 1261440000000000LLU)
    #else
        else if (time < 1261440000000000)
    #endif
        {
            //        qDebug() << "GEN time:" << time/1000 + onboardTimeOffset;
            if (onboardTimeOffset == 0)
            {
                onboardTimeOffset = QGC::groundTimeMilliseconds() - time/1000;
            }
            return time/1000 + onboardTimeOffset;
        }
        else
        {
            // Time is not zero and larger than 40 years -> has to be
            // a Unix epoch timestamp. Do nothing.
            return time/1000;
        }
    }
    
    /**
    * @warning If attitudeStamped is enabled, this function will not actually return
    
    * the precise time stamp of this measurement augmented to UNIX time, but will
    
    * MOVE the timestamp IN TIME to match the last measured attitude. There is no
    
    * reason why one would want this, except for system setups where the onboard
    
    * clock is not present or broken and datasets should be collected that are still
    
    * roughly synchronized. PLEASE NOTE THAT ENABLING ATTITUDE STAMPED RUINS THE
    
    * SCIENTIFIC NATURE OF THE CORRECT LOGGING FUNCTIONS OF QGROUNDCONTROL!
    */
    quint64 UAS::getUnixTimeFromMs(quint64 time)
    {
        return getUnixTime(time*1000);
    }
    
    /**
    * @warning If attitudeStamped is enabled, this function will not actually return
    
    * the precise time stam of this measurement augmented to UNIX time, but will
    * MOVE the timestamp IN TIME to match the last measured attitude. There is no
    * reason why one would want this, except for system setups where the onboard
    * clock is not present or broken and datasets should be collected that are
    
    * still roughly synchronized. PLEASE NOTE THAT ENABLING ATTITUDE STAMPED
    * RUINS THE SCIENTIFIC NATURE OF THE CORRECT LOGGING FUNCTIONS OF QGROUNDCONTROL!
    */
    quint64 UAS::getUnixTime(quint64 time)
    {
        quint64 ret = 0;
        if (attitudeStamped)
        {
            ret = lastAttitude;
        }
    
        if (time == 0)
        {
            ret = QGC::groundTimeMilliseconds();
        }
        // Check if time is smaller than 40 years,
        // assuming no system without Unix timestamp
        // runs longer than 40 years continuously without
        // reboot. In worst case this will add/subtract the
        // communication delay between GCS and MAV,
        // it will never alter the timestamp in a safety
        // critical way.
        //
        // Calculation:
        // 40 years
        // 365 days
        // 24 hours
        // 60 minutes
        // 60 seconds
        // 1000 milliseconds
        // 1000 microseconds
    #ifndef _MSC_VER
        else if (time < 1261440000000000LLU)
    #else
        else if (time < 1261440000000000)
    #endif
        {
            //        qDebug() << "GEN time:" << time/1000 + onboardTimeOffset;
            if (onboardTimeOffset == 0 || time < (lastNonNullTime - 100))
            {
                lastNonNullTime = time;
                onboardTimeOffset = QGC::groundTimeMilliseconds() - time/1000;
            }
            if (time > lastNonNullTime) lastNonNullTime = time;
    
            ret = time/1000 + onboardTimeOffset;
        }
        else
        {
            // Time is not zero and larger than 40 years -> has to be
            // a Unix epoch timestamp. Do nothing.
            ret = time/1000;
        }
    
        return ret;
    }
    
    /**
    * @param component that will be searched for in the map of parameters.
    */
    QList<QString> UAS::getParameterNames(int component)
    {
        if (parameters.contains(component))
        {
            return parameters.value(component)->keys();
        }
        else
        {
            return QList<QString>();
        }
    }
    
    QList<int> UAS::getComponentIds()
    {
        return parameters.keys();
    }
    
    /**
    
    * @param newBaseMode that UAS is to be set to.
    * @param newCustomMode that UAS is to be set to.
    
    void UAS::setMode(uint8_t newBaseMode, uint32_t newCustomMode)
    
        if (receivedMode)
        {
            //this->mode = mode; //no call assignament, update receive message from UAS
    
            // Strip armed / disarmed call for safety reasons, this is not relevant for setting the mode
            newBaseMode &= ~MAV_MODE_FLAG_SAFETY_ARMED;
            // Now set current state (request no change)
            newBaseMode |= this->base_mode & MAV_MODE_FLAG_SAFETY_ARMED;
    
    //        // Strip HIL part, replace it with current system state
    //        newBaseMode &= (~MAV_MODE_FLAG_HIL_ENABLED);
    //        // Now set current state (request no change)
    //        newBaseMode |= this->base_mode & MAV_MODE_FLAG_HIL_ENABLED;
    
    Thomas Gubler's avatar
    Thomas Gubler committed
            qDebug() << "WARNING: setMode called before base_mode bitmask was received from UAS, new mode was not sent to system";
    
        }
    }
    
    /**
    * @param newBaseMode that UAS is to be set to.
    * @param newCustomMode that UAS is to be set to.
    */
    void UAS::setModeArm(uint8_t newBaseMode, uint32_t newCustomMode)
    {
        if (receivedMode)
        {
            mavlink_message_t msg;
            mavlink_msg_set_mode_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, (uint8_t)uasId, newBaseMode, newCustomMode);
            qDebug() << "mavlink_msg_set_mode_pack 1";
            sendMessage(msg);
            qDebug() << "SENDING REQUEST TO SET MODE TO SYSTEM" << uasId << ", MODE " << newBaseMode << " " << newCustomMode;
        }
        else
        {
    
    Thomas Gubler's avatar
    Thomas Gubler committed
            qDebug() << "WARNING: setModeArm called before base_mode bitmask was received from UAS, new mode was not sent to system";
    
    }
    
    /**
    * Send a message to every link that is connected.
    * @param message that is to be sent
    */
    void UAS::sendMessage(mavlink_message_t message)
    {
    
        if (!LinkManager::instance())
        {
    
            qDebug() << "LINKMANAGER NOT AVAILABLE!";
    
        if (links.count() < 1) {
    
            qDebug() << "NO LINK AVAILABLE TO SEND!";
        }
    
    
        // Emit message on all links that are currently connected
    
        foreach (LinkInterface* link, links) {
            if (link->isConnected()) {
                sendMessage(link, message);
    
            }
        }
    }
    
    /**
    * Forward a message to all links that are currently connected.
    * @param message that is to be forwarded
    */
    void UAS::forwardMessage(mavlink_message_t message)
    {
        // Emit message on all links that are currently connected
    
        QList<LinkInterface*>link_list = LinkManager::instance()->getLinks();
    
    
        foreach(LinkInterface* link, link_list)
        {
            if (link)
            {
                SerialLink* serial = dynamic_cast<SerialLink*>(link);
                if(serial != 0)
                {
    
                    for(int i=0; i<links.size(); i++)
    
                        if(serial != links.at(i))
    
                            if (link->isConnected()) {
                                qDebug()<<"Antenna tracking: Forwarding Over link: "<<serial->getName()<<" "<<serial;
                                sendMessage(serial, message);
                            }
    
                        }
                    }
                }
            }
        }
    }
    
    /**
    * Send a message to the link that is connected.
    * @param link that the message will be sent to
    * @message that is to be sent
    */
    void UAS::sendMessage(LinkInterface* link, mavlink_message_t message)
    {
        if(!link) return;
        // Create buffer
        uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
        // Write message into buffer, prepending start sign
        int len = mavlink_msg_to_send_buffer(buffer, &message);
        static uint8_t messageKeys[256] = MAVLINK_MESSAGE_CRCS;
        mavlink_finalize_message_chan(&message, mavlink->getSystemId(), mavlink->getComponentId(), link->getId(), message.len, messageKeys[message.msgid]);
    
        // If link is connected
        if (link->isConnected())
        {
            // Send the portion of the buffer now occupied by the message
            link->writeBytes((const char*)buffer, len);
        }
    
        else
        {
            qDebug() << "LINK NOT CONNECTED, NOT SENDING!";
        }
    
    }
    
    /**
     * @param value battery voltage
     */
    float UAS::filterVoltage(float value) const
    {
    
    Lorenz Meier's avatar
    Lorenz Meier committed
        return lpVoltage * 0.6f + value * 0.4f;
    
    * Get the status of the code and a description of the status.
    * Status can be unitialized, booting up, calibrating sensors, active
    * standby, cirtical, emergency, shutdown or unknown.
    */
    void UAS::getStatusForCode(int statusCode, QString& uasState, QString& stateDescription)
    {
        switch (statusCode)
        {
        case MAV_STATE_UNINIT:
            uasState = tr("UNINIT");
            stateDescription = tr("Unitialized, booting up.");
            break;
        case MAV_STATE_BOOT:
            uasState = tr("BOOT");
            stateDescription = tr("Booting system, please wait.");
            break;
        case MAV_STATE_CALIBRATING:
            uasState = tr("CALIBRATING");
            stateDescription = tr("Calibrating sensors, please wait.");
            break;
        case MAV_STATE_ACTIVE:
            uasState = tr("ACTIVE");
            stateDescription = tr("Active, normal operation.");
            break;
        case MAV_STATE_STANDBY:
            uasState = tr("STANDBY");
            stateDescription = tr("Standby mode, ready for launch.");
            break;
        case MAV_STATE_CRITICAL:
            uasState = tr("CRITICAL");
            stateDescription = tr("FAILURE: Continuing operation.");
            break;
        case MAV_STATE_EMERGENCY:
            uasState = tr("EMERGENCY");
            stateDescription = tr("EMERGENCY: Land Immediately!");
            break;
            //case MAV_STATE_HILSIM:
            //uasState = tr("HIL SIM");
            //stateDescription = tr("HIL Simulation, Sensors read from SIM");
            //break;
    
        case MAV_STATE_POWEROFF:
            uasState = tr("SHUTDOWN");
            stateDescription = tr("Powering off system.");
            break;
    
        default:
            uasState = tr("UNKNOWN");
            stateDescription = tr("Unknown system state");
            break;
        }
    }
    
    QImage UAS::getImage()
    {
    
    //    qDebug() << "IMAGE TYPE:" << imageType;
    
        // RAW greyscale
        if (imageType == MAVLINK_DATA_STREAM_IMG_RAW8U)
        {
    
            int imgColors = 255;
    
    
            // Construct PGM header
            QString header("P5\n%1 %2\n%3\n");
            header = header.arg(imageWidth).arg(imageHeight).arg(imgColors);
    
    
    Don Gagne's avatar
    Don Gagne committed
            QByteArray tmpImage(header.toStdString().c_str(), header.length());
    
            tmpImage.append(imageRecBuffer);
    
            //qDebug() << "IMAGE SIZE:" << tmpImage.size() << "HEADER SIZE: (15):" << header.size() << "HEADER: " << header;
    
            if (imageRecBuffer.isNull())
            {
                qDebug()<< "could not convertToPGM()";
                return QImage();
            }
    
            if (!image.loadFromData(tmpImage, "PGM"))
            {
    
                qDebug()<< __FILE__ << __LINE__ << "could not create extracted image";
    
                return QImage();
            }
    
        }
        // BMP with header
        else if (imageType == MAVLINK_DATA_STREAM_IMG_BMP ||
                 imageType == MAVLINK_DATA_STREAM_IMG_JPEG ||
                 imageType == MAVLINK_DATA_STREAM_IMG_PGM ||
                 imageType == MAVLINK_DATA_STREAM_IMG_PNG)
        {
            if (!image.loadFromData(imageRecBuffer))
            {
    
                qDebug() << __FILE__ << __LINE__ << "Loading data from image buffer failed!";
    
                return QImage();
    
        // Restart statemachine
        imagePacketsArrived = 0;
    
        imagePackets = 0;
        imageRecBuffer.clear();
    
        return image;
    }
    
    void UAS::requestImage()
    {
        qDebug() << "trying to get an image from the uas...";
    
        // check if there is already an image transmission going on
        if (imagePacketsArrived == 0)
        {
            mavlink_message_t msg;
    
            mavlink_msg_data_transmission_handshake_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, MAVLINK_DATA_STREAM_IMG_JPEG, 0, 0, 0, 0, 0, 50);
    
            sendMessage(msg);
        }
    }
    
    
    /* MANAGEMENT */
    
    /**
     *
     * @return The uptime in milliseconds
     *
     */
    quint64 UAS::getUptime() const
    {
        if(startTime == 0)
        {
            return 0;
        }
        else
        {
            return QGC::groundTimeMilliseconds() - startTime;
        }
    }
    
    int UAS::getCommunicationStatus() const
    {
        return commStatus;
    }
    
    void UAS::writeParametersToStorage()
    {
        mavlink_message_t msg;
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_PREFLIGHT_STORAGE, 1, 1, -1, -1, -1, 0, 0, 0);
        qDebug() << "SENT COMMAND" << MAV_CMD_PREFLIGHT_STORAGE;
        sendMessage(msg);
    }
    
    void UAS::readParametersFromStorage()
    {
        mavlink_message_t msg;
        mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, 0, MAV_CMD_PREFLIGHT_STORAGE, 1, 0, -1, -1, -1, 0, 0, 0);
        sendMessage(msg);
    }
    
    
    bool UAS::isRotaryWing()
    {
    
            case MAV_TYPE_QUADROTOR:
            /* fallthrough */
            case MAV_TYPE_COAXIAL:
            case MAV_TYPE_HELICOPTER:
            case MAV_TYPE_HEXAROTOR:
            case MAV_TYPE_OCTOROTOR:
            case MAV_TYPE_TRICOPTER:
                return true;
            default:
                return false;
        }
    }
    
    bool UAS::isFixedWing()
    {
    
            case MAV_TYPE_FIXED_WING:
                return true;
            default:
                return false;
        }
    }
    
    
    * @param rate The update rate in Hz the message should be sent
    */
    void UAS::enableAllDataTransmission(int rate)
    {