|
|
#include "Arith_CoordModule.h"
|
|
|
|
|
|
//#include "Arith_SysVar.h"
|
|
|
#include <cmath>
|
|
|
#include "Arith_Utils.h"
|
|
|
|
|
|
|
|
|
|
|
|
// 从惯性系(建航坐标系)到 像坐标系
|
|
|
POINT32F getImagePosFromStablePole(Pole stablePole, CameraParam cam, ServoParam servoInfo, EulerRPY att, DeviceSetupError err)
|
|
|
{
|
|
|
POINT32F imgPos = { 0 };
|
|
|
|
|
|
// 从稳定性到设备系
|
|
|
Pole devicePole = getDevicePoleFromStablePole(stablePole, att, err);
|
|
|
|
|
|
// 从设备系到像方
|
|
|
imgPos = getImagePosFromDevicePole(devicePole, cam, servoInfo);
|
|
|
|
|
|
return imgPos;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 从像坐标系 到 惯性系(建航坐标系)
|
|
|
Pole getStablePoleFromImagePos(POINT32F imagePos, CameraParam cam, ServoParam servoInfo, EulerRPY att, DeviceSetupError err)
|
|
|
{
|
|
|
Pole StablePole = { 0 };
|
|
|
|
|
|
// 从像方到设备系
|
|
|
Pole devicePole = getDevicePoleFromImagePos(imagePos, cam, servoInfo);
|
|
|
|
|
|
// 从设备系到惯性系
|
|
|
StablePole = getStablePoleFromDevicePole(devicePole, att, err);
|
|
|
|
|
|
return StablePole;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BBOOL bTargetInScanFov(ANGLE32F targetPos, Pole scanNueRange1, Pole scanNueRange2)
|
|
|
{
|
|
|
BBOOL AzInScan = TRUE;
|
|
|
BBOOL PtInScan = TRUE;
|
|
|
// 俯仰扫描区间有效
|
|
|
if (scanNueRange1.alpha != 0 && scanNueRange2.alpha != 0)
|
|
|
{
|
|
|
if (targetPos.fPt < scanNueRange1.alpha || targetPos.fPt > scanNueRange2.alpha)
|
|
|
{
|
|
|
PtInScan = FALSE;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 方位扫描区间有效
|
|
|
if (scanNueRange1.beta != 0 && scanNueRange2.beta != 0)
|
|
|
{
|
|
|
if (targetPos.fAz < scanNueRange1.beta || targetPos.fAz > scanNueRange2.beta)
|
|
|
{
|
|
|
AzInScan = FALSE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return (AzInScan && PtInScan);
|
|
|
|
|
|
}
|
|
|
|
|
|
Pole getDevicePoleFromStablePole(Pole stablePole, EulerRPY att, DeviceSetupError err)
|
|
|
{
|
|
|
Pole targetCarNUEPole = stablePole;
|
|
|
|
|
|
// 地理极坐标 转 地理直角坐标
|
|
|
PointXYZ targetCarNUEXYZ = getXYZFromPole(targetCarNUEPole);
|
|
|
|
|
|
// 地理直角坐标 转 平台直角坐标
|
|
|
PointXYZ targetCarXYZ = getCarXYZFromCarNUEXYZ(targetCarNUEXYZ, att.fYaw, att.fPitch, att.fRoll);
|
|
|
|
|
|
// 平台直角 转 光电基准系直角
|
|
|
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromCarXYZ(targetCarXYZ, err.g_XBias, err.g_YBias, err.g_ZBias);
|
|
|
|
|
|
// 光电基准系直角 转 光电伺服直角
|
|
|
PointXYZ targetEOServoXYZ = getEOServoXYZFromEOBaseXYZ(targetEOBaseXYZ, err.g_YawBias, err.g_PitchBias, err.g_RollBias);
|
|
|
|
|
|
// 光电伺服直角 转 光电伺服极坐标
|
|
|
Pole targetEOServoPole = getPoleFromXYZ(targetEOServoXYZ);
|
|
|
|
|
|
return targetEOServoPole;
|
|
|
|
|
|
}
|
|
|
|
|
|
Pole getStablePoleFromDevicePole(Pole devicePole, EulerRPY att, DeviceSetupError err)
|
|
|
{
|
|
|
// 设备系转伺服直角坐标
|
|
|
PointXYZ targetServoXYZ = getXYZFromPole(devicePole);
|
|
|
|
|
|
// 光电伺服直角坐标 转 光电基准直角坐标
|
|
|
PointXYZ targetEOBaseXYZ = getEOBaseXYZFromEOServoXYZ(targetServoXYZ, err.g_YawBias, err.g_PitchBias, err.g_RollBias);
|
|
|
|
|
|
// 光电基准直角坐标 转 平台直角坐标
|
|
|
PointXYZ targetCarXYZ = getCarXYZFromEOBaseXYZ(targetEOBaseXYZ, err.g_XBias, err.g_YBias, err.g_ZBias);
|
|
|
|
|
|
// 平台直角坐标 转 平台地理直角坐标
|
|
|
PointXYZ targetCarNUEXYZ = getCarNUEXYZFromCarXYZ(targetCarXYZ, att.fYaw, att.fPitch, att.fRoll);
|
|
|
|
|
|
// 平台地理直角坐标 转 平台地理极坐标
|
|
|
Pole targetCarNUEPole = getPoleFromXYZ(targetCarNUEXYZ);
|
|
|
|
|
|
return targetCarNUEPole;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 像方转设备系
|
|
|
Pole getDevicePoleFromImagePos(POINT32F imagePos, CameraParam cam, ServoParam servoInfo)
|
|
|
{
|
|
|
Pole targetDevicePole = { 0 };
|
|
|
|
|
|
if(cam.bImageRataSys)
|
|
|
{
|
|
|
double refmat[9] = { 0 };
|
|
|
PMS_MultiRefMat(servoInfo.fAz, servoInfo.fPt, servoInfo.fFSMAz, servoInfo.fFSMPt, refmat);
|
|
|
|
|
|
targetDevicePole = PMS_ProjectPixelToWorld((int)imagePos.x, (int)imagePos.y, refmat,
|
|
|
cam.f / cam.dSize * 1000, cam.dx + cam.ImageWidth / 2, cam.dy + cam.ImageHeight / 2);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 像方转相机坐标系
|
|
|
Pole targetCamPole = { 0 };
|
|
|
float fAglRes = FLOAT32(ANGLE(cam.dSize / cam.f / 1000));
|
|
|
SINT32 cx = cam.dx + cam.ImageWidth / 2;
|
|
|
SINT32 cy = cam.dy + cam.ImageHeight / 2;
|
|
|
targetCamPole.beta = (imagePos.x - cx) * fAglRes;
|
|
|
targetCamPole.alpha = (cy - imagePos.y) * fAglRes;
|
|
|
|
|
|
// 1:一般旋转矩阵方法
|
|
|
// 光电镜面极坐标 转 光电镜面直角坐标
|
|
|
PointXYZ targetCamXYZ = getXYZFromPole(targetCamPole);
|
|
|
|
|
|
// 光电镜面直角坐标 转 光电伺服直角坐标
|
|
|
PointXYZ targetServoXYZ = getEOServoXYZFromEOCamXYZ(targetCamXYZ, servoInfo.fPt, servoInfo.fAz);
|
|
|
|
|
|
// 2:正割补偿方法
|
|
|
// 光电镜面极坐标 转 光电伺服极坐标
|
|
|
// Pole targetEOServoPOLE;
|
|
|
// targetEOServoPOLE.alpha = alaph + targetCamPole.alpha;
|
|
|
// targetEOServoPOLE.beta = beta + targetCamPole.beta/cos(RADIAN(alaph));
|
|
|
// targetEOServoPOLE.distance = targetCamPole.distance;
|
|
|
// // 光电伺服极坐标 转 光电伺服直角坐标
|
|
|
// targetServoXYZ = getXYZFromPole(targetEOServoPOLE);
|
|
|
|
|
|
targetDevicePole = getPoleFromXYZ(targetServoXYZ);
|
|
|
}
|
|
|
|
|
|
|
|
|
return targetDevicePole;
|
|
|
}
|
|
|
|
|
|
|
|
|
// 设备系转像方坐标
|
|
|
POINT32F getImagePosFromDevicePole(Pole devicePole, CameraParam cam, ServoParam servoInfo)
|
|
|
{
|
|
|
POINT32F imgpos = { 0 };
|
|
|
|
|
|
// 常规光电成像模型
|
|
|
if(cam.bImageRataSys)
|
|
|
{
|
|
|
double refmat[9] = { 0 };
|
|
|
double refmat_inv[9] = { 0 };
|
|
|
PMS_MultiRefMat(servoInfo.fAz, servoInfo.fPt, servoInfo.fFSMAz, servoInfo.fFSMPt, refmat);
|
|
|
//invMat3(refmat, refmat_inv);
|
|
|
TransposeMat(refmat, 3, 3, refmat_inv);//等价
|
|
|
|
|
|
PointXYZ imgPosition =
|
|
|
PMS_ProjectWorldToPixel((float)devicePole.beta, (float)devicePole.alpha, refmat_inv,
|
|
|
cam.f / cam.dSize * 1000, cam.dx + cam.ImageWidth/2, cam.dy + cam.ImageHeight/2);
|
|
|
|
|
|
imgpos.x = (float)imgPosition.X;
|
|
|
imgpos.y = (float)imgPosition.Y;
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 设备极坐标转直角坐标
|
|
|
PointXYZ targetEOServoXYZ = getXYZFromPole(devicePole);
|
|
|
|
|
|
// 光电伺服直角 转 光电镜面直角坐标(相机系)
|
|
|
PointXYZ targetEOCamXYZ = getEOCamXYZFromEOServoXYZ(targetEOServoXYZ, servoInfo.fPt, servoInfo.fAz);
|
|
|
|
|
|
// 光电镜面极坐标
|
|
|
Pole targetEOCamPole = getPoleFromXYZ(targetEOCamXYZ);
|
|
|
|
|
|
float fAglRes = FLOAT32(ANGLE(cam.dSize / cam.f / 1000.0f));
|
|
|
SINT32 cx = cam.dx + cam.ImageWidth / 2;
|
|
|
SINT32 cy = cam.dy + cam.ImageHeight / 2;
|
|
|
imgpos.x = FLOAT32(targetEOCamPole.beta / fAglRes + cx);
|
|
|
imgpos.y = FLOAT32(cy - targetEOCamPole.alpha / fAglRes);
|
|
|
}
|
|
|
|
|
|
return imgpos;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PMS_MultiRefMat(float fMainAz, float fMainAPt, float fFSMAz, float fFSMPt, double* mat)
|
|
|
{
|
|
|
// 反射镜1
|
|
|
// fa -- 方位角输出-外框
|
|
|
// fb -- 俯仰角输出-内框
|
|
|
PointXYZ N1_0;
|
|
|
N1_0.X = 1 / sqrt(2.0);
|
|
|
N1_0.Y = 1 / sqrt(2.0);
|
|
|
N1_0.Z = 0;
|
|
|
|
|
|
// n1绕z轴旋转fb(向上为正)
|
|
|
double Sz[9] = { cosd(fMainAPt),sind(fMainAPt),0,
|
|
|
-sind(fMainAPt),cosd(fMainAPt),0,
|
|
|
0,0,1 };
|
|
|
|
|
|
// 再绕y轴旋转fa(向右为正)
|
|
|
double Sy[9] = { cosd(fMainAz),0,-sind(fMainAz),
|
|
|
0,1,0,
|
|
|
sind(fMainAz),0,cosd(fMainAz) };
|
|
|
|
|
|
// 反射镜1法向量 %% 前两个法向量在XOY面里
|
|
|
//N1_F = Sy * Sz * N1_0;
|
|
|
PointXYZ N1_F = RtPoint(Sy, RtPoint(Sz, N1_0));
|
|
|
|
|
|
// 反射镜1反射矩阵
|
|
|
//R1 = eye(3) - (2 * N1_F * N1_F');
|
|
|
double R1[9] = { 0 };
|
|
|
RMirror(N1_F, R1);
|
|
|
|
|
|
|
|
|
// 反射镜23,没有动 %%注意:第3、4面镜子已经在XOZ面里了,注意空间关系
|
|
|
PointXYZ N2_0;
|
|
|
N2_0.X = -1 / sqrt(2.0);
|
|
|
N2_0.Y = -1 / sqrt(2.0);
|
|
|
N2_0.Z = 0;
|
|
|
double R2[9] = { 0 };
|
|
|
RMirror(N2_0, R2);
|
|
|
|
|
|
PointXYZ N3_0;
|
|
|
N3_0.X = 1 / sqrt(2.0);
|
|
|
N3_0.Y = 0;
|
|
|
N3_0.Z = 1 / sqrt(2.0);
|
|
|
double R3[9] = { 0 };
|
|
|
RMirror(N3_0, R3);
|
|
|
|
|
|
// 反射镜4是快反
|
|
|
// Qa -- 方位角输出-外框,向右偏转为正
|
|
|
// Qb -- 俯仰角输出-内框,抬头为正
|
|
|
PointXYZ N4_0;
|
|
|
N4_0.X = 1 / sqrt(2.0);
|
|
|
N4_0.Y = 0;
|
|
|
N4_0.Z = -1 / sqrt(2.0);
|
|
|
|
|
|
// 外框扫描轴为y轴,内框扫描轴L0为x=z 即(1,0,1)'
|
|
|
double Sy2[9] = { cosd(fFSMAz),0,-sind(fFSMAz),
|
|
|
0,1,0,
|
|
|
sind(fFSMAz),0,cosd(fFSMAz) };
|
|
|
|
|
|
// 内框旋转向量,注意左手系,会引入负号
|
|
|
PointXYZ L0;
|
|
|
L0.X = 1;
|
|
|
L0.Y = 0;
|
|
|
L0.Z = 1;
|
|
|
double SL2[9] = { 0 };
|
|
|
rotationVectorToMatrix(L0, -fFSMPt, SL2);
|
|
|
|
|
|
//快反镜法向量,经过内框和外框旋转
|
|
|
// N4_F = Sy2 * SL2 * N4_0;
|
|
|
PointXYZ N4_F = RtPoint(Sy2, RtPoint(SL2, N4_0));
|
|
|
|
|
|
// 快反的反射矩阵
|
|
|
double R4[9] = { 0 };
|
|
|
RMirror(N4_F, R4);
|
|
|
|
|
|
// 整个光路的反射模型,从像方到物方
|
|
|
double tmp[9] = { 0 };
|
|
|
MultiMat333(R2, R3, R4, tmp);
|
|
|
MultiMat33(R1, tmp, mat);
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// 像方到物方的映射,转到方位俯仰角
|
|
|
Pole PMS_ProjectPixelToWorld(int x, int y, float fMainAz, float fMainAPt, float fFSMAz, float fFSMPt, float f_px, int cx, int cy)
|
|
|
{
|
|
|
// 计算反射矩阵
|
|
|
double mat[9] = { 0 };
|
|
|
PMS_MultiRefMat(fMainAz, fMainAPt, fFSMAz, fFSMPt, mat);
|
|
|
return PMS_ProjectPixelToWorld(x, y, mat, f_px, cx, cy);
|
|
|
}
|
|
|
|
|
|
Pole PMS_ProjectPixelToWorld(int x, int y, double* mat, float f_px, int cx, int cy)
|
|
|
{
|
|
|
Pole worldPole = { 0 };
|
|
|
// 内参信息
|
|
|
// const int nWidth = 860;
|
|
|
// const int nHeight = 715;
|
|
|
// const float f = 350;
|
|
|
// const int piexlSize = 7.5;
|
|
|
// float fpiexl = f/piexlSize * 1000; //像素焦距
|
|
|
|
|
|
// 从靶面出射的矢量
|
|
|
PointXYZ PO;
|
|
|
PO.X = -f_px;
|
|
|
PO.Y = -(y - cy);
|
|
|
PO.Z = -(x - cx);
|
|
|
|
|
|
//%%猜测y方向设置了-Y,否则成像应该是倒着的,所以这里
|
|
|
PO.Y = -PO.Y;
|
|
|
|
|
|
// 出射矢量
|
|
|
PointXYZ OQ;
|
|
|
OQ = RtPoint(mat, PO);
|
|
|
|
|
|
|
|
|
|
|
|
// 物方角度
|
|
|
double len = sqrt(PO.X * PO.X + PO.Y * PO.Y + PO.Z * PO.Z);
|
|
|
|
|
|
|
|
|
worldPole.alpha = ANGLE(asin(-OQ.Y / len));
|
|
|
worldPole.beta = ANGLE(atan2(OQ.Z, OQ.X));
|
|
|
|
|
|
return worldPole;
|
|
|
}
|
|
|
|
|
|
// PointXYZ PMS_ProjectPixelToWorldVec(int x, int y, double* mat, float f_px, int cx, int cy)
|
|
|
// {
|
|
|
// Pole worldPole = { 0 };
|
|
|
// // 内参信息
|
|
|
// // const int nWidth = 860;
|
|
|
// // const int nHeight = 715;
|
|
|
// // const float f = 350;
|
|
|
// // const int piexlSize = 7.5;
|
|
|
// // float fpiexl = f/piexlSize * 1000; //像素焦距
|
|
|
|
|
|
// // 从靶面出射的矢量
|
|
|
// PointXYZ PO;
|
|
|
// PO.X = -f_px;
|
|
|
// PO.Y = -(y - cy);
|
|
|
// PO.Z = -(x - cx);
|
|
|
|
|
|
// //%%猜测y方向设置了-Y,否则成像应该是倒着的,所以这里
|
|
|
// PO.Y = -PO.Y;
|
|
|
|
|
|
// // 出射矢量
|
|
|
// PointXYZ OQ;
|
|
|
// OQ = RtPoint(mat, PO);
|
|
|
|
|
|
// return OQ;
|
|
|
|
|
|
// }
|
|
|
//物方到像方的映射,转到像素位置
|
|
|
PointXYZ PMS_ProjectWorldToPixel(float fAz, float fPt, double* refmat, float f_px, int cx, int cy)
|
|
|
{
|
|
|
PointXYZ pxPos = { 0 };
|
|
|
|
|
|
// 物方直角系出射矢量
|
|
|
PointXYZ OQ = { 0 };
|
|
|
float Dep = 1000;//单位向量
|
|
|
OQ.Y = -Dep * sind(fPt);
|
|
|
OQ.X = Dep * cosd(fPt) * cosd(fAz);
|
|
|
OQ.Z = Dep * cosd(fPt) * sind(fAz);
|
|
|
|
|
|
|
|
|
// 投影,得到靶面出射矢量
|
|
|
PointXYZ PO = RtPoint(refmat, OQ);
|
|
|
|
|
|
PointXYZ OP = { 0 };//射向靶面
|
|
|
OP.X = -PO.X;
|
|
|
OP.Y = -PO.Y;
|
|
|
OP.Z = -PO.Z;
|
|
|
|
|
|
|
|
|
// 内参矩阵
|
|
|
pxPos.X = f_px * OP.Z / OP.X + cx;
|
|
|
pxPos.Y = -f_px * OP.Y / OP.X + cy;
|
|
|
|
|
|
|
|
|
return pxPos;
|
|
|
}
|
|
|
|
|
|
// PointXYZ PMS_ProjectWorldVecToPixel(PointXYZ worldVec, double* refmat, float f_px, int cx, int cy)
|
|
|
// {
|
|
|
// PointXYZ pxPos = { 0 };
|
|
|
// // 投影,得到靶面出射矢量
|
|
|
// PointXYZ PO = RtPoint(refmat, worldVec);
|
|
|
|
|
|
// PointXYZ OP = { 0 };//射向靶面
|
|
|
// OP.X = -PO.X;
|
|
|
// OP.Y = -PO.Y;
|
|
|
// OP.Z = -PO.Z;
|
|
|
|
|
|
|
|
|
// // 内参矩阵
|
|
|
// pxPos.X = f_px * OP.Z / OP.X + cx;
|
|
|
// pxPos.Y = -f_px * OP.Y / OP.X + cy;
|
|
|
|
|
|
|
|
|
// return pxPos;
|
|
|
// }
|
|
|
|
|
|
|
|
|
// // S726像方到物方转换
|
|
|
// 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;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // S726物方到像方转换
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
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°
|
|
|
|
|
|
// 吊舱无源定位允许最低高度10米
|
|
|
if (targetPole.distance < 10)
|
|
|
{
|
|
|
targetPole.distance = 10000;
|
|
|
}
|
|
|
|
|
|
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直角坐标
|
|
|
// targetPointXYZ:NUE下的目标坐标
|
|
|
// 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直角坐标
|
|
|
// targetPointXYZ:CGCS下的目标坐标
|
|
|
// 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;
|
|
|
}
|
|
|
|
|
|
|