diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/CasicDevPhase.h b/CasicDevPhase.h new file mode 100644 index 0000000..05751fb --- /dev/null +++ b/CasicDevPhase.h @@ -0,0 +1,89 @@ +#ifndef CASICDEVPHASE_H +#define CASICDEVPHASE_H + +#include +#include +#include +#include "PhaseProtocolBM.h" +#include "PhaseDataDto.h" + +namespace casic { + namespace birmm { + namespace tflab { + class CasicDevPhase + { + public: + CasicDevPhase(); + + /** + * @brief frameParse 解析协议字节数组并计算稳定度 + * @param rawBytes 入参 从设备取到的原始二进制字节 + * @param frameSN 出参 帧计数 + * @param channelValue 出参 各通道补偿后的时差数据 + * @param channelExtra 出参 各通道的扩展输出数据 目前仅包括1秒稳定度 + * @return int 返回是否成功 0=成功 -1=帧解析失败 -2=稳定度结果无效 + */ + int frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra); + + /** + * @brief setChannelDelay 设置各通道时延补偿绝对值 + * @param channelDelay 入参 各通道的时延补偿绝对值 + * @return int 返回是否设置成功 0=成功 -1=失败 + */ + int setChannelDelay(QList channelDelay); + + /** + * @brief getChannelDelay 获取各通道时延补偿绝对值 + * @return QList 当前使用的各通道时延补偿值 + */ + QList getChannelDelay(); + + private: + /** + * @brief channelDelay 各通道的时延补偿值 + */ + QList channelDelay; + + /** + * @brief frameId 需要返回的帧编号 + */ + qulonglong frameId; + + /** + * @brief frameCount 总共的帧计数 + */ + qulonglong frameCount; + + /** + * @brief phaseVector 各个通道的时差数据 只保留最近的五组数据 + * 用于计算稳定度 + */ + QVector> phaseVector; + + /** + * @brief lastSigmaVector 计算Allen方差时的上一个平方和 + */ + QList lastSigmaVector; + + /** + * @brief allan 计算指定数组的阿伦方差值 + * @param channelData 指定数组 + * @param d 采样间隔 默认值=1 + * @param aN 数组长度 + * @param lastSigma 上一个平方和 需要取到并保存以用于下次计算 + * @return 返回值 开方后的值 + */ + double calcAllen(int index, int aN); + }; + + enum RETURN_STATUS { + SUCCESS = 0, + FAIL = -1, + INVALID = -2 + }; + } + } +} + + +#endif // CASICDEVPHASE_H diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/CasicDevPhase.h b/CasicDevPhase.h new file mode 100644 index 0000000..05751fb --- /dev/null +++ b/CasicDevPhase.h @@ -0,0 +1,89 @@ +#ifndef CASICDEVPHASE_H +#define CASICDEVPHASE_H + +#include +#include +#include +#include "PhaseProtocolBM.h" +#include "PhaseDataDto.h" + +namespace casic { + namespace birmm { + namespace tflab { + class CasicDevPhase + { + public: + CasicDevPhase(); + + /** + * @brief frameParse 解析协议字节数组并计算稳定度 + * @param rawBytes 入参 从设备取到的原始二进制字节 + * @param frameSN 出参 帧计数 + * @param channelValue 出参 各通道补偿后的时差数据 + * @param channelExtra 出参 各通道的扩展输出数据 目前仅包括1秒稳定度 + * @return int 返回是否成功 0=成功 -1=帧解析失败 -2=稳定度结果无效 + */ + int frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra); + + /** + * @brief setChannelDelay 设置各通道时延补偿绝对值 + * @param channelDelay 入参 各通道的时延补偿绝对值 + * @return int 返回是否设置成功 0=成功 -1=失败 + */ + int setChannelDelay(QList channelDelay); + + /** + * @brief getChannelDelay 获取各通道时延补偿绝对值 + * @return QList 当前使用的各通道时延补偿值 + */ + QList getChannelDelay(); + + private: + /** + * @brief channelDelay 各通道的时延补偿值 + */ + QList channelDelay; + + /** + * @brief frameId 需要返回的帧编号 + */ + qulonglong frameId; + + /** + * @brief frameCount 总共的帧计数 + */ + qulonglong frameCount; + + /** + * @brief phaseVector 各个通道的时差数据 只保留最近的五组数据 + * 用于计算稳定度 + */ + QVector> phaseVector; + + /** + * @brief lastSigmaVector 计算Allen方差时的上一个平方和 + */ + QList lastSigmaVector; + + /** + * @brief allan 计算指定数组的阿伦方差值 + * @param channelData 指定数组 + * @param d 采样间隔 默认值=1 + * @param aN 数组长度 + * @param lastSigma 上一个平方和 需要取到并保存以用于下次计算 + * @return 返回值 开方后的值 + */ + double calcAllen(int index, int aN); + }; + + enum RETURN_STATUS { + SUCCESS = 0, + FAIL = -1, + INVALID = -2 + }; + } + } +} + + +#endif // CASICDEVPHASE_H diff --git a/DevPhaseLib.pro b/DevPhaseLib.pro new file mode 100644 index 0000000..172ed6a --- /dev/null +++ b/DevPhaseLib.pro @@ -0,0 +1,32 @@ +QT -= gui + +TEMPLATE = lib +CONFIG += dynamiclib + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += CasicDevPhase.cpp +SOURCES += PhaseProtocolBM.cpp +SOURCES += ByteUtil.cpp + +HEADERS += CasicDevPhase.h +HEADERS += PhaseProtocolBM.h +HEADERS += PhaseDataDto.h +HEADERS += ByteUtil.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/CasicDevPhase.h b/CasicDevPhase.h new file mode 100644 index 0000000..05751fb --- /dev/null +++ b/CasicDevPhase.h @@ -0,0 +1,89 @@ +#ifndef CASICDEVPHASE_H +#define CASICDEVPHASE_H + +#include +#include +#include +#include "PhaseProtocolBM.h" +#include "PhaseDataDto.h" + +namespace casic { + namespace birmm { + namespace tflab { + class CasicDevPhase + { + public: + CasicDevPhase(); + + /** + * @brief frameParse 解析协议字节数组并计算稳定度 + * @param rawBytes 入参 从设备取到的原始二进制字节 + * @param frameSN 出参 帧计数 + * @param channelValue 出参 各通道补偿后的时差数据 + * @param channelExtra 出参 各通道的扩展输出数据 目前仅包括1秒稳定度 + * @return int 返回是否成功 0=成功 -1=帧解析失败 -2=稳定度结果无效 + */ + int frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra); + + /** + * @brief setChannelDelay 设置各通道时延补偿绝对值 + * @param channelDelay 入参 各通道的时延补偿绝对值 + * @return int 返回是否设置成功 0=成功 -1=失败 + */ + int setChannelDelay(QList channelDelay); + + /** + * @brief getChannelDelay 获取各通道时延补偿绝对值 + * @return QList 当前使用的各通道时延补偿值 + */ + QList getChannelDelay(); + + private: + /** + * @brief channelDelay 各通道的时延补偿值 + */ + QList channelDelay; + + /** + * @brief frameId 需要返回的帧编号 + */ + qulonglong frameId; + + /** + * @brief frameCount 总共的帧计数 + */ + qulonglong frameCount; + + /** + * @brief phaseVector 各个通道的时差数据 只保留最近的五组数据 + * 用于计算稳定度 + */ + QVector> phaseVector; + + /** + * @brief lastSigmaVector 计算Allen方差时的上一个平方和 + */ + QList lastSigmaVector; + + /** + * @brief allan 计算指定数组的阿伦方差值 + * @param channelData 指定数组 + * @param d 采样间隔 默认值=1 + * @param aN 数组长度 + * @param lastSigma 上一个平方和 需要取到并保存以用于下次计算 + * @return 返回值 开方后的值 + */ + double calcAllen(int index, int aN); + }; + + enum RETURN_STATUS { + SUCCESS = 0, + FAIL = -1, + INVALID = -2 + }; + } + } +} + + +#endif // CASICDEVPHASE_H diff --git a/DevPhaseLib.pro b/DevPhaseLib.pro new file mode 100644 index 0000000..172ed6a --- /dev/null +++ b/DevPhaseLib.pro @@ -0,0 +1,32 @@ +QT -= gui + +TEMPLATE = lib +CONFIG += dynamiclib + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += CasicDevPhase.cpp +SOURCES += PhaseProtocolBM.cpp +SOURCES += ByteUtil.cpp + +HEADERS += CasicDevPhase.h +HEADERS += PhaseProtocolBM.h +HEADERS += PhaseDataDto.h +HEADERS += ByteUtil.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target diff --git a/PhaseDataDto.h b/PhaseDataDto.h new file mode 100644 index 0000000..e43ae95 --- /dev/null +++ b/PhaseDataDto.h @@ -0,0 +1,27 @@ +#ifndef PHASEDATADTO_H +#define PHASEDATADTO_H + +#include +#include +#include + +class PhaseDataDto +{ +public: + PhaseDataDto() {} + + QString frameId; // 帧id + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QByteArray rawFrame; // 原始帧字节数组 + + QString devCode; + QString devStatus; + QList channelActive; + QList rawPhaseDiffData; // 原始相差数据 + QList channelBeforeDelay; // 补偿前的时差数据 + QList channelData; // 补偿后的时差数据 + QList channelDataStr; // 补偿后的时差数据格式化显示字符串 +}; + +#endif // PHASEDATADTO_H diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/CasicDevPhase.h b/CasicDevPhase.h new file mode 100644 index 0000000..05751fb --- /dev/null +++ b/CasicDevPhase.h @@ -0,0 +1,89 @@ +#ifndef CASICDEVPHASE_H +#define CASICDEVPHASE_H + +#include +#include +#include +#include "PhaseProtocolBM.h" +#include "PhaseDataDto.h" + +namespace casic { + namespace birmm { + namespace tflab { + class CasicDevPhase + { + public: + CasicDevPhase(); + + /** + * @brief frameParse 解析协议字节数组并计算稳定度 + * @param rawBytes 入参 从设备取到的原始二进制字节 + * @param frameSN 出参 帧计数 + * @param channelValue 出参 各通道补偿后的时差数据 + * @param channelExtra 出参 各通道的扩展输出数据 目前仅包括1秒稳定度 + * @return int 返回是否成功 0=成功 -1=帧解析失败 -2=稳定度结果无效 + */ + int frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra); + + /** + * @brief setChannelDelay 设置各通道时延补偿绝对值 + * @param channelDelay 入参 各通道的时延补偿绝对值 + * @return int 返回是否设置成功 0=成功 -1=失败 + */ + int setChannelDelay(QList channelDelay); + + /** + * @brief getChannelDelay 获取各通道时延补偿绝对值 + * @return QList 当前使用的各通道时延补偿值 + */ + QList getChannelDelay(); + + private: + /** + * @brief channelDelay 各通道的时延补偿值 + */ + QList channelDelay; + + /** + * @brief frameId 需要返回的帧编号 + */ + qulonglong frameId; + + /** + * @brief frameCount 总共的帧计数 + */ + qulonglong frameCount; + + /** + * @brief phaseVector 各个通道的时差数据 只保留最近的五组数据 + * 用于计算稳定度 + */ + QVector> phaseVector; + + /** + * @brief lastSigmaVector 计算Allen方差时的上一个平方和 + */ + QList lastSigmaVector; + + /** + * @brief allan 计算指定数组的阿伦方差值 + * @param channelData 指定数组 + * @param d 采样间隔 默认值=1 + * @param aN 数组长度 + * @param lastSigma 上一个平方和 需要取到并保存以用于下次计算 + * @return 返回值 开方后的值 + */ + double calcAllen(int index, int aN); + }; + + enum RETURN_STATUS { + SUCCESS = 0, + FAIL = -1, + INVALID = -2 + }; + } + } +} + + +#endif // CASICDEVPHASE_H diff --git a/DevPhaseLib.pro b/DevPhaseLib.pro new file mode 100644 index 0000000..172ed6a --- /dev/null +++ b/DevPhaseLib.pro @@ -0,0 +1,32 @@ +QT -= gui + +TEMPLATE = lib +CONFIG += dynamiclib + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += CasicDevPhase.cpp +SOURCES += PhaseProtocolBM.cpp +SOURCES += ByteUtil.cpp + +HEADERS += CasicDevPhase.h +HEADERS += PhaseProtocolBM.h +HEADERS += PhaseDataDto.h +HEADERS += ByteUtil.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target diff --git a/PhaseDataDto.h b/PhaseDataDto.h new file mode 100644 index 0000000..e43ae95 --- /dev/null +++ b/PhaseDataDto.h @@ -0,0 +1,27 @@ +#ifndef PHASEDATADTO_H +#define PHASEDATADTO_H + +#include +#include +#include + +class PhaseDataDto +{ +public: + PhaseDataDto() {} + + QString frameId; // 帧id + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QByteArray rawFrame; // 原始帧字节数组 + + QString devCode; + QString devStatus; + QList channelActive; + QList rawPhaseDiffData; // 原始相差数据 + QList channelBeforeDelay; // 补偿前的时差数据 + QList channelData; // 补偿后的时差数据 + QList channelDataStr; // 补偿后的时差数据格式化显示字符串 +}; + +#endif // PHASEDATADTO_H diff --git a/PhaseProtocolBM.cpp b/PhaseProtocolBM.cpp new file mode 100644 index 0000000..4a76b01 --- /dev/null +++ b/PhaseProtocolBM.cpp @@ -0,0 +1,89 @@ +#include "PhaseProtocolBM.h" +#include + +PhaseProtocolBM::PhaseProtocolBM() +{ + +} + +PhaseProtocolBM::~PhaseProtocolBM() +{ + +} + +bool PhaseProtocolBM::parseMessureData(QByteArray rawData, PhaseDataDto * dataObj) +{ + // 获取帧头——帧计数 + QByteArray head = rawData.left(PHASE_FRAME_ID_LENGTH); + dataObj->frameId = ByteUtil::binToHexString(head); + + int j = 0; // 用于转换通道顺序 + + // 获取每个通道的测量数据 + for (int i = 1; i <= PHASE_MESSURE_CHANNEL; i++) + { + if (i <= 8) + { + j = 2 * i - 1; + + } else + { + j = 2 * (i - 8); + } + + QByteArray channelRaw = rawData.left(PHASE_MESSURE_SIZE * j + PHASE_FRAME_ID_LENGTH).right(PHASE_MESSURE_SIZE); + qulonglong channelRawData = ByteUtil::binToULong(channelRaw, 8); + + if (channelRawData == CALCULATE_OFFSET) + { + dataObj->channelActive.append("0"); + dataObj->rawPhaseDiffData.append(0); + dataObj->channelBeforeDelay.append(0.00); + dataObj->channelData.append(0.00); + dataObj->channelDataStr.append("0.00"); + } else + { + double phase = 0.0; + if (channelRawData > CALCULATE_OFFSET) + { + phase = (channelRawData - CALCULATE_OFFSET) * CALCULATE_FACTOR; + } else + { + phase = (CALCULATE_OFFSET - channelRawData) * CALCULATE_FACTOR; + } + dataObj->channelActive.append("1"); + dataObj->rawPhaseDiffData.append(channelRawData - CALCULATE_OFFSET); + dataObj->channelBeforeDelay.append(phase); + dataObj->channelData.append(phase); // 暂时不加补偿值 + dataObj->channelDataStr.append(QString::number(phase, 'f', 15)); + } + } + + return true; +} + +bool PhaseProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧长度小于最小的长度 + if (rawData.length() != PHASE_FRAM_LENGTH) + { + return false; + } + + // 帧尾不是0xEEEEEEEE + if (rawData.mid(rawData.length() - PHASE_FRAME_TAIL.size()) != PHASE_FRAME_TAIL) + { + return false; + } + + return true; +} + +QString PhaseProtocolBM::startMessure() +{ + return "$START*"; +} +QString PhaseProtocolBM::stopMessure() +{ + return "$$STOP*"; +} diff --git a/ByteUtil.cpp b/ByteUtil.cpp new file mode 100644 index 0000000..cad0d82 --- /dev/null +++ b/ByteUtil.cpp @@ -0,0 +1,50 @@ +#include "ByteUtil.h" + +QString ByteUtil::binToHexString(QByteArray bytes) +{ + return bytes.toHex().toUpper(); +} + +QByteArray ByteUtil::hexStringToBytes(QString hexString) +{ + hexString = hexString.toUpper(); + if (hexString.length() % 2 == 1) + { + hexString = "0" + hexString; + } + + bool ok; + QByteArray bytes; + for (int i = 0; i < hexString.length() - 1; i = i + 2) + { + QString str = hexString.mid(i, 2); + bytes.append(str.toInt(&ok, 16)); + } + + return bytes; +} + +qulonglong ByteUtil::binToULong(QByteArray bytes, quint8 length) +{ + qulonglong value = 0; + + for (int i = 0; i < bytes.length() && i < length; i++) + { + value = value * 256 + (quint8) bytes.at(i); + } + + return value; +} + +QByteArray ByteUtil::ULongToBytes(qulonglong value, qint8 length) +{ + QByteArray ba; + + for (int i = 0; i < length; i++) + { + ba.prepend(value % 256); + value = value / 256; + } + + return ba; +} diff --git a/ByteUtil.h b/ByteUtil.h new file mode 100644 index 0000000..9b441ee --- /dev/null +++ b/ByteUtil.h @@ -0,0 +1,38 @@ +#ifndef BYTEUTIL_H +#define BYTEUTIL_H + +#include +#include + +class ByteUtil +{ +public: + /******** 字节数组与字符串互转 ********/ + /** + * @brief binToHexString + * @param bytes + * @note 16进制字节数组转字符串,用于输出显示,不含空格 + * @return + */ + static QString binToHexString(QByteArray bytes); + /** + * @brief hexStringToBytes + * @param hexString + * @note 16进制字符串转字节数组,不含空格 + * @return + */ + static QByteArray hexStringToBytes(QString hexString); + + /******** 字节数组与long互转 ********/ + /** + * @brief binToULong + * @param bytes + * @note 16进制字节数组转无符号long,length个字节。字符串顺序,高位在前,低位在后 + * 如0x0080000000086A43 = 36028797019515459 + * @return + */ + static qulonglong binToULong(QByteArray bytes, quint8 length); + static QByteArray ULongToBytes(qulonglong value, qint8 length); +}; + +#endif // BYTEUTIL_H diff --git a/CasicDevPhase.cpp b/CasicDevPhase.cpp new file mode 100644 index 0000000..2fa3a4e --- /dev/null +++ b/CasicDevPhase.cpp @@ -0,0 +1,122 @@ +#include "CasicDevPhase.h" + +casic::birmm::tflab::CasicDevPhase::CasicDevPhase() +{ + QVector zero(6, 0.0); + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + channelDelay.append(0.0); // 初始化各个通道的时延值 + + lastSigmaVector.append(0.0); // 初始化计算稳定度时需要的上一个平方和值 + + phaseVector.append(zero); + } + + frameId = 0; // 帧编号初始化为0 + frameCount = 0; // 帧计数初始化为0 +} + +int casic::birmm::tflab::CasicDevPhase::frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra) +{ + int retCode = RETURN_STATUS::FAIL; + + if (PhaseProtocolBM::checkFrame(rawBytes) == false) + { + // 数据帧尾和长度不对则返回解析失败 + return retCode; + } + + PhaseDataDto * phaseData = new PhaseDataDto(); + bool parse = PhaseProtocolBM::parseMessureData(rawBytes, phaseData); + + // 解析成功 + if (parse == true) + { + frameCount++; + + // 返回帧计数 + frameId = phaseData->frameId.toULongLong(0, 16); + *frameSN = &frameId; + + // 返回补偿后的测量结果 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + double value = phaseData->channelBeforeDelay.at(i) + channelDelay.at(i); + channelValue->append(value); + } + + if (frameCount <= 5) + { + // 总计小于5帧时无法计算稳定度 + retCode = RETURN_STATUS::INVALID; + + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][frameCount - 1] = phaseData->channelBeforeDelay.at(i); + } + } else + { + // 开始计算稳定度 + for (int i = 0; i < PHASE_MESSURE_CHANNEL; i++) + { + phaseVector[i][5] = phaseData->channelBeforeDelay.at(i); // 最新的一帧数据 + + double allen = calcAllen(i, frameCount); + channelExtra->append(allen); + + // 保留最新的五组数据 + phaseVector[i][0] = phaseVector[i][1]; + phaseVector[i][1] = phaseVector[i][2]; + phaseVector[i][2] = phaseVector[i][3]; + phaseVector[i][3] = phaseVector[i][4]; + phaseVector[i][4] = phaseVector[i][5]; + } + + retCode = RETURN_STATUS::SUCCESS; + } + } + + delete phaseData; + return retCode; +} + +int casic::birmm::tflab::CasicDevPhase::setChannelDelay(QList channelDelay) +{ + this->channelDelay = channelDelay; + + return RETURN_STATUS::SUCCESS; +} +QList casic::birmm::tflab::CasicDevPhase::getChannelDelay() +{ + return this->channelDelay; +} + +double casic::birmm::tflab::CasicDevPhase::calcAllen(int index, int aN) +{ + int i = 0; + int d = 1; //此处只计算秒稳 + double tau0 = 1; //tau0是基本采样间隔,由计数器或比相仪的最小采样间隔决定,最小为1s + + double allan = 0.0; + double *y = new double[4]; + double tau_2 = pow(d * tau0, 2); //pow是计算x的y次幂 + double sum = lastSigmaVector.at(index); + + for (int j = 4; j > 0; j--) + { + i = 6 - 2*d - j; + double x2 = phaseVector[index][i+2*d]; + double x1 = phaseVector[index][i+d]; + double x = phaseVector[index][i]; + y[4 - j] = pow(x2 - 2 * x1 + x, 2); + + sum = sum + y[4 - j]; + } + + lastSigmaVector[index] += y[0]; + + allan = sqrt(sum/(2*tau_2*(aN-2*d))); //delta + + delete[] y; + return allan; +} diff --git a/CasicDevPhase.h b/CasicDevPhase.h new file mode 100644 index 0000000..05751fb --- /dev/null +++ b/CasicDevPhase.h @@ -0,0 +1,89 @@ +#ifndef CASICDEVPHASE_H +#define CASICDEVPHASE_H + +#include +#include +#include +#include "PhaseProtocolBM.h" +#include "PhaseDataDto.h" + +namespace casic { + namespace birmm { + namespace tflab { + class CasicDevPhase + { + public: + CasicDevPhase(); + + /** + * @brief frameParse 解析协议字节数组并计算稳定度 + * @param rawBytes 入参 从设备取到的原始二进制字节 + * @param frameSN 出参 帧计数 + * @param channelValue 出参 各通道补偿后的时差数据 + * @param channelExtra 出参 各通道的扩展输出数据 目前仅包括1秒稳定度 + * @return int 返回是否成功 0=成功 -1=帧解析失败 -2=稳定度结果无效 + */ + int frameParse(QByteArray rawBytes, qulonglong** frameSN, QList* channelValue, QList* channelExtra); + + /** + * @brief setChannelDelay 设置各通道时延补偿绝对值 + * @param channelDelay 入参 各通道的时延补偿绝对值 + * @return int 返回是否设置成功 0=成功 -1=失败 + */ + int setChannelDelay(QList channelDelay); + + /** + * @brief getChannelDelay 获取各通道时延补偿绝对值 + * @return QList 当前使用的各通道时延补偿值 + */ + QList getChannelDelay(); + + private: + /** + * @brief channelDelay 各通道的时延补偿值 + */ + QList channelDelay; + + /** + * @brief frameId 需要返回的帧编号 + */ + qulonglong frameId; + + /** + * @brief frameCount 总共的帧计数 + */ + qulonglong frameCount; + + /** + * @brief phaseVector 各个通道的时差数据 只保留最近的五组数据 + * 用于计算稳定度 + */ + QVector> phaseVector; + + /** + * @brief lastSigmaVector 计算Allen方差时的上一个平方和 + */ + QList lastSigmaVector; + + /** + * @brief allan 计算指定数组的阿伦方差值 + * @param channelData 指定数组 + * @param d 采样间隔 默认值=1 + * @param aN 数组长度 + * @param lastSigma 上一个平方和 需要取到并保存以用于下次计算 + * @return 返回值 开方后的值 + */ + double calcAllen(int index, int aN); + }; + + enum RETURN_STATUS { + SUCCESS = 0, + FAIL = -1, + INVALID = -2 + }; + } + } +} + + +#endif // CASICDEVPHASE_H diff --git a/DevPhaseLib.pro b/DevPhaseLib.pro new file mode 100644 index 0000000..172ed6a --- /dev/null +++ b/DevPhaseLib.pro @@ -0,0 +1,32 @@ +QT -= gui + +TEMPLATE = lib +CONFIG += dynamiclib + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += CasicDevPhase.cpp +SOURCES += PhaseProtocolBM.cpp +SOURCES += ByteUtil.cpp + +HEADERS += CasicDevPhase.h +HEADERS += PhaseProtocolBM.h +HEADERS += PhaseDataDto.h +HEADERS += ByteUtil.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target diff --git a/PhaseDataDto.h b/PhaseDataDto.h new file mode 100644 index 0000000..e43ae95 --- /dev/null +++ b/PhaseDataDto.h @@ -0,0 +1,27 @@ +#ifndef PHASEDATADTO_H +#define PHASEDATADTO_H + +#include +#include +#include + +class PhaseDataDto +{ +public: + PhaseDataDto() {} + + QString frameId; // 帧id + QString timestamp; // 时间戳字符串 + qlonglong milisecond; // 毫秒计数 + QByteArray rawFrame; // 原始帧字节数组 + + QString devCode; + QString devStatus; + QList channelActive; + QList rawPhaseDiffData; // 原始相差数据 + QList channelBeforeDelay; // 补偿前的时差数据 + QList channelData; // 补偿后的时差数据 + QList channelDataStr; // 补偿后的时差数据格式化显示字符串 +}; + +#endif // PHASEDATADTO_H diff --git a/PhaseProtocolBM.cpp b/PhaseProtocolBM.cpp new file mode 100644 index 0000000..4a76b01 --- /dev/null +++ b/PhaseProtocolBM.cpp @@ -0,0 +1,89 @@ +#include "PhaseProtocolBM.h" +#include + +PhaseProtocolBM::PhaseProtocolBM() +{ + +} + +PhaseProtocolBM::~PhaseProtocolBM() +{ + +} + +bool PhaseProtocolBM::parseMessureData(QByteArray rawData, PhaseDataDto * dataObj) +{ + // 获取帧头——帧计数 + QByteArray head = rawData.left(PHASE_FRAME_ID_LENGTH); + dataObj->frameId = ByteUtil::binToHexString(head); + + int j = 0; // 用于转换通道顺序 + + // 获取每个通道的测量数据 + for (int i = 1; i <= PHASE_MESSURE_CHANNEL; i++) + { + if (i <= 8) + { + j = 2 * i - 1; + + } else + { + j = 2 * (i - 8); + } + + QByteArray channelRaw = rawData.left(PHASE_MESSURE_SIZE * j + PHASE_FRAME_ID_LENGTH).right(PHASE_MESSURE_SIZE); + qulonglong channelRawData = ByteUtil::binToULong(channelRaw, 8); + + if (channelRawData == CALCULATE_OFFSET) + { + dataObj->channelActive.append("0"); + dataObj->rawPhaseDiffData.append(0); + dataObj->channelBeforeDelay.append(0.00); + dataObj->channelData.append(0.00); + dataObj->channelDataStr.append("0.00"); + } else + { + double phase = 0.0; + if (channelRawData > CALCULATE_OFFSET) + { + phase = (channelRawData - CALCULATE_OFFSET) * CALCULATE_FACTOR; + } else + { + phase = (CALCULATE_OFFSET - channelRawData) * CALCULATE_FACTOR; + } + dataObj->channelActive.append("1"); + dataObj->rawPhaseDiffData.append(channelRawData - CALCULATE_OFFSET); + dataObj->channelBeforeDelay.append(phase); + dataObj->channelData.append(phase); // 暂时不加补偿值 + dataObj->channelDataStr.append(QString::number(phase, 'f', 15)); + } + } + + return true; +} + +bool PhaseProtocolBM::checkFrame(QByteArray rawData) +{ + // 帧长度小于最小的长度 + if (rawData.length() != PHASE_FRAM_LENGTH) + { + return false; + } + + // 帧尾不是0xEEEEEEEE + if (rawData.mid(rawData.length() - PHASE_FRAME_TAIL.size()) != PHASE_FRAME_TAIL) + { + return false; + } + + return true; +} + +QString PhaseProtocolBM::startMessure() +{ + return "$START*"; +} +QString PhaseProtocolBM::stopMessure() +{ + return "$$STOP*"; +} diff --git a/PhaseProtocolBM.h b/PhaseProtocolBM.h new file mode 100644 index 0000000..766116a --- /dev/null +++ b/PhaseProtocolBM.h @@ -0,0 +1,33 @@ +#ifndef PHASEPROTOCOLBM_H +#define PHASEPROTOCOLBM_H + +#include "PhaseDataDto.h" +#include "ByteUtil.h" + +static const QByteArray PHASE_FRAME_TAIL("\xEE\xEE\xEE\xEE", 4); // 帧尾 + +static const int PHASE_FRAME_ID_LENGTH = 4; // 帧头id计数器为4个字节 +static const int PHASE_MESSURE_CHANNEL = 16; +static const int PHASE_MESSURE_SIZE = 8; +static const int PHASE_FRAM_LENGTH = 4 + 4 + 16 * 8; + +static const qulonglong CALCULATE_OFFSET = 0X0080000000000000; +static const double CALCULATE_FACTOR = 1.6810E-15; + +class PhaseProtocolBM +{ +public: + PhaseProtocolBM(); + ~PhaseProtocolBM(); + + // 解析比相仪测量数据 + static bool parseMessureData(QByteArray rawData, PhaseDataDto * phaseData); + + // 检测帧格式,帧头帧尾 + static bool checkFrame(QByteArray rawData); + + static QString startMessure(); + static QString stopMessure(); +}; + +#endif // PHASEROTOCOLBM_H