You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1080 lines
35 KiB

/*********版权所有C2020武汉高德红外股份有限公司***************************************
* Arith_ZHRPY.cpp
*
* <-> --
*
* 2.0
* 11531yj
* 2023.10.26
*****************************************************************************************/
#include "Arith_zhryp.h"
#include <iostream>
#include <assert.h>
#include <fstream>
#include <math.h>
using namespace std;
using namespace sRPYCacl;
/**********************************************************
*
**********************************************************/
Angle3D g_SlantingAngleBias = { 0 }; //光电伺服与光电基准坐标系的安装旋角误差//
BiasXYZ g_PositionXYZBias = { 0 }; //光电基准与平台直角坐标系位置偏差//
/**********************************************************
*
**********************************************************/
void sRPYCacl::setBiasPara(Angle3D eoServoToEoBias, BiasXYZ eoToZTPosBias)
{
g_SlantingAngleBias.dHAngle = eoServoToEoBias.dHAngle; //光电伺服与光电基准坐标系的航向角误差//
g_SlantingAngleBias.dVAngle = eoServoToEoBias.dVAngle; //光电伺服与光电基准坐标系的俯仰角误差//
g_SlantingAngleBias.dSAngle = eoServoToEoBias.dSAngle; //光电伺服与光电基准坐标系的横滚角误差//
g_PositionXYZBias.deltaX = eoToZTPosBias.deltaX; //光电基准与平台直角坐标系X坐标的偏差
g_PositionXYZBias.deltaY = eoToZTPosBias.deltaY; //光电基准与平台直角坐标系Y坐标的偏差
g_PositionXYZBias.deltaZ = eoToZTPosBias.deltaZ; //光电基准与平台直角坐标系Z坐标的偏差
}
/*********************************************************************************************
*
*
*
* targetServoPole:
* stEulerRPY: 姿
* selfPointBLH:
* targetBLH
* AngleError3D: 姿
* NUEPole:
* Sum_Error_Min
* AngleError3D
*
*********************************************************************************************/
Pole sRPYCacl::getNUEPoleFromEOServoPole(Pole targetServoPole, EulerRPY stEulerRPY)
{
//伺服方位角限制在0-360
if (targetServoPole.Azimuth > 360)
{
targetServoPole.Azimuth -= AzimuthMax;
}
//限制伺服俯仰角度// (80、-5、360改成宏(已改20231115)) alpha改成方位俯仰对应的Amizith
targetServoPole.Pitch = MIN(targetServoPole.Pitch, PitchMax);
targetServoPole.Pitch = MAX(targetServoPole.Pitch, PitchMin);
//1.光电吊舱伺服极坐标 转 光电伺服直角坐标
PointXYZ targetServoXYZ = getXYZFromPole(targetServoPole);
//2.光电伺服直角坐标 转 光电基准直角坐标
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromEOServoXYZ(targetServoXYZ, g_SlantingAngleBias);
//3.光电基准直角坐标 转 载体惯导直角坐标
PointXYZ targetZTXYZ = getZTXYZFromEOBaseXYZ(targetEOBaseXYZ, g_PositionXYZBias);
//4.载体惯导直角坐标 转 地理直角坐标
PointXYZ targetNUEXYZ = getNUEXYZFromZTXYZ(targetZTXYZ, stEulerRPY);
//5.地理直角坐标 转 地理极坐标
Pole targetNUEPole = getPoleFromXYZ(targetNUEXYZ);
//上报目标北天东地理极坐标
return targetNUEPole;
}
/*********************************************************************************************
*
* targetServoXYZ
* dSAngle
* dHAngle
* dVAngle
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getEOBaseXYZFromEOServoXYZ(PointXYZ targetServoXYZ, Angle3D eoServoToEoBias)
{
//先绕x轴横滚旋转 -dSAngle再绕z轴俯仰旋转 -dVAngle再绕y轴方位旋转-dHAngle
DOUBLE64 oppRx[9];
DOUBLE64 oppRy[9];
DOUBLE64 oppRz[9];
DOUBLE64 oppRyzx[9];
//计算旋转矩阵
Rx(-eoServoToEoBias.dSAngle, oppRx);
Rz(-eoServoToEoBias.dVAngle, oppRz);
Ry(-eoServoToEoBias.dHAngle, oppRy);
MultiMat333(oppRy, oppRz, oppRx, oppRyzx);
//坐标转换
return RtPoint(oppRyzx, targetServoXYZ);
}
/*********************************************************************************************
*
* targetEOBaseXYZ
* deltaX X
* deltaY Y
* deltaZ Z
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getZTXYZFromEOBaseXYZ(PointXYZ targetEOBaseXYZ, BiasXYZ eoToZTPosBias)
{
//平台坐标系下目标坐标
PointXYZ targetZTXYZ;
targetZTXYZ.X = targetEOBaseXYZ.X + eoToZTPosBias.deltaX;
targetZTXYZ.Y = targetEOBaseXYZ.Y + eoToZTPosBias.deltaY;
targetZTXYZ.Z = targetEOBaseXYZ.Z + eoToZTPosBias.deltaZ;
return targetZTXYZ;
}
/*********************************************************************************************
*
* targetZTXYZ
* stEulerRPY 姿
* selfPointBLH
* targetBLH
* double *Sum_Error_Min /
Angle3D *AngleError3D /°
Pole *NUEPole
*
*********************************************************************************************/
PointBLH sRPYCacl::getPosFromZTXYZ(PointXYZ targetZTXYZ, EulerRPY stEulerRPY, PointBLH selfPointBLH, PointBLH targetBLH, double* Sum_Error_Min, Angle3D* AngleError3D)
{
DOUBLE64 oppRx[9];
DOUBLE64 oppRy[9];
DOUBLE64 oppRz[9];
DOUBLE64 oppRyzx[9];
PointBLH pointBLH = { 0 };
PointBLH pointMinBLH = { 0 };
EulerRPY stEulerRPYAddError;
// double Sum_Error_Min_Yaw, Sum_Error_Min_Pitch, Sum_Error_Min_Roll; //定位精度最小时偏航角/俯仰角/横滚角
double i, j, k; //横滚角度i / 偏航角度j / 俯仰角度k偏差//
// double Error_Yaw = 0; //方位角偏差//
// double Error_Pitch = 0; //俯仰角偏差//
// double Error_Roll = 0; //横滚角偏差//
double Error_L = 0; //经、纬误差转化成米//
double Error_B = 0;
double Error_H = 0;
double Sum_Error;
for (i = -0.5; i <= 0.5; i = i + 0.05) { //横滚//
for (j = -8; j <= 8; j = j + 0.05) { //方位//
for (k = -1; k <= 1; k = k + 0.05) { //俯仰//
// Error_Yaw = j * PI / 180;
// Error_Roll = i * PI / 180;
// Error_Pitch = k * PI / 180;
//给量测载机姿态角添加误差//
//载机姿态角参与计算 20240229
stEulerRPYAddError.Roll = stEulerRPY.Roll + i;
stEulerRPYAddError.Pitch = stEulerRPY.Pitch + k;
stEulerRPYAddError.Yaw = stEulerRPY.Yaw + j;
//计算旋转矩阵//
Rx(-stEulerRPYAddError.Roll, oppRx);
Rz(-stEulerRPYAddError.Pitch, oppRz);
Ry(-stEulerRPYAddError.Yaw, oppRy);
MultiMat333(oppRy, oppRz, oppRx, oppRyzx);
PointXYZ targetNUEXYZ = RtPoint(oppRyzx, targetZTXYZ);
//地理直角坐标 转 地理极坐标 //
Pole targetNUEPole = getPoleFromXYZ(targetNUEXYZ);
//2、由目标的北天东极坐标转到经、纬、高。
stTrgOutput Target1;
stTrgOutput* Target4 = &Target1;
pointBLH = getPosFromNUEPole(targetNUEPole, selfPointBLH);
//0131zqq: 计算经纬误差
Error_L = fabs(pointBLH.L - targetBLH.L) * 111000;
Error_B = fabs(pointBLH.B - targetBLH.B) * 111000;
Error_H = fabs(pointBLH.H - targetBLH.H);
Sum_Error = sqrt(Error_L * Error_L + Error_B * Error_B + Error_H * Error_H);
if (Sum_Error < *Sum_Error_Min)
{
// Sum_Error_Min_Yaw = Error_Yaw * 57.3;
// Sum_Error_Min_Pitch = Error_Pitch * 57.3;
// Sum_Error_Min_Roll = Error_Roll * 57.3;
*Sum_Error_Min = Sum_Error;
if (*Sum_Error_Min < 100) {
pointMinBLH = pointBLH; //返回误差最小的经纬高//
AngleError3D->dHAngle = j; //方位误差//
AngleError3D->dVAngle = k; //俯仰误差//
AngleError3D->dSAngle = i; //横滚误差//
}
}
}
}
}
return pointMinBLH;
}
/*********************************************************************************************
*
* targetZTXYZ
* stEulerRPY 姿
*
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getNUEXYZFromZTXYZ(PointXYZ targetZTXYZ, EulerRPY stEulerRPY)
{
DOUBLE64 oppRx[9];
DOUBLE64 oppRy[9];
DOUBLE64 oppRz[9];
DOUBLE64 oppRyzx[9];
//计算旋转矩阵//
Rx(-stEulerRPY.Roll, oppRx);
Rz(-stEulerRPY.Pitch, oppRz);
Ry(-stEulerRPY.Yaw, oppRy);
MultiMat333(oppRy, oppRz, oppRx, oppRyzx);
return RtPoint(oppRyzx, targetZTXYZ);
}
/*********************************************************************************************
*
*
* targetNUEPole
* selfPointBLH:
*
* BLH
*********************************************************************************************/
PointBLH sRPYCacl::getPosFromNUEPole(Pole targetNUEPole, PointBLH selfPointBLH)
{
//载机自身的经纬高转地心空间直角坐标系//
PointXYZ selfPointXYZ = getXYZFromBLH(selfPointBLH);
//目标的地理极坐标转地理直角坐标//
PointXYZ targetPointXYZ = getZTFromPole(targetNUEPole);
//目标的地心空间直角坐标//
PointXYZ targetCGCSPointXYZ = getCGCSFromNUE(targetPointXYZ, selfPointXYZ);
//目标的地心空间直角坐标转地心大地坐标
return getBLHFromXYZ(targetCGCSPointXYZ);
}
/*********************************************************************************************
* BLH
* pointBLH
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getXYZFromBLH(PointBLH pointBLH)
{
PointXYZ pointXYZ;
DOUBLE64 W, N;
W = sqrt(1 - ee * pow(sin(RADIAN(pointBLH.B)), 2));
N = a / W; // 椭球的卯酉圈曲率//
//将B、L、H变换到地心空间直角坐标
pointXYZ.X = (N + pointBLH.H) * cos(RADIAN(pointBLH.B)) * cos(RADIAN(pointBLH.L));
pointXYZ.Y = (N + pointBLH.H) * cos(RADIAN(pointBLH.B)) * sin(RADIAN(pointBLH.L));
pointXYZ.Z = (N * (1 - ee) + pointBLH.H) * sin(RADIAN(pointBLH.B));
return pointXYZ;
}
/*********************************************************************************************
*
* targetPole
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getZTFromPole(Pole targetPole)
{
PointXYZ result;
DOUBLE64 aa, bb, cc;
cc = sin(RADIAN(targetPole.Pitch)) * targetPole.distance;
aa = sin(RADIAN(targetPole.Azimuth)) * sqrt(fabs(targetPole.distance * targetPole.distance - cc * cc));
bb = sqrt(fabs(targetPole.distance * targetPole.distance - aa * aa - cc * cc));
if (targetPole.Azimuth > 90 && targetPole.Azimuth < 270)
{
bb = -bb;
}
//此处的X、Y、Z为目标的北天东地理直角坐标 20231125yj
result.X = bb;
result.Y = cc;
result.Z = aa;
return result;
}
/*********************************************************************************************
*
*
* targetPointXYZ
* selfPointXYZ
*
*
*********************************************************************************************/
PointXYZ sRPYCacl::getCGCSFromNUE(PointXYZ targetPointXYZ, PointXYZ selfPointXYZ)
{
DOUBLE64 dx, dy, dz, sinL, cosL, sinB, cosB;
PointXYZ result;
//载机自身的X、Y、Z转载机自身的经纬高
PointBLH selfPointBLH = getBLHFromXYZ(selfPointXYZ);
//目标的北天东地理直角坐标//
dx = targetPointXYZ.X;
dy = targetPointXYZ.Y;
dz = targetPointXYZ.Z;
sinL = sin(RADIAN(selfPointBLH.L));
cosL = cos(RADIAN(selfPointBLH.L));
sinB = sin(RADIAN(selfPointBLH.B));
cosB = cos(RADIAN(selfPointBLH.B));
//目标的地心直角坐标=目标相对于载机的地心坐标+载机的地心直角坐标//
result.X = -sinB * cosL * dx + cosB * cosL * dy - sinL * dz + selfPointXYZ.X; //修改了dxdydz矩阵系数 20231125yj
result.Y = -sinB * sinL * dx + cosB * sinL * dy + cosL * dz + selfPointXYZ.Y;
result.Z = cosB * dx + sinB * dy + selfPointXYZ.Z;
return result;
}
/*********************************************************************************************
* :
* PointXYZ
*
* BLH
* XYZBLHL. yj2023.11.9
* arctan180. yj2023.11.9
**********************************************************************************************/
PointBLH sRPYCacl::getBLHFromXYZ(PointXYZ pointXYZ)
{
DOUBLE64 U, B0, N, L, H, B;
U = atan(pointXYZ.Z * a / (sqrt(pointXYZ.X * pointXYZ.X + pointXYZ.Y * pointXYZ.Y) * b));
B0 = atan((pointXYZ.Z + b * epep * pow(sin(U), 3)) / (sqrt(pointXYZ.X * pointXYZ.X + pointXYZ.Y * pointXYZ.Y) - a * ee * pow(cos(U), 3)));
N = a / sqrt(1 - ee * pow(sin(B0), 2));
L = atan(pointXYZ.Y / pointXYZ.X);
//在XYZ转到BLH过程中atan的取值有多个解对L取值分情况考虑
if (pointXYZ.X < 0 && L < 0)
{
L = L + PI;
}
else if (pointXYZ.X < 0 && L > 0)
{
L = L - PI;
}
else if (pointXYZ.X > 0)
{
L = L;
}
H = sqrt(pointXYZ.X * pointXYZ.X + pointXYZ.Y * pointXYZ.Y + pow(pointXYZ.Z + N * ee * sin(B0), 2)) - N;
B = atan(pointXYZ.Z / sqrt(pointXYZ.X * pointXYZ.X + pointXYZ.Y * pointXYZ.Y) / (1 - ee * N / (N + H)));
PointBLH pointBLH;
pointBLH.B = ANGLE(B);
pointBLH.L = ANGLE(L);
pointBLH.H = H;
return pointBLH;
}
/*********************************************************************************************
* ----
* ptselfBLH
* ptTargetBLH:
*
* 20240228
*********************************************************************************************/
Pole sRPYCacl::getNUEPoleFromENUXYZ(PointBLH ptselfBLH, PointBLH ptTargetBLH)
{
PointXYZ ptSelfXYZ = getXYZFromBLH(ptselfBLH);
PointXYZ ptTargetXYZ = getXYZFromBLH(ptTargetBLH);
Pole poleTarget = getPoleFromCGCS(ptTargetXYZ, ptSelfXYZ);
return poleTarget;
}
Pole sRPYCacl::getPoleFromCGCS(PointXYZ ptTargetXYZ, PointXYZ ptSelfXYZ)
{
PointXYZ pointENUXYZ = getENUFromCGCS(ptTargetXYZ, ptSelfXYZ);
Pole targetPole = getPoleFromZT(pointENUXYZ);
if (targetPole.Pitch > 90)
{
targetPole.Pitch = 180 - targetPole.Pitch;
targetPole.Azimuth += 180;
}
if (targetPole.Pitch < -90)
{
targetPole.Pitch = -180 - targetPole.Pitch;
targetPole.Azimuth += 180;
}
if (targetPole.Azimuth > 360)
{
targetPole.Azimuth -= 360;
}
if (targetPole.Azimuth < 0)
{
targetPole.Azimuth += 360;
}
return targetPole;
}
PointXYZ sRPYCacl::getENUFromCGCS(PointXYZ ptTargetXYZ, PointXYZ ptSelfXYZ)
{
PointBLH selfPointBLH = getBLHFromXYZ(ptSelfXYZ);
double dx = ptTargetXYZ.X - ptSelfXYZ.X;
double dy = ptTargetXYZ.Y - ptSelfXYZ.Y;
double dz = ptTargetXYZ.Z - ptSelfXYZ.Z;
double sinL = sin(RADIAN(selfPointBLH.L));
double cosL = cos(RADIAN(selfPointBLH.L));
double sinB = sin(RADIAN(selfPointBLH.B));
double cosB = cos(RADIAN(selfPointBLH.B));
PointXYZ result;
result.X = -sinL * dx + cosL * dy;
result.Y = -sinB * cosL * dx - sinB * sinL * dy + cosB * dz;
result.Z = cosB * cosL * dx + cosB * sinL * dy + sinB * dz;
return result;
}
Pole sRPYCacl::getPoleFromZT(PointXYZ targetPointXYZ)
{
double x = targetPointXYZ.X;
double y = targetPointXYZ.Y;
double z = targetPointXYZ.Z;
Pole result;
result.distance = sqrt(x * x + y * y + z * z);
result.Pitch = ANGLE(asin(z / result.distance));
result.Azimuth = ABS(ANGLE(asin(x / sqrt(x * x + y * y))));
if (y < 0 && x > 0) //90-180
{
result.Azimuth = 180 - result.Azimuth;
}
else if (x < 0 && y <= 0) //180-270
{
result.Azimuth = result.Azimuth + 180;
}
else if (x <= 0 && y >= 0) //270-360
{
result.Azimuth = 360 - result.Azimuth;
}
return result;
}
/*********************************************************************************************
*
*
* targetNUEPole
* stEulerRPY: 姿
*
*
*********************************************************************************************/
Pole sRPYCacl::getEOServoPoleFromNUEPole(Pole targetNUEPole, EulerRPY stEulerRPY)
{
//1.地理坐标系下的极坐标 转 地理坐标系下的直角坐标
PointXYZ targetNUEXYZ = getXYZFromPole(targetNUEPole);
//2.地理坐标系下的直角坐标转换为载体惯导坐标系下的直角坐标
PointXYZ targetZTXYZ = getZTXYZFromNUEXYZ(targetNUEXYZ, stEulerRPY);
//3.载体惯导坐标系下的直角坐标 转 光电基准系下的直角坐标
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromZTXYZ(targetZTXYZ, g_PositionXYZBias);
//4.光电基准系直角 转 光电伺服坐标系下直角坐标
PointXYZ targetEOServoXYZ = getEOServoXYZFromEOBaseXYZ(targetEOBaseXYZ, g_SlantingAngleBias);
//5.光电伺服坐标系下直角坐标 转 光电伺服坐标系下极坐标
Pole targetEOServoPole = getPoleFromXYZ(targetEOServoXYZ);
return targetEOServoPole;
}
/*********************************************************************************************
*
* targetPointXYZ
* Roll
* Yaw
* Pitch
*
*
**********************************************************************************************/
PointXYZ sRPYCacl::getZTXYZFromNUEXYZ(PointXYZ targetPointXYZ, EulerRPY stEulerRPY)
{
//先绕y轴方位旋转Yaw -> 再绕z轴俯仰旋转 Pitch -> 绕x轴横滚旋转 Roll
DOUBLE64 oppRx[9];
DOUBLE64 oppRy[9];
DOUBLE64 oppRz[9];
DOUBLE64 oppRxzy[9];
//计算旋转矩阵
Ry(stEulerRPY.Yaw, oppRy);
Rz(stEulerRPY.Pitch, oppRz);
Rx(stEulerRPY.Roll, oppRx);
MultiMat333(oppRx, oppRz, oppRy, oppRxzy);
//坐标转换
return RtPoint(oppRxzy, targetPointXYZ);
}
/*********************************************************************************************
*
* targetZTXYZ
* deltaX X
* deltaY Y
* deltaZ: Z
*
*
**********************************************************************************************/
PointXYZ sRPYCacl::getEOBaseXYZFromZTXYZ(PointXYZ targetZTXYZ, BiasXYZ ztToEoBaseBias)
{
//平台坐标系下目标坐标
PointXYZ targetEOBaseXYZ;
targetEOBaseXYZ.X = targetZTXYZ.X - ztToEoBaseBias.deltaX;
targetEOBaseXYZ.Y = targetZTXYZ.Y - ztToEoBaseBias.deltaY;
targetEOBaseXYZ.Z = targetZTXYZ.Z - ztToEoBaseBias.deltaZ;
return targetEOBaseXYZ;
}
/*********************************************************************************************
*
* targetEOBaseXYZ
* dHAngle
* dVAngle
* dSAngle:
*
*
**********************************************************************************************/
PointXYZ sRPYCacl::getEOServoXYZFromEOBaseXYZ(PointXYZ targetEOBaseXYZ, Angle3D eoBaseToEOServoBias)
{
//先绕y轴方位旋转dHAngle,再绕z轴俯仰旋转 dVAngle,再绕x轴横滚旋转 dSAngle
DOUBLE64 oppRx[9];
DOUBLE64 oppRy[9];
DOUBLE64 oppRz[9];
DOUBLE64 oppRxzy[9];
//计算旋转矩阵
Rx(eoBaseToEOServoBias.dSAngle, oppRx);
Rz(eoBaseToEOServoBias.dVAngle, oppRz);
Ry(eoBaseToEOServoBias.dHAngle, oppRy);
MultiMat333(oppRx, oppRz, oppRy, oppRxzy);
//坐标转换
return RtPoint(oppRxzy, targetEOBaseXYZ);
}
/*********************************************************************************************
*
* x,y,z
*
* alphabeta
* 1.
* 2.
*
**********************************************************************************************/
Pole sRPYCacl::getPoleFromXYZ(PointXYZ targetXYZ)
{
DOUBLE64 x, y, z;
x = targetXYZ.X;
y = targetXYZ.Y;
z = targetXYZ.Z;
Pole result;
result.distance = sqrt(x * x + y * y + z * z);
result.Pitch = ANGLE(asin(y / result.distance));
result.Azimuth = ABS(ANGLE(atan(z / x)));
//方位角约束0-360
if (x < 0 && z >= 0) // 90 - 180
{
result.Azimuth = 180 - result.Azimuth;
}
else if (x < 0 && z < 0) // 180 - 270
{
result.Azimuth = result.Azimuth + 180;
}
else if (x >= 0 && z < 0) // 270 - 360
{
result.Azimuth = 360 - result.Azimuth;
}
return result;
}
/*********************************************************************************************
*
* alphabeta
*
* x,y,z
* 1.
* 2.
*
**********************************************************************************************/
//0131zqq 伺服由极坐标转为直角坐标//
PointXYZ sRPYCacl::getXYZFromPole(Pole targetPole)
{
PointXYZ result = { 0 };
DOUBLE64 aa, bb, cc, ac;
//激光或雷达测距时的判断(异常判断)
if (targetPole.distance < 100)
{
targetPole.distance = 1000;
}
bb = sin(RADIAN(targetPole.Pitch)) * targetPole.distance;
ac = sqrt(targetPole.distance * targetPole.distance - bb * bb);
aa = cos(RADIAN(targetPole.Azimuth)) * ac;
cc = sin(RADIAN(targetPole.Azimuth)) * ac;
result.X = aa;
result.Y = bb;
result.Z = cc;
return result;
}
// 绕X轴旋转矩阵 横滚角
/* 1 0 0
0 cos sin
0 -sin cos
*///备注对应矩阵M3
void sRPYCacl::Rx(DOUBLE64 omega, DOUBLE64* Opp)
{
DOUBLE64 coso = cos(RADIAN(omega));
DOUBLE64 sino = sin(RADIAN(omega));
Opp[0] = 1;
Opp[1] = 0;
Opp[2] = 0;
Opp[3] = 0;
Opp[4] = coso;
Opp[5] = sino;
Opp[6] = 0;
Opp[7] = -sino;
Opp[8] = coso;
}
// 绕Y轴旋转矩阵 方位角
/* cos 0 sin
0 1 0
-sin 0 cos
*/
void sRPYCacl::Ry(DOUBLE64 omega, DOUBLE64* Opp)
{
DOUBLE64 coso = cos(RADIAN(omega));
DOUBLE64 sino = sin(RADIAN(omega));
Opp[0] = coso;
Opp[1] = 0;
Opp[2] = sino; //S3311中此处为-sino
Opp[3] = 0;
Opp[4] = 1;
Opp[5] = 0;
Opp[6] = -sino; //S3311中此处为sino
Opp[7] = 0;
Opp[8] = coso;
}
// 绕Y轴旋转矩阵 方位角 对应矩阵M1、M4
/* cos 0 -sin
0 1 0
sin 0 cos
*///M1、M4
void sRPYCacl::R_y(DOUBLE64 omega, DOUBLE64* Opp)
{
DOUBLE64 coso = cos(RADIAN(omega));
DOUBLE64 sino = sin(RADIAN(omega));
Opp[0] = coso;
Opp[1] = 0;
Opp[2] = -sino;
Opp[3] = 0;
Opp[4] = 1;
Opp[5] = 0;
Opp[6] = sino;
Opp[7] = 0;
Opp[8] = coso;
}
// 绕Z轴旋转矩阵 俯仰角
/* cos sin 0
-sin cos 0
0 0 1
*///备注对应矩阵M2、M5
void sRPYCacl::Rz(DOUBLE64 omega, DOUBLE64* Opp)
{
DOUBLE64 coso = cos(RADIAN(omega));
DOUBLE64 sino = sin(RADIAN(omega));
Opp[0] = coso;
Opp[1] = sino;
Opp[2] = 0;
Opp[3] = -sino;
Opp[4] = coso;
Opp[5] = 0;
Opp[6] = 0;
Opp[7] = 0;
Opp[8] = 1;
}
/*********************************************************************************************
* A*B
*********************************************************************************************/
void sRPYCacl::MultiMat(DOUBLE64* A, DOUBLE64* B, DOUBLE64* AB, SINT32 m, SINT32 n, SINT32 p)
{
// A为m*n ; B为n*p ;输出AB为m*p
SINT32 i, j, k;
DOUBLE64 Multisum;
for (i = 0; i < m; i++) //输出矩阵的m行
{
for (j = 0; j < p; j++) //输出矩阵的p列
{
Multisum = 0;
for (k = 0; k < n; k++)
Multisum += A[i * n + k] * B[k * p + j];
AB[i * p + j] = Multisum;
}
}
}
/*********************************************************************************************
* 3A*B
*********************************************************************************************/
void sRPYCacl::MultiMat33(DOUBLE64* A, DOUBLE64* B, DOUBLE64* AB)
{
MultiMat(A, B, AB, 3, 3, 3);
}
/*********************************************************************************************
* 3A*B*C
*********************************************************************************************/
void sRPYCacl::MultiMat333(DOUBLE64* A, DOUBLE64* B, DOUBLE64* C, DOUBLE64* ABC)
{
DOUBLE64 BC[9];
MultiMat(B, C, BC, 3, 3, 3);
MultiMat(A, BC, ABC, 3, 3, 3);
}
/*********************************************************************************************
* 3
*********************************************************************************************/
//0131zqq第一个参数有点问题没用到
PointXYZ sRPYCacl::RtPoint(DOUBLE64* M, PointXYZ targetPointXYZ)
{
DOUBLE64 A[3];
DOUBLE64 G[3];
A[0] = targetPointXYZ.X;
A[1] = targetPointXYZ.Y;
A[2] = targetPointXYZ.Z;
MultiMat(M, A, G, 3, 3, 1);
PointXYZ result;
result.X = G[0];
result.Y = G[1];
result.Z = G[2];
return result;
}
/*********************************************************************************************
*
*
*
* targetServoPole:
* stEulerRPY: 姿
* selfPointBLH:
* targetBLH
* AngleError3D: 姿
* NUEPole:
* Sum_Error_Min
* AngleError3D
*
*********************************************************************************************/
Angle3D sRPYCacl::getAngle3DFromEOServoPole(Pole targetServoPole, EulerRPY stEulerRPY, PointBLH selfPointBLH, PointBLH targetBLH, double* Sum_Error_Min, Angle3D* AngleError3D)
{
//伺服方位角限制在0-360
if (targetServoPole.Azimuth > 360)
{
targetServoPole.Azimuth -= AzimuthMax;
}
//限制伺服俯仰角度// (80、-5、360改成宏(已改20231115)) alpha改成方位俯仰对应的Amizith
targetServoPole.Pitch = MIN(targetServoPole.Pitch, PitchMax);
targetServoPole.Pitch = MAX(targetServoPole.Pitch, PitchMin);
//1.光电吊舱伺服极坐标 转 光电伺服直角坐标
PointXYZ targetServoXYZ = getXYZFromPole(targetServoPole);
//2.光电伺服直角坐标 转 光电基准直角坐标
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromEOServoXYZ(targetServoXYZ, g_SlantingAngleBias);
//3.光电基准直角坐标 转 载体惯导直角坐标
PointXYZ targetZTXYZ = getZTXYZFromEOBaseXYZ(targetEOBaseXYZ, g_PositionXYZBias);
//4.如果是标定模式就通过标定函数getPosFromZTXYZ计算修正误差
getPosFromZTXYZ(targetZTXYZ, stEulerRPY, selfPointBLH, targetBLH, Sum_Error_Min, AngleError3D);
return *AngleError3D;
}
/*********************************************************************************************
* 姿
*
*
* x,y,z
*
**********************************************************************************************/
EulerRPY sRPYCacl::SumRPYCacl(Pole ServoAngle, EulerRPY s_RPYAngle)
{
//伺服角度相乘得到3*3矩阵
DOUBLE64 m1_R[9];
DOUBLE64 m2_R[9];
DOUBLE64 M1_M2[9];
DOUBLE64 M1_M2_M3[9];
DOUBLE64 m3_R[9];
DOUBLE64 m4_R[9];
DOUBLE64 m5_R[9];
//计算旋转矩阵
R_y(-ServoAngle.Pitch, m1_R);
Rz(-ServoAngle.Azimuth, m2_R);
Rx(-s_RPYAngle.Roll, m3_R);
R_y(-s_RPYAngle.Pitch, m4_R);
Rz(-s_RPYAngle.Yaw, m5_R);
MultiMat33(m2_R, m1_R, M1_M2);
MultiMat33(m3_R, M1_M2, M1_M2_M3);
DOUBLE64 DiliMuller[9];
//计算出地理坐标3*3矩阵DiliMuller
MultiMat333(m5_R, m4_R, M1_M2_M3, DiliMuller);
//
EulerRPY SumRPY;
SumRPY.Roll = ANGLE(atan2(DiliMuller[7], DiliMuller[8]));
SumRPY.Pitch = ANGLE(-asin(DiliMuller[6]));
SumRPY.Yaw = ANGLE(atan2(DiliMuller[3], DiliMuller[0]));
return SumRPY;
}
EulerRPY sRPYCacl::SumRPYCaclDown(Pole ServoAngle, EulerRPY s_RPYAngle)
{
//伺服角度相乘得到3*3矩阵
DOUBLE64 m1_R[9];
DOUBLE64 m2_R[9];
DOUBLE64 M1_M2[9];
DOUBLE64 M1_M2_M3[9];
DOUBLE64 m3_R[9];
DOUBLE64 m4_R[9];
DOUBLE64 m5_R[9];
//s7215a 载荷1使用计算安装面姿态
R_y(ServoAngle.Pitch, m1_R);
Rx(ServoAngle.fRoll, m2_R);
Rx(s_RPYAngle.Roll, m3_R);
R_y(s_RPYAngle.Pitch, m4_R);
Rz(s_RPYAngle.Yaw, m5_R);
MultiMat33(m2_R, m1_R, M1_M2);
MultiMat33(m4_R, M1_M2, M1_M2_M3);
DOUBLE64 DiliMuller[9];
//计算出地理坐标3*3矩阵DiliMuller
MultiMat333(m5_R, m3_R, M1_M2_M3, DiliMuller);
//
EulerRPY SumRPY;
SumRPY.Roll =-ANGLE(asin(DiliMuller[7]));
SumRPY.Pitch = ANGLE(atan2(DiliMuller[6], DiliMuller[8]));
SumRPY.Yaw = ANGLE(atan2(DiliMuller[1], DiliMuller[4]));
return SumRPY;
}
//说明:目标定位主接口函数
//输入载机结构体9个参数目标经纬高、姿态角、伺服角度和激光测距值
//输出:目标结构体(目标经纬高、地心地固直角坐标、目标三向速度以及合速度)
Angle3D sRPYCacl::TarGetLocate_Cal(stTrackPlatInfo mytrack)
{
//伺服方位俯仰
Pole targetServoPole;
targetServoPole.Azimuth = mytrack.fServoAz;
targetServoPole.Pitch = mytrack.fServoPt;
targetServoPole.distance = mytrack.Distance;
//载机方位、俯仰、横滚
EulerRPY stEulerRPY;
stEulerRPY.Yaw = mytrack.fPlatAz;
stEulerRPY.Pitch = mytrack.fPlatPt;
stEulerRPY.Roll = mytrack.fPlatRoll;
//载机经、纬、高
PointBLH selfPointBLH;
selfPointBLH.L = mytrack.fLon;
selfPointBLH.B = mytrack.fLat;
selfPointBLH.H = mytrack.fWGS_H;
//目标真实经、纬、高//
PointBLH targetBLH;
targetBLH.L = mytrack.tarLon;
targetBLH.B = mytrack.tarLat;
targetBLH.H = mytrack.tarH;
double* Sum_Error_Min;
double Error_Min = 111000;
Sum_Error_Min = &Error_Min;
Angle3D* AngleError3D;
Angle3D Error3D = { 0 };
AngleError3D = &Error3D;
//=========================目标定位===========================
//目标定位
//模式1--误差修正当Error有数值后getAngle3DFromEOServoPole不再调用注释掉93-98行
Angle3D AngleError = getAngle3DFromEOServoPole(targetServoPole, stEulerRPY, selfPointBLH, targetBLH, Sum_Error_Min, AngleError3D);//注:只计算一次
return AngleError;
}
/*********************************************************************************************
* 姿姿姿
*
*
*
*
**********************************************************************************************/
int Counter = 0;
Angle3D RPY = { 0 };
EulerRPY sRPYCacl::Zh_dRPY(stTrackPlatInfo track)
{
EulerRPY s_RPYAngle;
Pole ServoAngle;
Angle3D d_RPY = { 0 };
Counter++;
s_RPYAngle.Yaw = track.fPlatAz;
s_RPYAngle.Pitch = track.fPlatPt;
s_RPYAngle.Roll = track.fPlatRoll;
ServoAngle.Azimuth = track.fServoAz;
ServoAngle.Pitch = track.fServoPt;
ServoAngle.distance = track.Distance;
//计算目标在北东地坐标系下的姿态角
EulerRPY S_RPY = SumRPYCacl(ServoAngle, s_RPYAngle);
////计算修正姿态角
//if (Counter == 1)
//{
// d_RPY = TarGetLocate_Cal(track);
// RPY = d_RPY;
//}
EulerRPY FinalAngle;
FinalAngle.Yaw = RPY.dHAngle + S_RPY.Yaw;
FinalAngle.Pitch = RPY.dVAngle + S_RPY.Pitch;
FinalAngle.Roll = RPY.dSAngle + S_RPY.Roll;
return FinalAngle;
}
EulerRPY sRPYCacl::Zh_dRPYDown(stTrackPlatInfo track)
{
EulerRPY s_RPYAngle;
Pole ServoAngle;
Angle3D d_RPY = { 0 };
Counter++;
s_RPYAngle.Yaw = track.fPlatAz;
s_RPYAngle.Pitch = track.fPlatPt;
s_RPYAngle.Roll = track.fPlatRoll;
ServoAngle.Azimuth = track.fServoAz;
ServoAngle.Pitch = track.fServoPt;
ServoAngle.fRoll = track.fRoll;
ServoAngle.distance = track.Distance;
//计算目标在北东地坐标系下的姿态角
EulerRPY S_RPY = SumRPYCaclDown(ServoAngle, s_RPYAngle);
////计算修正姿态角
//if (Counter == 1)
//{
// d_RPY = TarGetLocate_Cal(track);
// RPY = d_RPY;
//}
EulerRPY FinalAngle;
FinalAngle.Yaw = RPY.dHAngle + S_RPY.Yaw;
FinalAngle.Pitch = RPY.dVAngle + S_RPY.Pitch;
FinalAngle.Roll = RPY.dSAngle + S_RPY.Roll;
return FinalAngle;
}