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.
GPS2NUE_Qt/Arith_VehicleCoordModule.cpp

891 lines
23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "Arith_VehicleCoordModule.h"
#include <cmath>
// 标定参数:安装误差
double g_YawBias = 0;
double g_PitchBias = 0;
double g_RollBias = 0;
double g_XBias = 0;
double g_YBias = 0;
double g_ZBias = 0;
void setBiasPara(double YawBias, double PitchBias, double RollBias, double deltaX, double deltaY, double deltaZ)
{
g_YawBias = YawBias;
g_PitchBias = PitchBias;
g_RollBias = RollBias;
g_XBias = deltaX;
g_YBias = deltaY;
g_ZBias = deltaZ;
}
void getBiasPara(double * YawBias, double * PitchBias, double * RollBias, double * deltaX, double * deltaY, double * deltaZ)
{
*YawBias = g_YawBias;
*PitchBias =g_PitchBias;
*RollBias = g_RollBias;
*deltaX = g_XBias;
*deltaY= g_YBias;
*deltaZ = g_ZBias;
}
// 像方到物方转换
Pole getPointMirrorServoPoleFromImageXY(int Col,int Row,int nWidth,int nHeight,
float fServoA,float fServoB,float fLen,float pxSizeOfum)
{
// by wcw04046 @ 2021/12/04
// 注意:在通常成像系统中,伺服读数基本等价于伺服系下角度(需要考虑正割补偿)
// 在指向镜成像系统中,伺服读数与伺服系下角度完全不等价 fServoAz fServoPt 与目标在伺服系位置非线性
// 伺服坐标系角度
Pole ServoPole;
// 像素焦距
float f_0 = fLen/pxSizeOfum * 1000;
// 等效像方入射矢量
PointXYZ CamVec;
CamVec.X = f_0;
CamVec.Y = -nHeight/2 + Row;
CamVec.Z = (-nWidth/2 + Col);
// 反射镜能将正前方(x轴)的目标反射到成像系统光轴(y轴)上时,角编码器为零位
// 平面镜1零位的法向量
PointXYZ N_01;
N_01.X = 1/sqrt(2.0);
N_01.Y = 1/sqrt(2.0);
N_01.Z = 0;
double Sx[9] = {1,0,0,
0,cos(RADIAN(fServoA)),-sin(RADIAN(fServoA)),
0,sin(RADIAN(fServoA)),cos(RADIAN(fServoA))};
double Sy[9] = {cos(RADIAN(fServoB)),0,-sin(RADIAN(fServoB)),
0,1,0,
sin(RADIAN(fServoB)),0,cos(RADIAN(fServoB))};
PointXYZ N_1 = RtPoint(Sx,RtPoint(Sy,N_01));
// 镜面反射矩阵
// M = eye(3)-(2*N*N');
double M1[9] = {0};
RMirror(N_1,M1);
// 平面镜2零位的法向量
PointXYZ N_02;
N_02.X = -1/sqrt(2.0);
N_02.Y = -1/sqrt(2.0);
N_02.Z = 0;
PointXYZ N_2 = RtPoint(Sx,N_02);
double M2[9] = {0};
RMirror(N_2,M2);
// 平面镜3零位的法向量
PointXYZ N_03;
N_03.X = 1/sqrt(2.0);
N_03.Y = -1/sqrt(2.0);
N_03.Z = 0;
PointXYZ N_3 = RtPoint(Sx,N_03);
double M3[9] = {0};
RMirror(N_3,M3);
// 平面镜4零位的法向量
PointXYZ N_04;
N_04.X = -1/sqrt(2.0);
N_04.Y = 1/sqrt(2.0);
N_04.Z = 0;
PointXYZ N_4 = RtPoint(Sx,N_04);
double M4[9] = {0};
RMirror(N_4,M4);
// 等效物方出射矢量
PointXYZ worldPosVec = RtPoint(M1,RtPoint(M2,RtPoint(M3,RtPoint(M4,CamVec))));
PointXYZ worldPosVec_1 = NormPoint(worldPosVec);
ServoPole.alpha = ANGLE(asin(worldPosVec_1.Y));
ServoPole.beta = ANGLE(atan2(worldPosVec_1.Z,worldPosVec_1.X));
ServoPole.distance = 1000;
return ServoPole;
}
// 物方到像方转换
void getPointMirrorImageXYFromServoPole(int* Col,int* Row,int nWidth,int nHeight,float WAlaph,float WBeta,
float fServoA,float fServoB,float fLen,float pxSizeOfum)
{
//物方
int dep = 1000;
PointXYZ WorldVec;
WorldVec.Y = -dep * sin(RADIAN(WAlaph));
WorldVec.X = -dep * cos(RADIAN(WAlaph)) * cos(RADIAN(WBeta));
WorldVec.Z = -dep * cos(RADIAN(WAlaph)) * sin(RADIAN(WBeta));
// 内参矩阵
float f_0 = fLen/pxSizeOfum * 1000;
double K[9] =
{f_0,0,nWidth/2,
0,f_0,nHeight/2,
0,0,1};
// 平面镜1零位的法向量
PointXYZ N_01;
N_01.X = 1/sqrt(2.0);
N_01.Y = 1/sqrt(2.0);
N_01.Z = 0;
double Sx[9] = {1,0,0,
0,cos(RADIAN(fServoB)),-sin(RADIAN(fServoB)),
0,sin(RADIAN(fServoB)),cos(RADIAN(fServoB))};
double Sy[9] = {cos(RADIAN(fServoA)),0,-sin(RADIAN(fServoA)),
0,1,0,
sin(RADIAN(fServoA)),0,cos(RADIAN(fServoA))};
PointXYZ N_1 = RtPoint(Sx,RtPoint(Sy,N_01));
// 镜面反射矩阵
// M = eye(3)-(2*N*N');
double M1[9] = {0};
RMirror(N_1,M1);
// 平面镜2零位的法向量
PointXYZ N_02;
N_02.X = -1/sqrt(2.0);
N_02.Y = -1/sqrt(2.0);
N_02.Z = 0;
PointXYZ N_2 = RtPoint(Sx,N_02);
double M2[9] = {0};
RMirror(N_2,M2);
// 平面镜3零位的法向量
PointXYZ N_03;
N_03.X = 1/sqrt(2.0);
N_03.Y = -1/sqrt(2.0);
N_03.Z = 0;
PointXYZ N_3 = RtPoint(Sx,N_03);
double M3[9] = {0};
RMirror(N_3,M3);
// 平面镜4零位的法向量
PointXYZ N_04;
N_04.X = -1/sqrt(2.0);
N_04.Y = 1/sqrt(2.0);
N_04.Z = 0;
PointXYZ N_4 = RtPoint(Sx,N_04);
double M4[9] = {0};
RMirror(N_4,M4);
PointXYZ camPosVec = RtPoint(M4,RtPoint(M3,RtPoint(M2,RtPoint(M1,WorldVec))));
double m_adjust[9] = {0,0,1,0,1,0,1,0,0};
PointXYZ pixPos = RtPoint(K,RtPoint(m_adjust,camPosVec));
*Col = pixPos.X / float(pixPos.Z);
*Row = pixPos.Y / float(pixPos.Z);
}
Pole getCamZaxisNUERota(double mYaw,double mPitch,double mRoll,double servoAlpha, double servoBeta)
{
// 定义相机坐标系Z轴向量长度不影响
PointXYZ pTest = {0};pTest.Z = 10000;
//计算旋转矩阵
double Mat[9] = {0};
getCarNUEXYZFromEOCamXYZ_Mat(mYaw,mPitch,mRoll,servoAlpha,servoBeta,Mat);
// 计算大地系向量
PointXYZ targetCarNUEXYZ = RtPoint(Mat,pTest);
// 计算大地系转动量
Pole targetCarNUEPole = getPoleFromXYZ(targetCarNUEXYZ);
return targetCarNUEPole;
}
// 信息上报函数
Pole getCarNUEPoleFromEOCamPole(Pole targetCamPole, double mYaw, double mPitch, double mRoll, double servoAlpha, double servoBeta)
{
//// 方位角限制在0-360
if (targetCamPole.beta > 360)
{
targetCamPole.beta -= 360;
}
if(targetCamPole.distance <= 100)
{
targetCamPole.distance = 10000;
}
//限制俯仰角度
// targetCamPole.alpha = MIN(targetCamPole.alpha, 80);
// targetCamPole.alpha = MAX(targetCamPole.alpha, -5);
// 1:一般旋转矩阵方法
// 光电镜面极坐标 转 光电镜面直角坐标
PointXYZ targetCamXYZ = getXYZFromPole(targetCamPole);
// 光电镜面直角坐标 转 光电伺服直角坐标
PointXYZ targetServoXYZ = getEOServoXYZFromEOCamXYZ(targetCamXYZ, servoAlpha, servoBeta);
// 2:正割补偿方法
// 光电镜面极坐标 转 光电伺服极坐标
// Pole targetEOServoPOLE;
// targetEOServoPOLE.alpha = alaph + targetCamPole.alpha;
// targetEOServoPOLE.beta = beta + targetCamPole.beta/cos(RADIAN(alaph));
// targetEOServoPOLE.distance = targetCamPole.distance;
// // 光电伺服极坐标 转 光电伺服直角坐标
// targetServoXYZ = getXYZFromPole(targetEOServoPOLE);
//指向镜系统的成像模型
#ifdef POINT_MIRROR_SYS
int nWidth = 640;
int nHeight = 512;
int Row = SERVO_CalcObjCoordinateX((FLOAT32)targetCamPole.beta, nWidth,
0, g_SERVO_stInput.fResolAz);
int Col = SERVO_CalcObjCoordinateY((FLOAT32)targetCamPole.alpha, nHeight,
0, g_SERVO_stInput.fResolPt);
// test
//servoBeta = 20;
//servoAlpha = 5;
//Col = 320;
//Row = 256;
// Pole targetServoPole1 = getPointMirrorServoPoleFromImageXY( Col, Row, nWidth, nHeight,
// servoBeta, servoAlpha,80,15);
// targetServoXYZ = getXYZFromPole(targetServoPole1);
//
// Col = 0;
// Row = 0;
//
// getPointMirrorImageXYFromServoPole(&Col,&Row,nWidth,nHeight,targetServoPole.alpha,targetServoPole.beta,
// servoBeta, servoAlpha,80,15);
Pole targetServoPole = getPointMirrorServoPoleFromImageXY( Row, Col, nWidth, nHeight,
servoBeta, servoAlpha,80,15);
targetServoXYZ = getXYZFromPole(targetServoPole);
#endif
// 光电伺服直角坐标 转 光电基准直角坐标
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromEOServoXYZ(targetServoXYZ, g_YawBias, g_PitchBias, g_RollBias);
// 光电基准直角坐标 转 平台直角坐标
PointXYZ targetCarXYZ = getCarXYZFromEOBaseXYZ(targetEOBaseXYZ, g_XBias, g_YBias, g_ZBias);
// 平台直角坐标 转 平台地理直角坐标
PointXYZ targetCarNUEXYZ = getCarNUEXYZFromCarXYZ(targetCarXYZ, mYaw, mPitch, mRoll);
// 平台地理直角坐标 转 平台地理极坐标
Pole targetCarNUEPole = getPoleFromXYZ(targetCarNUEXYZ);
#if 0
//double Mat[9] = {0};
//mYaw = 0;mPitch = 80;mRoll =5.1;
//servoAlpha = 0;servoBeta=0;
PointXYZ pTest = {0};pTest.Z = 10000;
getCarNUEXYZFromEOCamXYZ_Mat(mYaw,mPitch,mRoll,servoAlpha,servoBeta,Mat);
PointXYZ targetCarNUEXYZ2 = RtPoint(Mat,pTest);
Pole targetCarNUEPole2 = getPoleFromXYZ(targetCarNUEXYZ2);
#endif
// 上报目标平台地理极坐标
return targetCarNUEPole;
}
PointXYZ getEOServoXYZFromEOCamXYZ(PointXYZ targetCamXYZ,double alaph,double beta)
{
// 先绕Z轴俯仰角旋转-alaph后绕Y轴方位角旋转-beta
double oppRz[9];
double oppRy[9];
double oppRyz[9];
// 计算旋转矩阵
Rz(-alaph, oppRz);
Ry(-beta, oppRy);
MultiMat33(oppRy,oppRz, oppRyz);
// 坐标转换
return RtPoint(oppRyz, targetCamXYZ);
}
PointXYZ getEOBaseXYZFromEOServoXYZ(PointXYZ targetServoXYZ, double eYaw, double ePitch, double eRoll)
{
// 先绕x轴横滚旋转 -eRoll再绕z轴俯仰旋转 -ePitch再绕y轴方位旋转-eYaw
double oppRx[9];
double oppRy[9];
double oppRz[9];
double oppRyzx[9];
// 计算旋转矩阵
Rx(-eRoll, oppRx);
Rz(-ePitch, oppRz);
Ry(-eYaw, oppRy);
MultiMat333(oppRy,oppRz, oppRx, oppRyzx);
// 坐标转换
return RtPoint(oppRyzx, targetServoXYZ);
}
PointXYZ getCarXYZFromEOBaseXYZ(PointXYZ targetEOBaseXYZ, double deltaX, double deltaY, double deltaZ)
{
//平台坐标系下目标坐标
PointXYZ targetCarXYZ;
targetCarXYZ.X = targetEOBaseXYZ.X + deltaX;
targetCarXYZ.Y = targetEOBaseXYZ.Y + deltaY;
targetCarXYZ.Z = targetEOBaseXYZ.Z + deltaZ;
return targetCarXYZ;
}
PointXYZ getCarNUEXYZFromCarXYZ(PointXYZ targetCarXYZ, double mYaw, double mPitch, double mRoll)
{
// 先绕x轴横滚旋转 -mRoll再绕z轴俯仰旋转 -mPitch再绕y轴方位旋转-mYaw
double oppRx[9];
double oppRy[9];
double oppRz[9];
double oppRyzx[9];
// 计算旋转矩阵
Rx(-mRoll, oppRx);
Rz(-mPitch, oppRz);
Ry(-mYaw, oppRy);
MultiMat333(oppRy,oppRz, oppRx, oppRyzx);
// 坐标转换
return RtPoint(oppRyzx, targetCarXYZ);
}
// 接受导引函数
Pole getEOServoPoleFromCarNUEPole(Pole targetCarNUEPole, Pole* targetEOCamPole,double mYaw, double mPitch, double mRoll, double servoAlpha, double servoBeta)
{
// 地理极坐标 转 地理直角坐标
PointXYZ targetCarNUEXYZ = getXYZFromPole(targetCarNUEPole);
// 地理直角坐标 转 平台直角坐标
PointXYZ targetCarXYZ = getCarXYZFromCarNUEXYZ(targetCarNUEXYZ, mYaw, mPitch, mRoll);
// 平台直角 转 光电基准系直角
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromCarXYZ(targetCarXYZ, g_XBias, g_YBias, g_ZBias);
// 光电基准系直角 转 光电伺服直角
PointXYZ targetEOServoXYZ = getEOServoXYZFromEOBaseXYZ(targetEOBaseXYZ, g_YawBias, g_PitchBias, g_RollBias);
// 光电伺服直角 转 光电伺服极坐标
Pole targetEOServoPole = getPoleFromXYZ(targetEOServoXYZ);
// 光电伺服直角 转 光电镜面直角坐标
PointXYZ targetEOCamXYZ = getEOCamXYZFromEOServoXYZ(targetEOServoXYZ, servoAlpha, servoBeta);
// 光电镜面直角系 转 光电镜面极坐标
*targetEOCamPole = getPoleFromXYZ(targetEOCamXYZ);
//指向镜系统的成像模型
#ifdef POINT_MIRROR_SYS
int nWidth = 640;
int nHeight = 512;
int Col = 0;
int Row = 0;
getPointMirrorImageXYFromServoPole(&Col,&Row,nWidth,nHeight,targetEOServoPole.alpha,targetEOServoPole.beta,servoAlpha,servoBeta,80,15);
// 计算目标的方位角、俯仰角
targetEOCamPole->beta = SERVO_CalcObjAzimuth(Col,
nWidth, 0, g_SERVO_stInput.fResolAz);
targetEOCamPole->alpha = SERVO_CalcObjPitching(Row,
nHeight,0, g_SERVO_stInput.fResolPt);
#endif
return targetEOServoPole;
}
PointXYZ getCarXYZFromCarNUEXYZ(PointXYZ targetCarNUEXYZ, double mYaw, double mPitch, double mRoll)
{
// 先绕y轴方位旋转mYaw -> 再绕z轴俯仰旋转 mPitch -> 绕x轴横滚旋转 mRoll
double oppRx[9];
double oppRy[9];
double oppRz[9];
double oppRxzy[9];
// 计算旋转矩阵
Ry(mYaw, oppRy);
Rz(mPitch, oppRz);
Rx(mRoll, oppRx);
MultiMat333(oppRx, oppRz, oppRy, oppRxzy);
// 坐标转换
return RtPoint(oppRxzy, targetCarNUEXYZ);
}
PointXYZ getEOBaseXYZFromCarXYZ(PointXYZ targetCarXYZ, double deltaX, double deltaY, double deltaZ)
{
//平台坐标系下目标坐标
PointXYZ targetEOBaseXYZ;
targetEOBaseXYZ.X = targetCarXYZ.X - deltaX;
targetEOBaseXYZ.Y = targetCarXYZ.Y - deltaY;
targetEOBaseXYZ.Z = targetCarXYZ.Z - deltaZ;
return targetEOBaseXYZ;
}
PointXYZ getEOServoXYZFromEOBaseXYZ(PointXYZ targetEOBaseXYZ, double eYaw, double ePitch, double eRoll)
{
// 先绕y轴方位旋转eYaw,再绕z轴俯仰旋转 ePitch,再绕x轴横滚旋转 eRoll
double oppRx[9];
double oppRy[9];
double oppRz[9];
double oppRxzy[9];
// 计算旋转矩阵
Rx(eRoll, oppRx);
Rz(ePitch, oppRz);
Ry(eYaw, oppRy);
MultiMat333(oppRx, oppRz, oppRy, oppRxzy);
// 坐标转换
return RtPoint(oppRxzy, targetEOBaseXYZ);
}
PointXYZ getEOCamXYZFromEOServoXYZ(PointXYZ targetEOServoXYZ, double alaph, double beta)
{
// 先绕Y轴方位角旋转beta,后绕Z轴俯仰角旋转alaph
double oppRz[9];
double oppRy[9];
double oppRzy[9];
// 计算旋转矩阵
Rz(alaph, oppRz);
Ry(beta, oppRy);
MultiMat33(oppRz, oppRy, oppRzy);
// 坐标转换
return RtPoint(oppRzy, targetEOServoXYZ);
}
Pole getPoleFromXYZ(PointXYZ targetXYZ)
{
double x = targetXYZ.X;
double y = targetXYZ.Y;
double z = targetXYZ.Z;
Pole result;
result.distance = sqrt(x*x + y*y + z*z);
result.alpha = ANGLE(asin(y / result.distance));
//if (x < 0)
//{
// result.alpha = -180-result.alpha;
//}
result.beta = (ANGLE(atan2(z , x)));
// if (x < 0 && z >= 0) // 90 - 180
// {
// result.beta = 180 - result.beta;
// }
// else if (x < 0 && z < 0) // 180 - 270
// {
// result.beta = result.beta + 180;
// }
// else if (x >= 0 && z < 0) // 270 - 360
// {
// result.beta = 360 - result.beta;
// }
return result;
}
PointXYZ getXYZFromPole(Pole targetPole)
{
// 距离未知时,异原点坐标系之间不能转换
// 但由于同车坐标系的原点差一般远小于目标距离,故距离较大时误差较小,误差量级可以用线偏差/距离获得的弧度进行估计
// 如线偏差1米目标3000米则转换误差为(1/1000-1/3000)约为0.04°
if (targetPole.distance < 100)
{
targetPole.distance = 1000;
}
PointXYZ result;
double aa, bb, cc;
//double ac = sqrt(targetPole.distance*targetPole.distance-bb*bb);
bb = sin(RADIAN(targetPole.alpha)) * targetPole.distance;
double ac = sqrt(targetPole.distance*targetPole.distance - bb*bb);
aa = cos(RADIAN(targetPole.beta)) * ac;
cc = sin(RADIAN(targetPole.beta)) * ac;
result.X = aa;
result.Y = bb;
result.Z = cc;
return result;
}
//大地坐标转地球空间直角坐标
PointXYZ getXYZFromBLH(PointBLH BLH)
{
double B = BLH.B;
double L = BLH.L;
double H = BLH.H;
double W = sqrt(1 - ee * pow(sin(RADIAN(B)), 2));
double N = a / W; // 椭球的卯酉圈曲率
// 将地理坐标变换到空间直角坐标
double X = (N + H) * cos(RADIAN(B)) * cos(RADIAN(L));
double Y = (N + H) * cos(RADIAN(B)) * sin(RADIAN(L));
double Z = (N * (1 - ee) + H) * sin(RADIAN(B));
PointXYZ pointXYZ;
pointXYZ.X = X;
pointXYZ.Y = Y;
pointXYZ.Z = Z;
return pointXYZ;
}
//地球空间直角坐标-->大地坐标
PointBLH getBLHFromXYZ(PointXYZ pointXYZ)
{
double X = pointXYZ.X;
double Y = pointXYZ.Y;
double Z = pointXYZ.Z;
double U = atan(Z * a / (sqrt(X * X + Y * Y) * b));
double B0 = atan((Z + b * epep * pow(sin(U), 3)) / (sqrt(X*X + Y*Y) - a*ee*pow(cos(U), 3)));
double N = a / sqrt(1 - ee * pow(sin(B0), 2));
//double L = atan(Y /X);
double L = atan2(Y, X); // 修改为全球范围计算 by wcw04046 @ 2021/02/18
double H = sqrt(X*X + Y*Y + pow(Z + N*ee*sin(B0), 2)) - N;
double B = atan(Z / sqrt(X*X + Y*Y) / (1 - ee*N / (N + H)));
PointBLH pointBLH;
pointBLH.B = ANGLE(B);
pointBLH.H = H;
// // 此处仅考虑东经
// pointBLH.L = ANGLE(L) > 0 ? ANGLE(L) : ANGLE(L) + 180;
// 修改为全球范围计算 by wcw04046 @ 2021/02/18
pointBLH.L = ANGLE(L);
return pointBLH;
}
//*********************************************************************************************
// 由NUE直角坐标变换到CGCS直角坐标
// targetPointXYZNUE下的目标坐标
// selfPointXYZ测站在CGCS下的直角坐标
// 返回CGCS下的目标坐标
//*********************************************************************************************
PointXYZ getCGCSXYZFromNUEXYZ(PointXYZ targetPointXYZ, PointXYZ selfPointXYZ)
{
// 将测站所在位置的CGCS直角坐标变换到地理坐标
PointBLH selfPointBLH = getBLHFromXYZ(selfPointXYZ);
/* 由NUE直角坐标变换到CGCS直角坐标*/
double A[3];
double G[3];
double OppRx[9];
double OppRy[9];
double OppRz[9];
double OppRzx[9];
double OppRzxy[9];
// 1、计算旋转矩阵
Rx(-selfPointBLH.B, OppRx);
Ry(-90, OppRy);
Rz(90 - selfPointBLH.L, OppRz);
MultiMat(OppRz, OppRx, OppRzx, 3, 3, 3);
MultiMat(OppRzx, OppRy, OppRzxy, 3, 3, 3);
// 2、将NUE直角坐标变换到CGCS直角坐标
A[0] = targetPointXYZ.X;
A[1] = targetPointXYZ.Y;
A[2] = targetPointXYZ.Z;
MultiMat(OppRzxy, A, G, 3, 3, 1);
PointXYZ result;
result.X = G[0] + selfPointXYZ.X;
result.Y = G[1] + selfPointXYZ.Y;
result.Z = G[2] + selfPointXYZ.Z;
return result;
}
//*********************************************************************************************
// 由CGCS直角坐标变换到NUE直角坐标
// targetPointXYZCGCS下的目标坐标
// selfPointXYZ测站在CGCS下的直角坐标
// 返回NUE下的目标坐标
//*********************************************************************************************
PointXYZ getNUEXYZFromCGCSXYZ(PointXYZ targetPointXYZ, PointXYZ selfPointXYZ)
{
// 将测站所在位置的CGCS直角坐标变换到地理坐标
PointBLH selfPointBLH = getBLHFromXYZ(selfPointXYZ);
// 计算中间值
double dx = targetPointXYZ.X - selfPointXYZ.X;
double dy = targetPointXYZ.Y - selfPointXYZ.Y;
double dz = targetPointXYZ.Z - selfPointXYZ.Z;
/* 由CGCS直角坐标变换到NUE直角坐标 */
double A[3];
double G[3];
double OppRx[9];
double OppRy[9];
double OppRz[9];
double OppRyx[9];
double OppRyxz[9];
// 1、计算旋转矩阵
Rx(selfPointBLH.B, OppRx);
Ry(90, OppRy);
Rz(-90 + selfPointBLH.L, OppRz);
MultiMat(OppRy, OppRx, OppRyx, 3, 3, 3);
MultiMat(OppRyx, OppRz, OppRyxz, 3, 3, 3);
// 2、将CGCS直角坐标变换到NUE直角坐标
A[0] = dx;
A[1] = dy;
A[2] = dz;
MultiMat(OppRyxz, A, G, 3, 3, 1);
PointXYZ result;
result.X = G[0];
result.Y = G[1];
result.Z = G[2];
return result;
}
// 绕X轴旋转矩阵
/* 1 0 0
0 cos sin
0 -sin cos
*/
void Rx(double omega, double *Opp)
{
double coso = cos(RADIAN(omega));
double 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 Ry(double omega, double *Opp)
{
double coso = cos(RADIAN(omega));
double 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
*/
void Rz(double omega, double *Opp)
{
double coso = cos(RADIAN(omega));
double 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;
}
// 镜面反射矩阵计算
void RMirror(PointXYZ normalVec, double *Opp)
{
// M = eye(3)-(2*N*N');
Opp[0] = 1-2*normalVec.X*normalVec.X;
Opp[1] = -2*normalVec.X*normalVec.Y;
Opp[2] = -2*normalVec.X*normalVec.Z;
Opp[3] = -2*normalVec.X*normalVec.Y;
Opp[4] = 1-2*normalVec.Y*normalVec.Y;
Opp[5] = -2*normalVec.Y*normalVec.Z;
Opp[6] = -2*normalVec.X*normalVec.Z;
Opp[7] = -2*normalVec.Y*normalVec.Z;
Opp[8] = 1-2*normalVec.Z*normalVec.Z;
}
//*********************************************************************************************
// 矩阵乘法矩阵A*矩阵B
//*********************************************************************************************
void MultiMat(double *A, double *B, double *AB, int m, int n, int p)
{
// A为m*n ; B为n*p ;输出AB为m*p
int i, j, k;
double 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;
}
}
}
//*********************************************************************************************
// 3阶矩阵乘法矩阵A*矩阵B
//*********************************************************************************************
void MultiMat33(double * A, double * B, double * AB)
{
MultiMat(A, B, AB, 3, 3, 3);
}
//*********************************************************************************************
// 3阶矩阵乘法矩阵A*矩阵B*矩阵C
//*********************************************************************************************
void MultiMat333(double * A, double * B, double * C, double * ABC)
{
double BC[9];
MultiMat(B, C, BC, 3, 3, 3);
MultiMat(A, BC, ABC, 3, 3, 3);
}
// 3维空间旋转矩阵执行坐标转换
PointXYZ RtPoint(double * M, PointXYZ Point)
{
// M * [X,Y,Z]'
double A[3];
double G[3];
A[0] = Point.X;
A[1] = Point.Y;
A[2] = Point.Z;
MultiMat(M, A, G, 3, 3, 1);
PointXYZ result;
result.X = G[0];
result.Y = G[1];
result.Z = G[2];
return result;
}
// 归一化
PointXYZ NormPoint(PointXYZ Point)
{
double Len = sqrt(Point.X * Point.X + Point.Y * Point.Y + Point.Z * Point.Z);
Point.X /= Len;
Point.Y /= Len;
Point.Z /= Len;
return Point;
}
void getCarNUEXYZFromEOCamXYZ_Mat(double mYaw,double mPitch,double mRoll,double servoAlpha, double servoBeta,double* Mat)
{
double oppRz[9];
double oppRy[9];
double oppRx[9];
// 1.光电镜面直角坐标 转 光电伺服直角坐标
// 先绕Z轴俯仰角旋转-alaph后绕Y轴方位角旋转-beta
double oppRyz_servo[9];
// 计算旋转矩阵
Rz(-servoAlpha, oppRz);
Ry(-servoBeta, oppRy);
MultiMat33(oppRy,oppRz, oppRyz_servo);
// 2.光电伺服直角坐标 转 光电基准直角坐标
// 先绕x轴横滚旋转 -eRoll再绕z轴俯仰旋转 -ePitch再绕y轴方位旋转-eYaw
double oppRyzx_base[9];
// 计算旋转矩阵
Rx(-g_RollBias, oppRx);
Rz(-g_PitchBias, oppRz);
Ry(-g_YawBias, oppRy);
MultiMat333(oppRy,oppRz, oppRx, oppRyzx_base);
// 3.光电基准直角坐标 转 平台直角坐标
// 不考虑平移关系
// 4.平台直角坐标 转 平台地理直角坐标
double oppRyzx_GEO[9];
// 计算旋转矩阵
Rx(-mRoll, oppRx);
Rz(-mPitch, oppRz);
Ry(-mYaw, oppRy);
MultiMat333(oppRy,oppRz, oppRx, oppRyzx_GEO);
// 连续旋转矩阵计算,注意顺序
MultiMat333(oppRyzx_GEO,oppRyzx_base,oppRyz_servo,Mat);
}