parent
3b83e60352
commit
0459704fde
@ -1,26 +0,0 @@
|
||||
|
||||
|
||||
add_library(gps
|
||||
Drivers/src/ashtech.cpp
|
||||
Drivers/src/gps_helper.cpp
|
||||
Drivers/src/mtk.cpp
|
||||
Drivers/src/rtcm.cpp
|
||||
Drivers/src/sbf.cpp
|
||||
Drivers/src/ubx.cpp
|
||||
GPSManager.cc
|
||||
GPSProvider.cc
|
||||
RTCM/RTCMMavlink.cc
|
||||
)
|
||||
|
||||
target_link_libraries(gps
|
||||
Qt6::Core
|
||||
Qt6::Location
|
||||
Qt6::SerialPort
|
||||
Qt6::Svg
|
||||
Qt6::TextToSpeech
|
||||
|
||||
qgc
|
||||
)
|
||||
|
||||
target_include_directories(gps INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
@ -1,42 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GPSProvider.h"
|
||||
#include "RTCM/RTCMMavlink.h"
|
||||
#include <QGCToolbox.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
/**
|
||||
** class GPSManager
|
||||
* handles a GPS provider and RTK
|
||||
*/
|
||||
class GPSManager : public QGCTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GPSManager(QGCApplication* app, QGCToolbox* toolbox);
|
||||
~GPSManager();
|
||||
|
||||
void connectGPS (const QString& device, const QString& gps_type);
|
||||
void disconnectGPS (void);
|
||||
bool connected (void) const { return _gpsProvider && _gpsProvider->isRunning(); }
|
||||
|
||||
signals:
|
||||
void onConnect();
|
||||
void onDisconnect();
|
||||
void surveyInStatus(float duration, float accuracyMM, double latitude, double longitude, float altitude, bool valid, bool active);
|
||||
void satelliteUpdate(int numSats);
|
||||
|
||||
private slots:
|
||||
void GPSPositionUpdate(GPSPositionMessage msg);
|
||||
void GPSSatelliteUpdate(GPSSatelliteMessage msg);
|
||||
|
||||
private:
|
||||
GPSProvider* _gpsProvider = nullptr;
|
||||
RTCMMavlink* _rtcmMavlink = nullptr;
|
||||
|
||||
std::atomic_bool _requestGpsStop; ///< signals the thread to quit
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vehicle_gps_position.h"
|
||||
#include "satellite_info.h"
|
||||
#include <QMetaType>
|
||||
|
||||
/**
|
||||
** struct GPSPositionMessage
|
||||
* wrapper that can be used for Qt signal/slots
|
||||
*/
|
||||
struct GPSPositionMessage
|
||||
{
|
||||
sensor_gps_s position_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(GPSPositionMessage);
|
||||
|
||||
|
||||
struct GPSSatelliteMessage
|
||||
{
|
||||
satellite_info_s satellite_data;
|
||||
};
|
||||
Q_DECLARE_METATYPE(GPSSatelliteMessage);
|
@ -1,84 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QByteArray>
|
||||
#include <QSerialPort>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "GPSPositionMessage.h"
|
||||
#include "Drivers/src/gps_helper.h"
|
||||
|
||||
|
||||
/**
|
||||
** class GPSProvider
|
||||
* opens a GPS device and handles the protocol
|
||||
*/
|
||||
class GPSProvider : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum class GPSType {
|
||||
u_blox,
|
||||
trimble,
|
||||
septentrio
|
||||
};
|
||||
|
||||
GPSProvider(const QString& device,
|
||||
GPSType type,
|
||||
bool enableSatInfo,
|
||||
double surveyInAccMeters,
|
||||
int surveryInDurationSecs,
|
||||
bool useFixedBaseLocation,
|
||||
double fixedBaseLatitude,
|
||||
double fixedBaseLongitude,
|
||||
float fixedBaseAltitudeMeters,
|
||||
float fixedBaseAccuracyMeters,
|
||||
const std::atomic_bool& requestStop);
|
||||
~GPSProvider();
|
||||
|
||||
/**
|
||||
* this is called by the callback method
|
||||
*/
|
||||
void gotRTCMData(uint8_t *data, size_t len);
|
||||
|
||||
signals:
|
||||
void positionUpdate(GPSPositionMessage message);
|
||||
void satelliteInfoUpdate(GPSSatelliteMessage message);
|
||||
void RTCMDataUpdate(QByteArray message);
|
||||
void surveyInStatus(float duration, float accuracyMM, double latitude, double longitude, float altitude, bool valid, bool active);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
void publishGPSPosition();
|
||||
void publishGPSSatellite();
|
||||
|
||||
/**
|
||||
* callback from the driver for the platform specific stuff
|
||||
*/
|
||||
static int callbackEntry(GPSCallbackType type, void *data1, int data2, void *user);
|
||||
|
||||
int callback(GPSCallbackType type, void *data1, int data2);
|
||||
|
||||
QString _device;
|
||||
GPSType _type;
|
||||
const std::atomic_bool& _requestStop;
|
||||
double _surveyInAccMeters;
|
||||
int _surveryInDurationSecs;
|
||||
bool _useFixedBaseLoction;
|
||||
double _fixedBaseLatitude;
|
||||
double _fixedBaseLongitude;
|
||||
float _fixedBaseAltitudeMeters;
|
||||
float _fixedBaseAccuracyMeters;
|
||||
GPSHelper::GPSConfig _gpsConfig{};
|
||||
|
||||
struct sensor_gps_s _reportGpsPos;
|
||||
struct satellite_info_s *_pReportSatInfo = nullptr;
|
||||
|
||||
QSerialPort *_serial = nullptr;
|
||||
};
|
@ -1,76 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#include "RTCMMavlink.h"
|
||||
|
||||
#include "MultiVehicleManager.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
RTCMMavlink::RTCMMavlink(QGCToolbox& toolbox)
|
||||
: _toolbox(toolbox)
|
||||
{
|
||||
_bandwidthTimer.start();
|
||||
}
|
||||
|
||||
void RTCMMavlink::RTCMDataUpdate(QByteArray message)
|
||||
{
|
||||
/* statistics */
|
||||
_bandwidthByteCounter += message.size();
|
||||
qint64 elapsed = _bandwidthTimer.elapsed();
|
||||
if (elapsed > 1000) {
|
||||
printf("RTCM bandwidth: %.2f kB/s\n", (float) _bandwidthByteCounter / elapsed * 1000.f / 1024.f);
|
||||
_bandwidthTimer.restart();
|
||||
_bandwidthByteCounter = 0;
|
||||
}
|
||||
|
||||
const qsizetype maxMessageLength = MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN;
|
||||
mavlink_gps_rtcm_data_t mavlinkRtcmData;
|
||||
memset(&mavlinkRtcmData, 0, sizeof(mavlink_gps_rtcm_data_t));
|
||||
|
||||
if (message.size() < maxMessageLength) {
|
||||
mavlinkRtcmData.len = message.size();
|
||||
mavlinkRtcmData.flags = (_sequenceId & 0x1F) << 3;
|
||||
memcpy(&mavlinkRtcmData.data, message.data(), message.size());
|
||||
sendMessageToVehicle(mavlinkRtcmData);
|
||||
} else {
|
||||
// We need to fragment
|
||||
|
||||
uint8_t fragmentId = 0; // Fragment id indicates the fragment within a set
|
||||
int start = 0;
|
||||
while (start < message.size()) {
|
||||
int length = std::min(message.size() - start, maxMessageLength);
|
||||
mavlinkRtcmData.flags = 1; // LSB set indicates message is fragmented
|
||||
mavlinkRtcmData.flags |= fragmentId++ << 1; // Next 2 bits are fragment id
|
||||
mavlinkRtcmData.flags |= (_sequenceId & 0x1F) << 3; // Next 5 bits are sequence id
|
||||
mavlinkRtcmData.len = length;
|
||||
memcpy(&mavlinkRtcmData.data, message.data() + start, length);
|
||||
sendMessageToVehicle(mavlinkRtcmData);
|
||||
start += length;
|
||||
}
|
||||
}
|
||||
++_sequenceId;
|
||||
}
|
||||
|
||||
void RTCMMavlink::sendMessageToVehicle(const mavlink_gps_rtcm_data_t& msg)
|
||||
{
|
||||
QmlObjectListModel& vehicles = *_toolbox.multiVehicleManager()->vehicles();
|
||||
MAVLinkProtocol* mavlinkProtocol = _toolbox.mavlinkProtocol();
|
||||
for (int i = 0; i < vehicles.count(); i++) {
|
||||
Vehicle* vehicle = qobject_cast<Vehicle*>(vehicles[i]);
|
||||
WeakLinkInterfacePtr weakLink = vehicle->vehicleLinkManager()->primaryLink();
|
||||
|
||||
if (!weakLink.expired()) {
|
||||
mavlink_message_t message;
|
||||
SharedLinkInterfacePtr sharedLink = weakLink.lock();
|
||||
|
||||
mavlink_msg_gps_rtcm_data_encode_chan(mavlinkProtocol->getSystemId(),
|
||||
mavlinkProtocol->getComponentId(),
|
||||
sharedLink->mavlinkChannel(),
|
||||
&message,
|
||||
&msg);
|
||||
vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), message);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "QGCToolbox.h"
|
||||
#include "MAVLinkProtocol.h"
|
||||
|
||||
/**
|
||||
** class RTCMMavlink
|
||||
* Receives RTCM updates and sends them via MAVLINK to the device
|
||||
*/
|
||||
class RTCMMavlink : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RTCMMavlink(QGCToolbox& toolbox);
|
||||
//TODO: API to select device(s)?
|
||||
|
||||
public slots:
|
||||
void RTCMDataUpdate(QByteArray message);
|
||||
|
||||
private:
|
||||
void sendMessageToVehicle(const mavlink_gps_rtcm_data_t& msg);
|
||||
|
||||
QGCToolbox& _toolbox;
|
||||
QElapsedTimer _bandwidthTimer;
|
||||
int _bandwidthByteCounter = 0;
|
||||
uint8_t _sequenceId = 0;
|
||||
};
|
@ -1,63 +0,0 @@
|
||||
|
||||
|
||||
/**
|
||||
* @file definitions.h
|
||||
* common platform-specific definitions & abstractions for gps
|
||||
* @author Beat Küng <beat-kueng@gmx.net>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#define GPS_READ_BUFFER_SIZE 1024
|
||||
|
||||
#define GPS_INFO(...) qInfo(__VA_ARGS__)
|
||||
#define GPS_WARN(...) qWarning(__VA_ARGS__)
|
||||
#define GPS_ERR(...) qCritical(__VA_ARGS__)
|
||||
|
||||
#include "vehicle_gps_position.h"
|
||||
#include "satellite_info.h"
|
||||
|
||||
#define M_DEG_TO_RAD (M_PI / 180.0)
|
||||
#define M_RAD_TO_DEG (180.0 / M_PI)
|
||||
#define M_DEG_TO_RAD_F 0.01745329251994f
|
||||
#define M_RAD_TO_DEG_F 57.2957795130823f
|
||||
|
||||
#include <QThread>
|
||||
|
||||
class Sleeper : public QThread
|
||||
{
|
||||
public:
|
||||
static void usleep(unsigned long usecs) { QThread::usleep(usecs); }
|
||||
};
|
||||
|
||||
static inline void gps_usleep(unsigned long usecs) {
|
||||
Sleeper::usleep(usecs);
|
||||
}
|
||||
|
||||
typedef uint64_t gps_abstime;
|
||||
|
||||
#include <QDateTime>
|
||||
/**
|
||||
* Get the current time in us. Function signature:
|
||||
* uint64_t hrt_absolute_time()
|
||||
*/
|
||||
static inline gps_abstime gps_absolute_time() {
|
||||
//FIXME: is there something with microsecond accuracy?
|
||||
return QDateTime::currentMSecsSinceEpoch() * 1000;
|
||||
}
|
||||
|
||||
//timespec is UNIX-specific
|
||||
#ifdef _WIN32
|
||||
#if _MSC_VER < 1900
|
||||
struct timespec
|
||||
{
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,24 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* This file is auto-generated from https://github.com/PX4/Firmware/blob/master/msg/satellite_info.msg
|
||||
* and was manually copied here.
|
||||
*/
|
||||
|
||||
struct satellite_info_s {
|
||||
uint64_t timestamp;
|
||||
uint8_t count;
|
||||
uint8_t svid[20];
|
||||
uint8_t used[20];
|
||||
uint8_t elevation[20];
|
||||
uint8_t azimuth[20];
|
||||
uint8_t snr[20];
|
||||
uint8_t prn[20];
|
||||
#ifdef __cplusplus
|
||||
static const uint8_t SAT_INFO_MAX_SATELLITES = 20;
|
||||
|
||||
#endif
|
||||
};
|
@ -1,39 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* This file is auto-generated from https://github.com/PX4/Firmware/blob/master/msg/vehicle_gps_position.msg
|
||||
* and was manually copied here.
|
||||
*/
|
||||
|
||||
struct sensor_gps_s {
|
||||
uint64_t timestamp;
|
||||
uint64_t time_utc_usec;
|
||||
int32_t lat;
|
||||
int32_t lon;
|
||||
int32_t alt;
|
||||
int32_t alt_ellipsoid;
|
||||
uint16_t automatic_gain_control;
|
||||
uint8_t jamming_state;
|
||||
float s_variance_m_s;
|
||||
float c_variance_rad;
|
||||
float eph;
|
||||
float epv;
|
||||
float hdop;
|
||||
float vdop;
|
||||
int32_t noise_per_ms;
|
||||
int32_t jamming_indicator;
|
||||
float vel_m_s;
|
||||
float vel_n_m_s;
|
||||
float vel_e_m_s;
|
||||
float vel_d_m_s;
|
||||
float cog_rad;
|
||||
int32_t timestamp_time_relative;
|
||||
float heading;
|
||||
uint8_t fix_type;
|
||||
bool vel_ned_valid;
|
||||
uint8_t satellites_used;
|
||||
};
|
@ -0,0 +1,520 @@
|
||||
/****************************************************************************
|
||||
*此代码是QGC开发的重要部分
|
||||
****************************************************************************/
|
||||
|
||||
#include "JsonHelper.h"
|
||||
#include "QGCQGeoCoordinate.h"
|
||||
#include "QmlObjectListModel.h"
|
||||
#include "MissionCommandList.h"
|
||||
#include "FactMetaData.h"
|
||||
#include "QGCApplication.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonParseError>
|
||||
#include <QObject>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QFile>
|
||||
#include <QTranslator>
|
||||
|
||||
const char* JsonHelper::jsonVersionKey = "version";
|
||||
const char* JsonHelper::jsonGroundStationKey = "groundStation";
|
||||
const char* JsonHelper::jsonGroundStationValue = "QGroundControl";
|
||||
const char* JsonHelper::jsonFileTypeKey = "fileType";
|
||||
const char* JsonHelper::_translateKeysKey = "translateKeys";
|
||||
const char* JsonHelper::_arrayIDKeysKey = "_arrayIDKeys";
|
||||
|
||||
bool JsonHelper::validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString)
|
||||
{
|
||||
QString missingKeys;
|
||||
|
||||
foreach(const QString& key, keys) {
|
||||
if (!jsonObject.contains(key)) {
|
||||
if (!missingKeys.isEmpty()) {
|
||||
missingKeys += QStringLiteral(", ");
|
||||
}
|
||||
missingKeys += key;
|
||||
}
|
||||
}
|
||||
|
||||
if (missingKeys.length() != 0) {
|
||||
errorString = QObject::tr("The following required keys are missing: %1").arg(missingKeys);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonHelper::_loadGeoCoordinate(const QJsonValue& jsonValue,
|
||||
bool altitudeRequired,
|
||||
QGeoCoordinate& coordinate,
|
||||
QString& errorString,
|
||||
bool geoJsonFormat)
|
||||
{
|
||||
if (!jsonValue.isArray()) {
|
||||
errorString = QObject::tr("value for coordinate is not array");
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonArray coordinateArray = jsonValue.toArray();
|
||||
int requiredCount = altitudeRequired ? 3 : 2;
|
||||
if (coordinateArray.count() != requiredCount) {
|
||||
errorString = QObject::tr("Coordinate array must contain %1 values").arg(requiredCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& jsonValue: coordinateArray) {
|
||||
if (jsonValue.type() != QJsonValue::Double && jsonValue.type() != QJsonValue::Null) {
|
||||
errorString = QObject::tr("Coordinate array may only contain double values, found: %1").arg(jsonValue.type());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (geoJsonFormat) {
|
||||
coordinate = QGeoCoordinate(coordinateArray[1].toDouble(), coordinateArray[0].toDouble());
|
||||
} else {
|
||||
coordinate = QGeoCoordinate(possibleNaNJsonValue(coordinateArray[0]), possibleNaNJsonValue(coordinateArray[1]));
|
||||
}
|
||||
if (altitudeRequired) {
|
||||
coordinate.setAltitude(possibleNaNJsonValue(coordinateArray[2]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonHelper::_saveGeoCoordinate(const QGeoCoordinate& coordinate,
|
||||
bool writeAltitude,
|
||||
QJsonValue& jsonValue,
|
||||
bool geoJsonFormat)
|
||||
{
|
||||
QJsonArray coordinateArray;
|
||||
|
||||
if (geoJsonFormat) {
|
||||
coordinateArray << coordinate.longitude() << coordinate.latitude();
|
||||
} else {
|
||||
coordinateArray << coordinate.latitude() << coordinate.longitude();
|
||||
}
|
||||
if (writeAltitude) {
|
||||
coordinateArray << coordinate.altitude();
|
||||
}
|
||||
|
||||
jsonValue = QJsonValue(coordinateArray);
|
||||
}
|
||||
|
||||
bool JsonHelper::loadGeoCoordinate(const QJsonValue& jsonValue,
|
||||
bool altitudeRequired,
|
||||
QGeoCoordinate& coordinate,
|
||||
QString& errorString,
|
||||
bool geoJsonFormat)
|
||||
{
|
||||
return _loadGeoCoordinate(jsonValue, altitudeRequired, coordinate, errorString, geoJsonFormat);
|
||||
}
|
||||
|
||||
void JsonHelper::saveGeoCoordinate(const QGeoCoordinate& coordinate,
|
||||
bool writeAltitude,
|
||||
QJsonValue& jsonValue)
|
||||
{
|
||||
_saveGeoCoordinate(coordinate, writeAltitude, jsonValue, false /* geoJsonFormat */);
|
||||
}
|
||||
|
||||
bool JsonHelper::loadGeoJsonCoordinate(const QJsonValue& jsonValue,
|
||||
bool altitudeRequired,
|
||||
QGeoCoordinate& coordinate,
|
||||
QString& errorString)
|
||||
{
|
||||
return _loadGeoCoordinate(jsonValue, altitudeRequired, coordinate, errorString, true /* geoJsonFormat */);
|
||||
}
|
||||
|
||||
void JsonHelper::saveGeoJsonCoordinate(const QGeoCoordinate& coordinate,
|
||||
bool writeAltitude,
|
||||
QJsonValue& jsonValue)
|
||||
{
|
||||
_saveGeoCoordinate(coordinate, writeAltitude, jsonValue, true /* geoJsonFormat */);
|
||||
}
|
||||
|
||||
bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString)
|
||||
{
|
||||
for (int i=0; i<types.count(); i++) {
|
||||
QString valueKey = keys[i];
|
||||
if (jsonObject.contains(valueKey)) {
|
||||
const QJsonValue& jsonValue = jsonObject[valueKey];
|
||||
if (jsonValue.type() == QJsonValue::Null && types[i] == QJsonValue::Double) {
|
||||
// Null type signals a NaN on a double value
|
||||
continue;
|
||||
}
|
||||
if (jsonValue.type() != types[i]) {
|
||||
errorString = QObject::tr("Incorrect value type - key:type:expected %1:%2:%3").arg(valueKey).arg(_jsonValueTypeToString(jsonValue.type())).arg(_jsonValueTypeToString(types[i]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonHelper::isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc, QString& errorString)
|
||||
{
|
||||
QJsonParseError parseError;
|
||||
|
||||
jsonDoc = QJsonDocument::fromJson(bytes, &parseError);
|
||||
|
||||
if (parseError.error == QJsonParseError::NoError) {
|
||||
return true;
|
||||
} else {
|
||||
int startPos = qMax(0, parseError.offset - 100);
|
||||
int length = qMin(bytes.length() - startPos, 200);
|
||||
qDebug() << QStringLiteral("Json read error '%1'").arg(bytes.mid(startPos, length).constData());
|
||||
errorString = parseError.errorString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool JsonHelper::isJsonFile(const QString& fileName, QJsonDocument& jsonDoc, QString& errorString)
|
||||
{
|
||||
QFile jsonFile(fileName);
|
||||
if (!jsonFile.open(QFile::ReadOnly)) {
|
||||
errorString = tr("File open failed: file:error %1 %2").arg(jsonFile.fileName()).arg(jsonFile.errorString());
|
||||
return false;
|
||||
}
|
||||
QByteArray jsonBytes = jsonFile.readAll();
|
||||
jsonFile.close();
|
||||
|
||||
return isJsonFile(jsonBytes, jsonDoc, errorString);
|
||||
}
|
||||
|
||||
bool JsonHelper::validateInternalQGCJsonFile(const QJsonObject& jsonObject,
|
||||
const QString& expectedFileType,
|
||||
int minSupportedVersion,
|
||||
int maxSupportedVersion,
|
||||
int& version,
|
||||
QString& errorString)
|
||||
{
|
||||
// Validate required keys
|
||||
QList<JsonHelper::KeyValidateInfo> requiredKeys = {
|
||||
{ jsonFileTypeKey, QJsonValue::String, true },
|
||||
{ jsonVersionKey, QJsonValue::Double, true },
|
||||
};
|
||||
if (!JsonHelper::validateKeys(jsonObject, requiredKeys, errorString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure file type is correct
|
||||
QString fileTypeValue = jsonObject[jsonFileTypeKey].toString();
|
||||
if (fileTypeValue != expectedFileType) {
|
||||
errorString = QObject::tr("Incorrect file type key expected:%1 actual:%2").arg(expectedFileType).arg(fileTypeValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Version check
|
||||
version = jsonObject[jsonVersionKey].toInt();
|
||||
if (version < minSupportedVersion) {
|
||||
errorString = QObject::tr("File version %1 is no longer supported").arg(version);
|
||||
return false;
|
||||
}
|
||||
if (version > maxSupportedVersion) {
|
||||
errorString = QObject::tr("File version %1 is newer than current supported version %2").arg(version).arg(maxSupportedVersion);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonHelper::validateExternalQGCJsonFile(const QJsonObject& jsonObject,
|
||||
const QString& expectedFileType,
|
||||
int minSupportedVersion,
|
||||
int maxSupportedVersion,
|
||||
int& version,
|
||||
QString& errorString)
|
||||
{
|
||||
// Validate required keys
|
||||
QList<JsonHelper::KeyValidateInfo> requiredKeys = {
|
||||
{ jsonGroundStationKey, QJsonValue::String, true },
|
||||
};
|
||||
if (!JsonHelper::validateKeys(jsonObject, requiredKeys, errorString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return validateInternalQGCJsonFile(jsonObject, expectedFileType, minSupportedVersion, maxSupportedVersion, version, errorString);
|
||||
}
|
||||
|
||||
QStringList JsonHelper::_addDefaultLocKeys(QJsonObject& jsonObject)
|
||||
{
|
||||
QString translateKeys;
|
||||
QString fileType = jsonObject[jsonFileTypeKey].toString();
|
||||
if (!fileType.isEmpty()) {
|
||||
if (fileType == MissionCommandList::qgcFileType) {
|
||||
if (jsonObject.contains(_translateKeysKey)) {
|
||||
translateKeys = jsonObject[_translateKeysKey].toString();
|
||||
} else {
|
||||
translateKeys = "label,enumStrings,friendlyName,description,category";
|
||||
jsonObject[_translateKeysKey] = translateKeys;
|
||||
}
|
||||
if (!jsonObject.contains(_arrayIDKeysKey)) {
|
||||
jsonObject[_arrayIDKeysKey] = "rawName,comment";
|
||||
}
|
||||
} else if (fileType == FactMetaData::qgcFileType) {
|
||||
if (jsonObject.contains(_translateKeysKey)) {
|
||||
translateKeys = jsonObject[_translateKeysKey].toString();
|
||||
} else {
|
||||
translateKeys = "shortDescription,longDescription,enumStrings";
|
||||
jsonObject[_translateKeysKey] = "shortDescription,longDescription,enumStrings";
|
||||
}
|
||||
if (!jsonObject.contains(_arrayIDKeysKey)) {
|
||||
jsonObject[_arrayIDKeysKey] = "name";
|
||||
}
|
||||
}
|
||||
}
|
||||
return translateKeys.split(",");
|
||||
}
|
||||
|
||||
QJsonObject JsonHelper::_translateObject(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys)
|
||||
{
|
||||
for (const QString& key: jsonObject.keys()) {
|
||||
if (jsonObject[key].isString()) {
|
||||
QString locString = jsonObject[key].toString();
|
||||
if (translateKeys.contains(key)) {
|
||||
QString disambiguation;
|
||||
QString disambiguationPrefix("#loc.disambiguation#");
|
||||
|
||||
if (locString.startsWith(disambiguationPrefix)) {
|
||||
locString = locString.right(locString.length() - disambiguationPrefix.length());
|
||||
int commentEndIndex = locString.indexOf("#");
|
||||
if (commentEndIndex != -1) {
|
||||
disambiguation = locString.left(commentEndIndex);
|
||||
locString = locString.right(locString.length() - disambiguation.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
QString xlatString = qgcApp()->qgcJSONTranslator().translate(translateContext.toUtf8().constData(), locString.toUtf8().constData(), disambiguation.toUtf8().constData());
|
||||
if (!xlatString.isNull()) {
|
||||
jsonObject[key] = xlatString;
|
||||
}
|
||||
}
|
||||
} else if (jsonObject[key].isArray()) {
|
||||
QJsonArray childJsonArray = jsonObject[key].toArray();
|
||||
jsonObject[key] = _translateArray(childJsonArray, translateContext, translateKeys);
|
||||
} else if (jsonObject[key].isObject()) {
|
||||
QJsonObject childJsonObject = jsonObject[key].toObject();
|
||||
jsonObject[key] = _translateObject(childJsonObject, translateContext, translateKeys);
|
||||
}
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
QJsonArray JsonHelper::_translateArray(QJsonArray& jsonArray, const QString& translateContext, const QStringList& translateKeys)
|
||||
{
|
||||
for (int i=0; i<jsonArray.count(); i++) {
|
||||
QJsonObject childJsonObject = jsonArray[i].toObject();
|
||||
jsonArray[i] = _translateObject(childJsonObject, translateContext, translateKeys);
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
QJsonObject JsonHelper::_translateRoot(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys)
|
||||
{
|
||||
return _translateObject(jsonObject, translateContext, translateKeys);
|
||||
}
|
||||
|
||||
QJsonObject JsonHelper::openInternalQGCJsonFile(const QString& jsonFilename,
|
||||
const QString& expectedFileType,
|
||||
int minSupportedVersion,
|
||||
int maxSupportedVersion,
|
||||
int &version,
|
||||
QString& errorString)
|
||||
{
|
||||
QFile jsonFile(jsonFilename);
|
||||
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
errorString = tr("Unable to open file: '%1', error: %2").arg(jsonFilename).arg(jsonFile.errorString());
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
QByteArray bytes = jsonFile.readAll();
|
||||
jsonFile.close();
|
||||
QJsonParseError jsonParseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
|
||||
if (jsonParseError.error != QJsonParseError::NoError) {
|
||||
errorString = tr("Unable to parse json file: %1 error: %2 offset: %3").arg(jsonFilename).arg(jsonParseError.errorString()).arg(jsonParseError.offset);
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
if (!doc.isObject()) {
|
||||
errorString = tr("Root of json file is not object: %1").arg(jsonFilename);
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
QJsonObject jsonObject = doc.object();
|
||||
bool success = validateInternalQGCJsonFile(jsonObject, expectedFileType, minSupportedVersion, maxSupportedVersion, version, errorString);
|
||||
if (!success) {
|
||||
errorString = tr("Json file: '%1'. %2").arg(jsonFilename).arg(errorString);
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
QStringList translateKeys = _addDefaultLocKeys(jsonObject);
|
||||
QString context = QFileInfo(jsonFile).fileName();
|
||||
return _translateRoot(jsonObject, context, translateKeys);
|
||||
}
|
||||
|
||||
void JsonHelper::saveQGCJsonFileHeader(QJsonObject& jsonObject,
|
||||
const QString& fileType,
|
||||
int version)
|
||||
{
|
||||
jsonObject[jsonGroundStationKey] = jsonGroundStationValue;
|
||||
jsonObject[jsonFileTypeKey] = fileType;
|
||||
jsonObject[jsonVersionKey] = version;
|
||||
}
|
||||
|
||||
bool JsonHelper::loadGeoCoordinateArray(const QJsonValue& jsonValue,
|
||||
bool altitudeRequired,
|
||||
QVariantList& rgVarPoints,
|
||||
QString& errorString)
|
||||
{
|
||||
if (!jsonValue.isArray()) {
|
||||
errorString = QObject::tr("value for coordinate array is not array");
|
||||
return false;
|
||||
}
|
||||
QJsonArray rgJsonPoints = jsonValue.toArray();
|
||||
|
||||
rgVarPoints.clear();
|
||||
for (int i=0; i<rgJsonPoints.count(); i++) {
|
||||
QGeoCoordinate coordinate;
|
||||
|
||||
if (!JsonHelper::loadGeoCoordinate(rgJsonPoints[i], altitudeRequired, coordinate, errorString)) {
|
||||
return false;
|
||||
}
|
||||
rgVarPoints.append(QVariant::fromValue(coordinate));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonHelper::loadGeoCoordinateArray(const QJsonValue& jsonValue,
|
||||
bool altitudeRequired,
|
||||
QList<QGeoCoordinate>& rgPoints,
|
||||
QString& errorString)
|
||||
{
|
||||
QVariantList rgVarPoints;
|
||||
|
||||
if (!loadGeoCoordinateArray(jsonValue, altitudeRequired, rgVarPoints, errorString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rgPoints.clear();
|
||||
for (int i=0; i<rgVarPoints.count(); i++) {
|
||||
rgPoints.append(rgVarPoints[i].value<QGeoCoordinate>());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonHelper::saveGeoCoordinateArray(const QVariantList& rgVarPoints,
|
||||
bool writeAltitude,
|
||||
QJsonValue& jsonValue)
|
||||
{
|
||||
QJsonArray rgJsonPoints;
|
||||
|
||||
// Add all points to the array
|
||||
for (int i=0; i<rgVarPoints.count(); i++) {
|
||||
QJsonValue jsonPoint;
|
||||
|
||||
JsonHelper::saveGeoCoordinate(rgVarPoints[i].value<QGeoCoordinate>(), writeAltitude, jsonPoint);
|
||||
rgJsonPoints.append(jsonPoint);
|
||||
}
|
||||
|
||||
jsonValue = rgJsonPoints;
|
||||
}
|
||||
|
||||
void JsonHelper::saveGeoCoordinateArray(const QList<QGeoCoordinate>& rgPoints,
|
||||
bool writeAltitude,
|
||||
QJsonValue& jsonValue)
|
||||
{
|
||||
QVariantList rgVarPoints;
|
||||
|
||||
for (int i=0; i<rgPoints.count(); i++) {
|
||||
rgVarPoints.append(QVariant::fromValue(rgPoints[i]));
|
||||
}
|
||||
return saveGeoCoordinateArray(rgVarPoints, writeAltitude, jsonValue);
|
||||
}
|
||||
|
||||
bool JsonHelper::validateKeys(const QJsonObject& jsonObject, const QList<JsonHelper::KeyValidateInfo>& keyInfo, QString& errorString)
|
||||
{
|
||||
QStringList keyList;
|
||||
QList<QJsonValue::Type> typeList;
|
||||
|
||||
for (int i=0; i<keyInfo.count(); i++) {
|
||||
if (keyInfo[i].required) {
|
||||
keyList.append(keyInfo[i].key);
|
||||
}
|
||||
}
|
||||
if (!validateRequiredKeys(jsonObject, keyList, errorString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
keyList.clear();
|
||||
for (int i=0; i<keyInfo.count(); i++) {
|
||||
keyList.append(keyInfo[i].key);
|
||||
typeList.append(keyInfo[i].type);
|
||||
}
|
||||
return validateKeyTypes(jsonObject, keyList, typeList, errorString);
|
||||
}
|
||||
|
||||
QString JsonHelper::_jsonValueTypeToString(QJsonValue::Type type)
|
||||
{
|
||||
const struct {
|
||||
QJsonValue::Type type;
|
||||
const char* string;
|
||||
} rgTypeToString[] = {
|
||||
{ QJsonValue::Null, "NULL" },
|
||||
{ QJsonValue::Bool, "Bool" },
|
||||
{ QJsonValue::Double, "Double" },
|
||||
{ QJsonValue::String, "String" },
|
||||
{ QJsonValue::Array, "Array" },
|
||||
{ QJsonValue::Object, "Object" },
|
||||
{ QJsonValue::Undefined, "Undefined" },
|
||||
};
|
||||
|
||||
for (size_t i=0; i<sizeof(rgTypeToString)/sizeof(rgTypeToString[0]); i++) {
|
||||
if (type == rgTypeToString[i].type) {
|
||||
return rgTypeToString[i].string;
|
||||
}
|
||||
}
|
||||
|
||||
return QObject::tr("Unknown type: %1").arg(type);
|
||||
}
|
||||
|
||||
bool JsonHelper::loadPolygon(const QJsonArray& polygonArray, QmlObjectListModel& list, QObject* parent, QString& errorString)
|
||||
{
|
||||
for (int i=0; i<polygonArray.count(); i++) {
|
||||
const QJsonValue& pointValue = polygonArray[i];
|
||||
|
||||
QGeoCoordinate pointCoord;
|
||||
if (!JsonHelper::loadGeoCoordinate(pointValue, false /* altitudeRequired */, pointCoord, errorString, true)) {
|
||||
list.clearAndDeleteContents();
|
||||
return false;
|
||||
}
|
||||
list.append(new QGCQGeoCoordinate(pointCoord, parent));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonHelper::savePolygon(QmlObjectListModel& list, QJsonArray& polygonArray)
|
||||
{
|
||||
for (int i=0; i<list.count(); i++) {
|
||||
QGeoCoordinate vertex = list.value<QGCQGeoCoordinate*>(i)->coordinate();
|
||||
|
||||
QJsonValue jsonValue;
|
||||
JsonHelper::saveGeoCoordinate(vertex, false /* writeAltitude */, jsonValue);
|
||||
polygonArray.append(jsonValue);
|
||||
}
|
||||
}
|
||||
|
||||
double JsonHelper::possibleNaNJsonValue(const QJsonValue& value)
|
||||
{
|
||||
if (value.type() == QJsonValue::Null) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
return value.toDouble();
|
||||
}
|
||||
}
|
@ -0,0 +1,822 @@
|
||||
|
||||
|
||||
/**
|
||||
* @file ViewLink.h
|
||||
* @brief ViewLink SDK header file
|
||||
* @details This header file defines ViewLink SDK interfaces and the necessary data structures
|
||||
* @author Edwin
|
||||
* @version 3.0.7
|
||||
* @date 2020-06-28
|
||||
* @copyright Copyright (c) 2020 Shenzhen Viewpro Technology Co., Ltd
|
||||
*/
|
||||
|
||||
#ifndef __VIEW_LINK_H__
|
||||
#define __VIEW_LINK_H__
|
||||
|
||||
#if (defined _WIN32) || (defined _WIN64) // windows
|
||||
#ifdef VLK_EXPORTS
|
||||
#define VLK_API extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define VLK_API extern "C" __declspec(dllimport)
|
||||
#endif
|
||||
#define VLK_CALL __stdcall
|
||||
#else
|
||||
#define VLK_API
|
||||
#define VLK_CALL
|
||||
#endif
|
||||
|
||||
/** @name error code
|
||||
* @brief usually used as return value of interface function to indicate the operation success or not
|
||||
* @{
|
||||
*/
|
||||
#define VLK_ERROR_NO_ERROR 0
|
||||
#define VLK_ERROR_INVALID_PARAM -1
|
||||
/** @} error code */
|
||||
|
||||
/** @name ViewLink SDK constant
|
||||
* @{
|
||||
*/
|
||||
/** the max value of yaw */
|
||||
#define VLK_YAW_MAX 180.0
|
||||
/** the min value of yaw */
|
||||
#define VLK_YAW_MIN -180.0
|
||||
/** the max value of pitch */
|
||||
#define VLK_PITCH_MAX 90.0
|
||||
/** the min value of pitch */
|
||||
#define VLK_PITCH_MIN -90.0
|
||||
|
||||
/** the yaw max moving speed (20 degrees per second)*/
|
||||
#define VLK_MAX_YAW_SPEED 2000.0
|
||||
/** the pitch max moving speed (20 degrees per second)*/
|
||||
#define VLK_MAX_PITCH_SPEED 2000.0
|
||||
|
||||
/** the min zoom (or focus) speed*/
|
||||
#define VLK_MIN_ZOOM_SPEED 1
|
||||
/** the max zoom (or focus) speed*/
|
||||
#define VLK_MAX_ZOOM_SPEED 8
|
||||
/** @} ViewLink SDK constant */
|
||||
|
||||
/** @name ViewLink SDK data structures
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* device connection type
|
||||
*/
|
||||
typedef enum _VLK_CONN_TYPE
|
||||
{
|
||||
VLK_CONN_TYPE_SERIAL_PORT = 0x00, ///< serial port
|
||||
VLK_CONN_TYPE_TCP = 0x01, ///< tcp
|
||||
VLK_CONN_TYPE_UDP = 0x02, ///< udp, not currently supported
|
||||
VLK_CONN_TYPE_BUTT
|
||||
}VLK_CONN_TYPE;
|
||||
|
||||
/**
|
||||
* TCP connect information
|
||||
*/
|
||||
typedef struct _VLK_DEV_IPADDR VLK_DEV_IPADDR;
|
||||
struct _VLK_DEV_IPADDR
|
||||
{
|
||||
char szIPV4[16]; ///< device ipv4 address, e.g: 192.168.2.119
|
||||
int iPort; ///< tcp port, e.g: 2000
|
||||
};
|
||||
|
||||
/**
|
||||
* serial port connect information
|
||||
*/
|
||||
typedef struct _VLK_DEV_SERIAL_PORT VLK_DEV_SERIAL_PORT;
|
||||
struct _VLK_DEV_SERIAL_PORT
|
||||
{
|
||||
char szSerialPortName[16]; ///< serial port name, e.g: /dev/ttyS0 on linux or COM1 on windows
|
||||
int iBaudRate; ///< baudrate, e.g: 115200
|
||||
};
|
||||
|
||||
/**
|
||||
* device connect parameter
|
||||
*/
|
||||
typedef struct _VLK_CONN_PARAM VLK_CONN_PARAM;
|
||||
struct _VLK_CONN_PARAM
|
||||
{
|
||||
VLK_CONN_TYPE emType;
|
||||
union {
|
||||
VLK_DEV_IPADDR IPAddr;
|
||||
VLK_DEV_SERIAL_PORT SerialPort;
|
||||
} ConnParam;
|
||||
};
|
||||
|
||||
/**
|
||||
* device connection status
|
||||
*/
|
||||
typedef enum _VLK_CONN_STATUS
|
||||
{
|
||||
VLK_CONN_STATUS_CONNECTED = 0x00, ///< deprecated
|
||||
VLK_CONN_STATUS_DISCONNECTED = 0x01, ///< deprecated
|
||||
VLK_CONN_STATUS_TCP_CONNECTED = 0x02, ///< TCP connected
|
||||
VLK_CONN_STATUS_TCP_DISCONNECTED = 0x03, ///< TCP disconnected
|
||||
VLK_CONN_STATUS_SERIAL_PORT_CONNECTED = 0x04, ///< serial port connected
|
||||
VLK_CONN_STATUS_SERIAL_PORT_DISCONNECTED = 0x05, ///< serial port disconnectd
|
||||
VLK_CONN_STATUS_BUTT
|
||||
}VLK_CONN_STATUS;
|
||||
|
||||
/**
|
||||
* track template size
|
||||
*/
|
||||
typedef enum _VLK_TRACK_TEMPLATE_SIZE
|
||||
{
|
||||
VLK_TRACK_TEMPLATE_SIZE_AUTO = 0,
|
||||
VLK_TRACK_TEMPLATE_SIZE_32 = 32,
|
||||
VLK_TRACK_TEMPLATE_SIZE_64 = 64,
|
||||
VLK_TRACK_TEMPLATE_SIZE_128 = 128,
|
||||
VLK_TRACK_TEMPLATE_SIZE_BUTT
|
||||
}VLK_TRACK_TEMPLATE_SIZE;
|
||||
|
||||
/**
|
||||
* sensor type
|
||||
*/
|
||||
typedef enum _VLK_SENSOR
|
||||
{
|
||||
VLK_SENSOR_VISIBLE1 = 0, ///< visible light only
|
||||
VLK_SENSOR_IR = 1, ///< IR only
|
||||
VLK_SENSOR_VISIBLE_IR = 2, ///< visible light + IR PIP
|
||||
VLK_SENSOR_IR_VISIBLE = 3, ///< IR + visible light PIP
|
||||
VLK_SENSOR_VISIBLE2 = 4, ///< prime lens visible light
|
||||
VLK_SENSOR_BUTT
|
||||
}VLK_SENSOR;
|
||||
|
||||
/**
|
||||
* track mode parameter
|
||||
*/
|
||||
typedef struct _VLK_TRACK_MODE_PARAM VLK_TRACK_MODE_PARAM;
|
||||
struct _VLK_TRACK_MODE_PARAM
|
||||
{
|
||||
VLK_TRACK_TEMPLATE_SIZE emTrackTempSize;
|
||||
VLK_SENSOR emTrackSensor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Record mode
|
||||
*/
|
||||
typedef enum _VLK_RECORD_MODE
|
||||
{
|
||||
VLK_RECORD_MODE_NONE = 0, ///< none mode, neither photo nor record mode
|
||||
VLK_RECORD_MODE_PHOTO = 1, ///< photo mode, take photos only
|
||||
VLK_RECORD_MODE_RECORD = 2, ///< record mode, video record only
|
||||
VLK_RECORD_MODE_BUTT
|
||||
}VLK_RECORD_MODE;
|
||||
|
||||
/**
|
||||
* Focus mode
|
||||
*/
|
||||
typedef enum _VLK_FOCUS_MODE
|
||||
{
|
||||
VLK_FOCUS_MODE_AUTO = 0, ///< automatic focus
|
||||
VLK_FOCUS_MODE_MANU = 1, ///< manual focus
|
||||
VLK_FOCUS_MODE_BUTT
|
||||
}VLK_FOCUS_MODE;
|
||||
|
||||
/**
|
||||
* Laser zoom mode
|
||||
*/
|
||||
typedef enum _VLK_LASER_ZOOM_MODE
|
||||
{
|
||||
VLK_LASER_ZOOM_MODE_FOLLOW_EO = 0, ///< follow visible light zoom
|
||||
VLK_LASER_ZOOM_MODE_MANU = 1, ///< manual control
|
||||
VLK_LASER_ZOOM_MODE_BUTT
|
||||
}VLK_LASER_ZOOM_MODE;
|
||||
|
||||
/**
|
||||
* OSD mask
|
||||
*/
|
||||
typedef enum _VLK_OSD_MASK
|
||||
{
|
||||
VLK_OSD_MASK_ENABLE_OSD = 0x1, ///< enable OSD
|
||||
VLK_OSD_MASK_CROSS = 0x2, ///< enable cross frame in center of image
|
||||
VLK_OSD_MASK_PITCH_YAW = 0x4, ///< show pitch and yaw
|
||||
VLK_OSD_MASK_XYSHIFT = 0x8, ///< enable xy shift
|
||||
VLK_OSD_MASK_GPS = 0x10, ///< enable GPS
|
||||
VLK_OSD_MASK_TIME = 0x20, ///< enable time
|
||||
VLK_OSD_MASK_VL_MAG = 0x40, ///< enable VL-MAG
|
||||
VLK_OSD_MASK_BIG_FONT = 0x80 ///< enable big font
|
||||
}VLK_OSD_MASK;
|
||||
|
||||
/**
|
||||
* OSD input mask
|
||||
*/
|
||||
typedef enum _VLK_OSD_INPUT_MASK
|
||||
{
|
||||
VLK_OSD_INPUT_MASK_PERMANENT_SAVE = 0x1, ///< save OSD configuration, still work after reboot
|
||||
VLK_OSD_INPUT_MASK_TIME = 0x2, ///< enalbe input time
|
||||
VLK_OSD_INPUT_MASK_GPS = 0x4, ///< enable input GPS
|
||||
VLK_OSD_INPUT_MASK_MGRS = 0x8,///< enable input MGRS
|
||||
VLK_OSD_INPUT_MASK_PITCH_YAW = 0x10, ///< enable input pitch and yaw
|
||||
VLK_OSD_INPUT_MASK_VL_MAG = 0x20, ///< enalbe input VL-MAG
|
||||
VLK_OSD_INPUT_MASK_ZOOM_TIMES_OR_FOV = 0x40, ///< display zoom times or FOV
|
||||
VLK_OSD_INPUT_MASK_CHAR_BLACK_BORDER = 0x80 ///< enable character black frame
|
||||
}VLK_OSD_INPUT_MASK;
|
||||
|
||||
/**
|
||||
* OSD configuration parameter
|
||||
*/
|
||||
typedef struct _VLK_OSD_PARAM VLK_OSD_PARAM;
|
||||
struct _VLK_OSD_PARAM
|
||||
{
|
||||
char cOSD; ///< mask of VLK_OSD_MASK, e.g: VLK_OSD_MASK_ENABLE_OSD | VLK_OSD_MASK_CROSS
|
||||
char cOSDInput; ///< mask of VLK_OSD_INPUT_MASK, e.g: VLK_OSD_INPUT_MASK_TIME | VLK_OSD_INPUT_MASK_GPS
|
||||
};
|
||||
|
||||
/**
|
||||
* Image type
|
||||
*/
|
||||
typedef enum _VLK_IMAGE_TYPE
|
||||
{
|
||||
VLK_IMAGE_TYPE_VISIBLE1, ///< visible light zoom lens
|
||||
VLK_IMAGE_TYPE_VISIBLE2, ///< visible light prime lens
|
||||
VLK_IMAGE_TYPE_IR1, ///< IR zoom lens
|
||||
VLK_IMAGE_TYPE_IR2, ///< IR prime lens
|
||||
VLK_IMAGE_TYPE_FUSION, ///< visible light + IR fusion
|
||||
VLK_IMAGE_TYPE_BUTT
|
||||
}VLK_IMAGE_TYPE;
|
||||
|
||||
/**
|
||||
* IR color type
|
||||
*/
|
||||
typedef enum _VLK_IR_COLOR
|
||||
{
|
||||
VLK_IR_COLOR_WHITEHOT,
|
||||
VLK_IR_COLOR_BLACKHOT,
|
||||
VLK_IR_COLOR_PSEUDOHOT,
|
||||
VLK_IR_COLOR_RUSTY,
|
||||
VLK_IR_COLOR_BUTT
|
||||
}VLK_IR_COLOR;
|
||||
|
||||
/**
|
||||
* 2.4G wireless control channels map
|
||||
*/
|
||||
typedef struct _VLK_CHANNELS_MAP VLK_CHANNELS_MAP;
|
||||
struct _VLK_CHANNELS_MAP
|
||||
{
|
||||
char cYW; ///< high 4 bits save yaw left channel index, low 4 bits save yaw right channel index
|
||||
char cPT; ///< high 4 bits save pitch up channel index, low 4 bits save pitch down channel index
|
||||
char cMO; ///< high 4 bits save adjust speed channel index, low 4 bits save recenter channel index
|
||||
char cZM; ///< high 4 bits save zoom out channel index, low 4 bits save zoom in channel index
|
||||
char cFC; ///< high 4 bits save focus out channel index, low 4 bits save focus in channel index
|
||||
char cRP; ///< high 4 bits save take photo channel index, low 4 bits save Gimbal record channel index
|
||||
char cMU; ///< high 4 bits save start track channel index, low 4 bits save stop track channel index
|
||||
};
|
||||
|
||||
/**
|
||||
* Device configuration
|
||||
*/
|
||||
typedef struct _VLK_DEV_CONFIG VLK_DEV_CONFIG;
|
||||
struct _VLK_DEV_CONFIG
|
||||
{
|
||||
char cTimeZone; ///< time zone, e.g: 8 (Beijing), 9 (Seoul)
|
||||
char cOSDCfg; ///< OSD configuration, equivalent to cOSD in VLK_OSD_PARAM
|
||||
char cMagneticVariation; ///< Magnetic Variation set https://skyvector.com/ http://www.magnetic-declination.com/
|
||||
char cOSDInput; ///< OSD input configuration, equivalent to cOSDInput in VLK_OSD_PARAM
|
||||
|
||||
/**
|
||||
* @brief Gimbal serial port baudrate \n
|
||||
* 0: 2400 \n
|
||||
* 1: 4800 \n
|
||||
* 2: 9600 \n
|
||||
* 3: 19200 \n
|
||||
* 4: 38400 \n
|
||||
* 5: 57600 \n
|
||||
* 6: 115200 \n
|
||||
* 7: S.BUS mode
|
||||
*/
|
||||
char cBaudRate;
|
||||
|
||||
char cEODigitalZoom; ///< EO digital zoom, 1: on; 0: off
|
||||
short sTemperatureAlarmLine;///< temperature alarm, low 8 bits save lower limit, high 8 bits save upper limit
|
||||
char cTrack; ///< track status, 1: enabled, 0: disabled
|
||||
|
||||
/**
|
||||
* @brief laser work mode \n
|
||||
* 0: stop LRF \n
|
||||
* 1: 1HZ get LRF data \n
|
||||
* 2: continuosly get LRF \n
|
||||
* 3: one time get LRF data
|
||||
*/
|
||||
char cLaser;
|
||||
|
||||
char cRecordDefinition; ///< record definition, 1: 4k 25fps; 2: 1080P 25fps
|
||||
char cOSDGPS; ///< OSD GPS, 0: OSD GPS is UAV; 1: OSD GPS is target
|
||||
|
||||
/**
|
||||
* @brief s.bus/mavlink channels map set \n
|
||||
* 1: 1~7 \n
|
||||
* 2: 6~12 \n
|
||||
* 3: 8~14 \n
|
||||
* 4: custom channels \n
|
||||
*/
|
||||
char cSBUSChnlMap;
|
||||
|
||||
VLK_CHANNELS_MAP ChnlsMap; ///< custom channels map
|
||||
char cFocusHoldSet; ///< deprecated
|
||||
char cCameraType; ///< deprecated
|
||||
char cReserved1[5]; ///< reserved
|
||||
char cRestoreIP; ///< deprecated
|
||||
char cReserved2[5]; ///< reserved
|
||||
char cReserved3[43]; ///< reserved
|
||||
char cVersionNO[20]; ///< firmware version NO
|
||||
char cDeviceID[10]; ///< device model
|
||||
char cSerialNO[22]; ///< serial NO
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Device model
|
||||
*/
|
||||
typedef struct _VLK_DEV_MODEL VLK_DEV_MODEL;
|
||||
struct _VLK_DEV_MODEL
|
||||
{
|
||||
char cModelCode; ///< Gimbal model code
|
||||
char szModelName[32]; ///< Gimbal model name
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracker status
|
||||
*/
|
||||
typedef enum _VLK_TRACKER_STATUS
|
||||
{
|
||||
VLK_TRACKER_STATUS_STOPPED,
|
||||
VLK_TRACKER_STATUS_SEARCHING,
|
||||
VLK_TRACKER_STATUS_TRACKING,
|
||||
VLK_TRACKER_STATUS_LOST,
|
||||
VLK_TRACKER_STATUS_BUTT
|
||||
}VLK_TRACKER_STATUS;
|
||||
|
||||
/**
|
||||
* Device telemetry
|
||||
*/
|
||||
typedef struct _VLK_DEV_TELEMETRY VLK_DEV_TELEMETRY;
|
||||
struct _VLK_DEV_TELEMETRY
|
||||
{
|
||||
double dYaw; ///< Gimbal current yaw
|
||||
double dPitch; ///< Gimbal current pitch
|
||||
VLK_SENSOR emSensorType; ///< sensor type
|
||||
VLK_TRACKER_STATUS emTrackerStatus; ///< tracker status
|
||||
double dTargetLat; ///< target latitude
|
||||
double dTargetLng; ///< target longitude
|
||||
double dTargetAlt; ///< target altitude
|
||||
double dZoomMagTimes; ///< camera magnification times
|
||||
short sLaserDistance; ///< laser distance
|
||||
VLK_IR_COLOR emIRColor; ///< IR color
|
||||
VLK_RECORD_MODE emRecordMode; ///< record mode
|
||||
};
|
||||
|
||||
/**
|
||||
* Device status type \n
|
||||
* device status is passed by VLK_DevStatus_CB, \n
|
||||
* VLK_DEV_STATUS_TYPE will be passed to formal paramter iType, \n
|
||||
* and the device status data will be passed to szBuffer, \n
|
||||
* different iType matches different status data struct
|
||||
*/
|
||||
typedef enum _VLK_DEV_STATUS_TYPE
|
||||
{
|
||||
VLK_DEV_STATUS_TYPE_MODEL, ///< matches VLK_DEV_MODEL
|
||||
VLK_DEV_STATUS_TYPE_CONFIG, ///< matches VLK_DEV_CONFIG
|
||||
VLK_DEV_STATUS_TYPE_TELEMETRY, ///< matches VLK_DEV_TELEMETRY
|
||||
VLK_DEV_STATUS_TYPE_BUTT,
|
||||
}VLK_DEV_STATUS_TYPE;
|
||||
/** @} ViewLink SDK data structures */
|
||||
|
||||
/** @name ViewLink SDK callback functions
|
||||
* @{
|
||||
*/
|
||||
/** @brief connection status callback
|
||||
* @param iConnStatus connection status, it must be one of VLK_CONN_STATUS
|
||||
* @param szMessage extended string message
|
||||
* @param iMsgLen extended string message length
|
||||
* @return return 0 anyway
|
||||
* @details VLK_ConnStatus_CB will be called by SDK once the connection status changed,
|
||||
* for example, developers should check connect result in this callback function
|
||||
* @see VLK_Connect
|
||||
*/
|
||||
typedef int (*VLK_ConnStatus_CB)(int iConnStatus, const char* szMessage, int iMsgLen, void* pUserParam);
|
||||
|
||||
/** @brief device status callback
|
||||
* @param iType device status type, it must be one of VLK_DEV_STATUS_TYPE
|
||||
* @param szBuffer device status data, it is an address of a struct matchs iType, e.g: VLK_DEV_MODEL
|
||||
* @param iBufLen device status data length, it must be equal to the size of struct matchs iType, e.g: iBufLen == sizeof(VLK_DEV_MODEL)
|
||||
* @return return 0 anyway
|
||||
* @details VLK_DevStatus_CB will be called by SDK once device new status is received, developers can easily get Gimbal latest status
|
||||
* @see VLK_RegisterDevStatusCB
|
||||
*/
|
||||
typedef int (*VLK_DevStatus_CB)(int iType, const char* szBuffer, int iBufLen, void* pUserParam);
|
||||
/** @} ViewLink SDK callback functions */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Get SDK version
|
||||
* @return SDK version number, e.g: 3.0.6
|
||||
* @details we recommend printing the SDK version number before you use SDK,
|
||||
* this is the only interface can be called before VLK_Init()
|
||||
*/
|
||||
VLK_API const char* VLK_CALL GetSDKVersion();
|
||||
|
||||
/** @brief Initialize SDK
|
||||
* @return VLK_ERROR_NO_ERROR on success, error code otherwise
|
||||
* @details it should be called somewhere at the beginning of your application,
|
||||
* and it should be called just once during the lifecirle of your application,
|
||||
* all interfaces are unavailbe before initialized
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_Init();
|
||||
|
||||
/** @brief Uninitialize SDK
|
||||
* @details it should be called somewhere at the end of your application,
|
||||
* and it should be called just once during the lifecirle of your application,
|
||||
* once you uninitialize sdk, all interfaces are nomore available
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_UnInit();
|
||||
|
||||
/** @brief connect Gimbal with specific type, TCP and serial port are available
|
||||
* @param pConnParam connect information, including connection type (TCP or serial port), ip address, port, serial port name, baudrate
|
||||
* @param pConnStatusCB connnection status callback function, it will be called by SDK when device is connected or disconnected
|
||||
* @param pUserParam user parameters, will be passed back when pConnStatusCB is called
|
||||
* @return VLK_ERROR_NO_ERROR on success, error code otherwise
|
||||
* @details this function is asynchronous, the connect result will be passed back by callback function, do not use return value to judge connect result.
|
||||
* SDK allows only one connection, it means if you create a new connection, the previous one will be disconnected automatically
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_Connect(const VLK_CONN_PARAM* pConnParam, VLK_ConnStatus_CB pConnStatusCB, void* pUserParam);
|
||||
|
||||
/** @brief Check if Gimbal is connected
|
||||
* @return
|
||||
* @retval 1 if either TCP or serial port is connected
|
||||
* @retval 0 if neither TCP nor serial port is connected
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsConnected();
|
||||
|
||||
/** @brief Check if Gimbal is TCP connected
|
||||
* @return
|
||||
* @retval 1 if TCP is connected
|
||||
* @retval 0 if TCP is disconnected
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsTCPConnected();
|
||||
|
||||
/** @brief Check if Gimbal is serial port connected
|
||||
* @return
|
||||
* @retval 1 if serial port is connected
|
||||
* @retval 0 if serial port is disconnected
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsSerialPortConnected();
|
||||
|
||||
/** @brief Disconnect current connection no matter it is TCP, serial port or other
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_Disconnect();
|
||||
|
||||
/** @brief Disconnect current TCP connection
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_DisconnectTCP();
|
||||
|
||||
/** @brief Disconnect current serial port connection
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_DisconnectSerialPort();
|
||||
|
||||
/** @brief Set keep alive interval
|
||||
* @param iMS keep alive interval in milliseconds range from 100 ms to 5000 ms
|
||||
* @details keep alive interval determines the frequncy of querying Gimbal telemetry data,
|
||||
* SDK default keep alive interval is 500 ms, no need to change it if not necessary
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetKeepAliveInterval(int iMS);
|
||||
|
||||
/** @brief Register device status callback
|
||||
* @param pDevStatusCB receive device status callback function
|
||||
* @param pUserParam user parameter, it will be passed back when pDevStatusCB is called
|
||||
* @details pDevStatusCB will be called once SDK received new Gimbal,
|
||||
* specifically, the telemetry data will keep updating once device is connected,
|
||||
* ignore it if you don't need it
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_RegisterDevStatusCB(VLK_DevStatus_CB pDevStatusCB, void* pUserParam);
|
||||
|
||||
/** @brief Control Gimbal yaw and pitch
|
||||
* @param sHorizontalSpeed the speed of changing yaw (0.01 degrees/s), for example, 2000 means 20 degrees per second
|
||||
* @param sVeritcalSpeed the speed of changing pitch (0.01 degrees/s)
|
||||
* @details considering a small angle adjustment will result in a huge visual field changing in sky view, we limit
|
||||
* speed in a proper range: \n
|
||||
* -VLK_MAX_YAW_SPEED <= sHorizontalSpeed <= VLK_MAX_YAW_SPEED \n
|
||||
* -VLK_MAX_PITCH_SPEED <= sVeritcalSpeed <= VLK_MAX_PITCH_SPEED \n
|
||||
* some example: \n
|
||||
* move up: VLK_Move(0, 1000); \n
|
||||
* move left: VLK_Move(-1000, 0); \n
|
||||
* move right: VLK_Move(1000, 0); \n
|
||||
* move down: VLK_Move(0, -1000);
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_Move(short sHorizontalSpeed, short sVeritcalSpeed);
|
||||
|
||||
/** @brief Stop moving
|
||||
* @details once you call VLK_Move, Gimbal will keep moving until it reach the yaw and pitch limitation or VLK_Stop is called
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_Stop();
|
||||
|
||||
/** @brief Zoom in
|
||||
* @param sSpeed the speed of zoom in
|
||||
* @details sSpeed must be a short number from VLK_MIN_ZOOM_SPEED to VLK_MAX_ZOOM_SPEED, the bigger the faster
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_ZoomIn(short sSpeed);
|
||||
|
||||
/** @brief Zoom out
|
||||
* @param sSpeed the speed of zoom out
|
||||
* @details sSpeed must be a short number from VLK_MIN_ZOOM_SPEED to VLK_MAX_ZOOM_SPEED, the bigger the faster
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_ZoomOut(short sSpeed);
|
||||
|
||||
/** @brief Stop zoom
|
||||
* @details once you call VLK_ZoomIn or VLK_ZoomOut, Camera will keep zooming until it reach the limitation or VLK_StopZoom is called
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_StopZoom();
|
||||
|
||||
/** @brief Enable track mode
|
||||
* @param Param track mode parameters
|
||||
* @see VLK_TrackTargetPositionEx
|
||||
* @deprecated
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_EnableTrackMode(const VLK_TRACK_MODE_PARAM* pParam);
|
||||
|
||||
/** @brief Track target by it's position
|
||||
* @param iX target position, number of pixels from top-left corner in horizontal direction
|
||||
* @param iY taget position, number of pixels from top-left corner in vertical direction
|
||||
* @param iVideoWidth video image width, e.g: 1920, 1280
|
||||
* @param iVideoHeight video image height, e.g: 1080, 720
|
||||
* @deprecated
|
||||
* @see VLK_TrackTargetPositionEx
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_TrackTargetPosition(int iX, int iY, int iVideoWidth, int iVideoHeight);
|
||||
|
||||
/** @brief Track target by it's position
|
||||
* @param pParam track mode parameters,
|
||||
* @param iX target position, number of pixels from top-left corner in horizontal direction
|
||||
* @param iY taget position, number of pixels from top-left corner in vertical direction
|
||||
* @param iVideoWidth video image width, e.g: 1920, 1280
|
||||
* @param iVideoHeight video image height, e.g: 1080, 720
|
||||
* @details we usually use VLK_TRACK_TEMPLATE_SIZE_AUTO for pParam->emTrackTempSize and VLK_SENSOR_VISIBLE1 for pParam->emTrackSensor
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_TrackTargetPositionEx(const VLK_TRACK_MODE_PARAM* pParam, int iX, int iY, int iVideoWidth, int iVideoHeight);
|
||||
|
||||
/** @brief Disable track mode
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_DisableTrackMode();
|
||||
|
||||
/** @brief Focus in
|
||||
* @param sSpeed the speed of focus in
|
||||
* @details sSpeed must be a short number from VLK_MIN_ZOOM_SPEED to VLK_MAX_ZOOM_SPEED, the bigger the faster
|
||||
* this function is available only when the Gimbal is in Manual focusing mode, call VLK_GetFocusMode to
|
||||
* get current focus mode, call VLK_SetFocusMode to set focus mode
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_FocusIn(short sSpeed);
|
||||
|
||||
/** @brief Focus out
|
||||
* @param sSpeed the speed of focus out
|
||||
* @details sSpeed must be a short number from VLK_MIN_ZOOM_SPEED to VLK_MAX_ZOOM_SPEED, the bigger the faster
|
||||
* this function is available only when the Gimbal is in Manual focusing mode, call VLK_GetFocusMode to
|
||||
* get current focus mode, call VLK_SetFocusMode to set focus mode
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_FocusOut(short sSpeed);
|
||||
|
||||
/** @brief Stop focus
|
||||
* @details once you call VLK_FocusIn or VLK_FocusOut, Camera will keep focusing until it reach the limitation or VLK_StopFocus is called
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_StopFocus();
|
||||
|
||||
/** @brief Move to home position
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_Home();
|
||||
|
||||
/** @brief Switch motor
|
||||
* @param iOn turn on/turn off \n
|
||||
* 1 turn on \n
|
||||
* 0 turn off
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SwitchMotor(int iOn);
|
||||
|
||||
/** @brief Check motor status
|
||||
* @return current motor status
|
||||
* @retval 1 on
|
||||
* @retval 0 off
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsMotorOn();
|
||||
|
||||
/** @brief Enable Gimbal follow drone
|
||||
* @param iEnable enable or disable \n
|
||||
* 1 enable \n
|
||||
* 0 disable
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_EnableFollowMode(int iEnable);
|
||||
|
||||
/** @brief Check follow mode
|
||||
* @return current follow status
|
||||
* @retval 1 enabled
|
||||
* @retval 0 disabled
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsFollowMode();
|
||||
|
||||
/** @brief Turn to specific yaw and pitch
|
||||
* @param dYaw specific yaw, must be a double value from VLK_YAW_MIN to VLK_YAW_MAX
|
||||
* @param dPitch specific pitch, must be a double value from VLK_PITCH_MIN to VLK_PITCH_MAX
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_TurnTo(double dYaw, double dPitch);
|
||||
|
||||
/** @brief Enable track
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_StartTrack();
|
||||
|
||||
|
||||
/** @brief Disable track
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_StopTrack();
|
||||
|
||||
/** @brief Check if track is enabled
|
||||
* @return current track status
|
||||
* @retval 1 enabled
|
||||
* @retval 0 disabled
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsTracking();
|
||||
|
||||
/** @brief Set track template size
|
||||
* @param emSize track template size enumeration
|
||||
* @see VLK_TRACK_TEMPLATE_SIZE
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetTrackTemplateSize(VLK_TRACK_TEMPLATE_SIZE emSize);
|
||||
|
||||
/** @brief Set image color
|
||||
* @param emImgType image type enumeration
|
||||
* @param iEnablePIP enable picture in picture \n
|
||||
* 1 enable \n
|
||||
* 0 disable
|
||||
* @param emIRColor IR color enumeration
|
||||
* @see VLK_IMAGE_TYPE
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetImageColor(VLK_IMAGE_TYPE emImgType, int iEnablePIP, VLK_IR_COLOR emIRColor);
|
||||
|
||||
/** @brief Ask Gimbal take a photograph
|
||||
* @details make sure there is SD card in the Gimbal
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_Photograph();
|
||||
|
||||
/** @brief Gimbal start or stop recording
|
||||
* @param iOn \n
|
||||
* 1 start recording \n
|
||||
* 0 stop recording
|
||||
* @details make sure there is SD card in the Gimbal
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SwitchRecord(int iOn);
|
||||
|
||||
/** @brief Check if Gimbal is recording
|
||||
* @return flag of recording status
|
||||
* @retval 1 recording
|
||||
* @retval 0 not recording
|
||||
* @details make sure there is SD card in the Gimbal
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsRecording();
|
||||
|
||||
/** @brief Enable defog
|
||||
* @param iOn \n
|
||||
* 1 defog is enabled \n
|
||||
* 0 defog is disabled
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SwitchDefog(int iOn);
|
||||
|
||||
/** @brief Check if defog is enabled
|
||||
* @return flag of defog status
|
||||
* @retval 1 defog is enabled
|
||||
* @retval 0 defog is disabled
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_IsDefogOn();
|
||||
|
||||
/** @brief Set record mode
|
||||
* @param emMode record mode enumeration
|
||||
* @details some models could not take photo while it is recording,
|
||||
* they must be switched to a certain
|
||||
* @see VLK_RECORD_MODE
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetRecordMode(VLK_RECORD_MODE emMode);
|
||||
|
||||
/** @brief Get current record mode
|
||||
* @return record mode enumeration
|
||||
* @see VLK_RECORD_MODE
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_GetRecordMode();
|
||||
|
||||
/** @brief Set focus mode ( manual focus or automatic focus)
|
||||
* @param focus mode enumeration
|
||||
* @see VLK_FOCUS_MODE
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetFocusMode(VLK_FOCUS_MODE emMode);
|
||||
|
||||
/** @brief Get current focus mode ( manual focus or automatic focus)
|
||||
* @return focus mode enumeration
|
||||
* @see VLK_FOCUS_MODE
|
||||
*/
|
||||
VLK_API int VLK_CALL VLK_GetFocusMode();
|
||||
|
||||
/** @brief Zoom to a specific magnification
|
||||
* @param fMag specific magnification
|
||||
* @details the camera will reach the limitation if the specific magnification over it's capability
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_ZoomTo(float fMag);
|
||||
|
||||
/** @brief IR digital zoom in
|
||||
* @param sSpeed deprecated, pass 0
|
||||
* @details zoom in x1 then stop automatically
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_IRDigitalZoomIn(short sSpeed);
|
||||
|
||||
/** @brief IR digital zoom out
|
||||
* @param sSpeed deprecated, pass 0
|
||||
* @details zoom out x1 then stop automatically
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_IRDigitalZoomOut(short sSpeed);
|
||||
|
||||
/** @brief Switch EO digital zoom status
|
||||
* @param iOn \n
|
||||
* 1 enable \n
|
||||
* 0 disable
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SwitchEODigitalZoom(int iOn);
|
||||
|
||||
/** @brief Enter S-BUS mode
|
||||
* @deprecated
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_EnterSBUSMode();
|
||||
|
||||
/** @brief Exit S-BUS mode
|
||||
* @deprecated
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_ExitSBUSMode();
|
||||
|
||||
/** @brief Query device configuration
|
||||
* @details this function is asynchronous, configuration data will be passed back throw VLK_DevStatus_CB
|
||||
* @see VLK_DevStatus_CB
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_QueryDevConfiguration();
|
||||
|
||||
/** @brief Set OSD
|
||||
* @param pParam OSG configuration
|
||||
* @details we don't provide VLK_GetOSD because OSD is included in device configuration
|
||||
* @see VLK_OSD_PARAM
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetOSD(const VLK_OSD_PARAM* pParam);
|
||||
|
||||
/** @brief Set wireless control channels map
|
||||
* @param pChnlsMap wireless control channels map configuration
|
||||
* @details we don't provide VLK_GetWirelessCtrlChnlMap because channels map is included in device configuration
|
||||
* @see VLK_CHANNELS_MAP
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetWirelessCtrlChnlMap(const VLK_CHANNELS_MAP* pChnlsMap);
|
||||
|
||||
/** @brief Send extent command
|
||||
* @param szCmd command data pointer
|
||||
* @param iLen command data length
|
||||
* @details for some seldom-used Gimbal control command which we didn't provide specific interface,
|
||||
* you should call this function to send command data directly
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SendExtentCmd(const char* szCmd, int iLen);
|
||||
|
||||
|
||||
/** @name Laser Control functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Switch laser status
|
||||
* @param iOn \n
|
||||
* 1 turn on \n
|
||||
* 0 turn off
|
||||
* @details make sure your device has laser capability
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SwitchLaser(int iOn);
|
||||
|
||||
/** @brief Laser single ranging
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_LaserSingle();
|
||||
|
||||
|
||||
/** @brief Laser zoom in
|
||||
* @param sSpeed deprecated, pass 0
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_LaserZoomIn(short sSpeed);
|
||||
|
||||
/** @brief Laser zoom out
|
||||
* @param sSpeed deprecated, pass 0
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_LaserZoomOut(short sSpeed);
|
||||
|
||||
/** @brief Laser stop zoom
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_LaserStopZoom();
|
||||
|
||||
/** @brief Set laser zoom mode
|
||||
* @param emMode laser zoom mode enumeration
|
||||
*/
|
||||
VLK_API void VLK_CALL VLK_SetLaserZoomMode(VLK_LASER_ZOOM_MODE emMode);
|
||||
/** @} Laser Control functions */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__VIEW_LINK_H__
|
@ -0,0 +1,293 @@
|
||||
#include <algorithm>
|
||||
|
||||
#if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "serial/serial.h"
|
||||
|
||||
#include "serial/impl/unix.h"
|
||||
|
||||
using std::invalid_argument;
|
||||
using std::min;
|
||||
using std::numeric_limits;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
using serial::bytesize_t;
|
||||
using serial::flowcontrol_t;
|
||||
using serial::IOException;
|
||||
using serial::parity_t;
|
||||
using serial::Serial;
|
||||
using serial::SerialException;
|
||||
using serial::stopbits_t;
|
||||
|
||||
class Serial::ScopedReadLock {
|
||||
public:
|
||||
ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) {
|
||||
this->pimpl_->readLock();
|
||||
}
|
||||
~ScopedReadLock() { this->pimpl_->readUnlock(); }
|
||||
|
||||
private:
|
||||
// Disable copy constructors
|
||||
ScopedReadLock(const ScopedReadLock &);
|
||||
const ScopedReadLock &operator=(ScopedReadLock);
|
||||
|
||||
SerialImpl *pimpl_;
|
||||
};
|
||||
|
||||
class Serial::ScopedWriteLock {
|
||||
public:
|
||||
ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) {
|
||||
this->pimpl_->writeLock();
|
||||
}
|
||||
~ScopedWriteLock() { this->pimpl_->writeUnlock(); }
|
||||
|
||||
private:
|
||||
// Disable copy constructors there
|
||||
ScopedWriteLock(const ScopedWriteLock &);
|
||||
const ScopedWriteLock &operator=(ScopedWriteLock);
|
||||
SerialImpl *pimpl_;
|
||||
};
|
||||
|
||||
Serial::Serial(const string &port, uint32_t baudrate, serial::Timeout timeout,
|
||||
bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
|
||||
flowcontrol_t flowcontrol)
|
||||
: pimpl_(new SerialImpl(port, baudrate, bytesize, parity, stopbits,
|
||||
flowcontrol)) {
|
||||
pimpl_->setTimeout(timeout);
|
||||
}
|
||||
|
||||
Serial::~Serial() { delete pimpl_; }
|
||||
|
||||
void Serial::open() { pimpl_->open(); }
|
||||
|
||||
void Serial::close() { pimpl_->close(); }
|
||||
|
||||
bool Serial::isOpen() const { return pimpl_->isOpen(); }
|
||||
|
||||
size_t Serial::available() { return pimpl_->available(); }
|
||||
|
||||
bool Serial::waitReadable() {
|
||||
serial::Timeout timeout(pimpl_->getTimeout());
|
||||
return pimpl_->waitReadable(timeout.read_timeout_constant);
|
||||
}
|
||||
|
||||
void Serial::waitByteTimes(size_t count) { pimpl_->waitByteTimes(count); }
|
||||
|
||||
size_t Serial::read_(uint8_t *buffer, size_t size) {
|
||||
return this->pimpl_->read(buffer, size);
|
||||
}
|
||||
|
||||
size_t Serial::read(uint8_t *buffer, size_t size) {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
return this->pimpl_->read(buffer, size);
|
||||
}
|
||||
|
||||
size_t Serial::read(std::vector<uint8_t> &buffer, size_t size) {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
uint8_t *buffer_ = new uint8_t[size];
|
||||
size_t bytes_read = 0;
|
||||
|
||||
try {
|
||||
bytes_read = this->pimpl_->read(buffer_, size);
|
||||
} catch (const std::exception &e) {
|
||||
delete[] buffer_;
|
||||
throw;
|
||||
}
|
||||
|
||||
buffer.insert(buffer.end(), buffer_, buffer_ + bytes_read);
|
||||
delete[] buffer_;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
size_t Serial::read(std::string &buffer, size_t size) {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
uint8_t *buffer_ = new uint8_t[size];
|
||||
size_t bytes_read = 0;
|
||||
try {
|
||||
bytes_read = this->pimpl_->read(buffer_, size);
|
||||
} catch (const std::exception &e) {
|
||||
delete[] buffer_;
|
||||
throw;
|
||||
}
|
||||
buffer.append(reinterpret_cast<const char *>(buffer_), bytes_read);
|
||||
delete[] buffer_;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
string Serial::read(size_t size) {
|
||||
std::string buffer;
|
||||
this->read(buffer, size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
size_t Serial::readline(string &buffer, size_t size, string eol) {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
size_t eol_len = eol.length();
|
||||
uint8_t *buffer_ = static_cast<uint8_t *>(alloca(size * sizeof(uint8_t)));
|
||||
size_t read_so_far = 0;
|
||||
while (true) {
|
||||
size_t bytes_read = this->read_(buffer_ + read_so_far, 1);
|
||||
read_so_far += bytes_read;
|
||||
if (bytes_read == 0) {
|
||||
break; // Timeout occured on reading 1 byte
|
||||
}
|
||||
if (read_so_far < eol_len)
|
||||
continue;
|
||||
if (string(reinterpret_cast<const char *>(buffer_ + read_so_far - eol_len),
|
||||
eol_len) == eol) {
|
||||
break; // EOL found
|
||||
}
|
||||
if (read_so_far == size) {
|
||||
break; // Reached the maximum read length
|
||||
}
|
||||
}
|
||||
buffer.append(reinterpret_cast<const char *>(buffer_), read_so_far);
|
||||
return read_so_far;
|
||||
}
|
||||
|
||||
string Serial::readline(size_t size, string eol) {
|
||||
std::string buffer;
|
||||
this->readline(buffer, size, eol);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
vector<string> Serial::readlines(size_t size, string eol) {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
std::vector<std::string> lines;
|
||||
size_t eol_len = eol.length();
|
||||
uint8_t *buffer_ = static_cast<uint8_t *>(alloca(size * sizeof(uint8_t)));
|
||||
size_t read_so_far = 0;
|
||||
size_t start_of_line = 0;
|
||||
while (read_so_far < size) {
|
||||
size_t bytes_read = this->read_(buffer_ + read_so_far, 1);
|
||||
read_so_far += bytes_read;
|
||||
if (bytes_read == 0) {
|
||||
if (start_of_line != read_so_far) {
|
||||
lines.push_back(
|
||||
string(reinterpret_cast<const char *>(buffer_ + start_of_line),
|
||||
read_so_far - start_of_line));
|
||||
}
|
||||
break; // Timeout occured on reading 1 byte
|
||||
}
|
||||
if (read_so_far < eol_len)
|
||||
continue;
|
||||
if (string(reinterpret_cast<const char *>(buffer_ + read_so_far - eol_len),
|
||||
eol_len) == eol) {
|
||||
// EOL found
|
||||
lines.push_back(
|
||||
string(reinterpret_cast<const char *>(buffer_ + start_of_line),
|
||||
read_so_far - start_of_line));
|
||||
start_of_line = read_so_far;
|
||||
}
|
||||
if (read_so_far == size) {
|
||||
if (start_of_line != read_so_far) {
|
||||
lines.push_back(
|
||||
string(reinterpret_cast<const char *>(buffer_ + start_of_line),
|
||||
read_so_far - start_of_line));
|
||||
}
|
||||
break; // Reached the maximum read length
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
size_t Serial::write(const string &data) {
|
||||
ScopedWriteLock lock(this->pimpl_);
|
||||
return this->write_(reinterpret_cast<const uint8_t *>(data.c_str()),
|
||||
data.length());
|
||||
}
|
||||
|
||||
size_t Serial::write(const std::vector<uint8_t> &data) {
|
||||
ScopedWriteLock lock(this->pimpl_);
|
||||
return this->write_(&data[0], data.size());
|
||||
}
|
||||
|
||||
size_t Serial::write(const uint8_t *data, size_t size) {
|
||||
ScopedWriteLock lock(this->pimpl_);
|
||||
return this->write_(data, size);
|
||||
}
|
||||
|
||||
size_t Serial::write_(const uint8_t *data, size_t length) {
|
||||
return pimpl_->write(data, length);
|
||||
}
|
||||
|
||||
void Serial::setPort(const string &port) {
|
||||
ScopedReadLock rlock(this->pimpl_);
|
||||
ScopedWriteLock wlock(this->pimpl_);
|
||||
bool was_open = pimpl_->isOpen();
|
||||
if (was_open)
|
||||
close();
|
||||
pimpl_->setPort(port);
|
||||
if (was_open)
|
||||
open();
|
||||
}
|
||||
|
||||
string Serial::getPort() const { return pimpl_->getPort(); }
|
||||
|
||||
void Serial::setTimeout(serial::Timeout &timeout) {
|
||||
pimpl_->setTimeout(timeout);
|
||||
}
|
||||
|
||||
serial::Timeout Serial::getTimeout() const { return pimpl_->getTimeout(); }
|
||||
|
||||
void Serial::setBaudrate(uint32_t baudrate) { pimpl_->setBaudrate(baudrate); }
|
||||
|
||||
uint32_t Serial::getBaudrate() const { return uint32_t(pimpl_->getBaudrate()); }
|
||||
|
||||
void Serial::setBytesize(bytesize_t bytesize) { pimpl_->setBytesize(bytesize); }
|
||||
|
||||
bytesize_t Serial::getBytesize() const { return pimpl_->getBytesize(); }
|
||||
|
||||
void Serial::setParity(parity_t parity) { pimpl_->setParity(parity); }
|
||||
|
||||
parity_t Serial::getParity() const { return pimpl_->getParity(); }
|
||||
|
||||
void Serial::setStopbits(stopbits_t stopbits) { pimpl_->setStopbits(stopbits); }
|
||||
|
||||
stopbits_t Serial::getStopbits() const { return pimpl_->getStopbits(); }
|
||||
|
||||
void Serial::setFlowcontrol(flowcontrol_t flowcontrol) {
|
||||
pimpl_->setFlowcontrol(flowcontrol);
|
||||
}
|
||||
|
||||
flowcontrol_t Serial::getFlowcontrol() const {
|
||||
return pimpl_->getFlowcontrol();
|
||||
}
|
||||
|
||||
void Serial::flush() {
|
||||
ScopedReadLock rlock(this->pimpl_);
|
||||
ScopedWriteLock wlock(this->pimpl_);
|
||||
pimpl_->flush();
|
||||
}
|
||||
|
||||
void Serial::flushInput() {
|
||||
ScopedReadLock lock(this->pimpl_);
|
||||
pimpl_->flushInput();
|
||||
}
|
||||
|
||||
void Serial::flushOutput() {
|
||||
ScopedWriteLock lock(this->pimpl_);
|
||||
pimpl_->flushOutput();
|
||||
}
|
||||
|
||||
void Serial::sendBreak(int duration) { pimpl_->sendBreak(duration); }
|
||||
|
||||
void Serial::setBreak(bool level) { pimpl_->setBreak(level); }
|
||||
|
||||
void Serial::setRTS(bool level) { pimpl_->setRTS(level); }
|
||||
|
||||
void Serial::setDTR(bool level) { pimpl_->setDTR(level); }
|
||||
|
||||
bool Serial::waitForChange() { return pimpl_->waitForChange(); }
|
||||
|
||||
bool Serial::getCTS() { return pimpl_->getCTS(); }
|
||||
|
||||
bool Serial::getDSR() { return pimpl_->getDSR(); }
|
||||
|
||||
bool Serial::getRI() { return pimpl_->getRI(); }
|
||||
|
||||
bool Serial::getCD() { return pimpl_->getCD(); }
|
Loading…
Reference in new issue