0
0
Files
build/sensor/source/sensor_optical.cpp

339 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "sensor_optical.h"
#include "orbit_info.h"
#include "libconvert.h"
#include "liblog.h"
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "GNCFunction.h"
void GetMeasDISRemote(double Dis_Remote[2], double TarRVECI[6], double ChaRVECI[6], double MtxECI2VVLH[3][3], double LOS_Remote[9], int TargetFLAG);
void GetMeasDISClose(double Dis_Close[2], double TarRVECI[6], double ChaRVECI[6], double MtxECI2VVLH[3][3], double MtxVVLH2Body[3][3], double Euler[3], double R_Plane[2], int TargetFLAG);
/// @brief 生成小光电遥测帧
/// @param frame:生成的遥测帧数据
/// @return 生成帧的长度,生成失败返回0
//输入: TarRVECI[6],目标轨道 从姿轨动力学获得
// ChaRVECI[6],本体轨道 从姿轨动力学获得
// MtxECI2VVLH[3][3], 转移矩阵 从姿轨动力学获得
// LOS_Remote[9], 远距离相机测角从TX2中获取
// Euler[3], 姿态角 从姿轨动力学获得
// R_Plane[2], 近距离相机从TX2中获取
// TargetFLAG 标记位 //XGD和TX2使用标记,1--左帆板, 0--本体
//输出:frame 生成帧
void generate_xgd_frame(uint8_t *frame, double TarRVECI[6], double ChaRVECI[6], double MtxECI2VVLH[3][3], double MtxVVLH2Body[3][3], double LOS_Remote[9], double Euler[3], double R_Plane[2], int TargetFLAG)
{
static uint8_t frame_cnt = 0;
OPTICAL_TLM_STR xgd;
memset(frame,0,OPTIC_FRAME_LENGTH);
memset( (uint8_t *)&xgd.FRAME_HEAD,0,OPTIC_FRAME_LENGTH);
double Dis_Remote[2], Dis_Close[2];
GetMeasDISRemote(Dis_Remote, TarRVECI, ChaRVECI, MtxECI2VVLH, LOS_Remote, TargetFLAG);
GetMeasDISClose(Dis_Close, TarRVECI, ChaRVECI, MtxECI2VVLH, MtxVVLH2Body, Euler, R_Plane, TargetFLAG);
//printf("LOS_Remote is %10.3f \t %10.3f\r\n", Dis_Remote[0], Dis_Remote[1]);
//printf("LOS_Close is %10.3f \t %10.3f\r\n", Dis_Remote[0], Dis_Remote[1]);
spdlog::info("函数{0} Dis_Remote为:{1:.6f}, {2:.6f}, Dis_Close为:{3:.6f}, {4:.6f}",__FUNCTION__,
Dis_Remote[0], Dis_Remote[1],Dis_Close[0], Dis_Close[1]);
xgd.FRAME_HEAD = 0x90EB;
xgd.length = OPTIC_FRAME_LENGTH - 3;
xgd.AI01 = convert_endian((float)Dis_Remote[1]);
xgd.AI02 = convert_endian((float)Dis_Close[1]);
xgd.AI03 = htons(2);
xgd.AI19 = htonl(150);
xgd.AI_far = (uint8_t)Dis_Remote[0];
xgd.AI_close = (uint8_t)Dis_Close[0];
xgd.AI10 = frame_cnt++;
uint8_t checksum = 0;
uint8_t *buffer = (uint8_t *)&xgd.FRAME_HEAD;
for(int kc = 2;kc<OPTIC_FRAME_LENGTH-1;kc++)
checksum +=buffer[kc];
xgd.Check_sum = checksum;
spdlog::info("函数{0}OPTICAL数据帧长度为:{1:2d} 校验和为:{2:2x}",__FUNCTION__,
sizeof(OPTICAL_TLM_STR),xgd.Check_sum);
memcpy(frame,(uint8_t *)&xgd.FRAME_HEAD,OPTIC_FRAME_LENGTH);
}
void generate_photo_frame(uint8_t *frame)
{
static uint16_t frame_cnt = 0;
memset(frame,0,249);
frame[0] = 0xEB;
frame[1] = 0x91;
frame[2] = 0;
frame[3] = 245;
frame[4] = (frame_cnt & 0xFF00)>>8;
frame[5] = (frame_cnt & 0x00FF);
for(int kc = 6;kc<248;kc++) //不给校验位赋值
{
frame[kc] = frame_cnt+kc;
}
if(frame_cnt++>=270) frame_cnt = 0;
for(int kc= 2;kc<248;kc++)
frame[248] += frame[kc];
}
/* 远距离激光测距 */
void GetMeasDISRemote(double Dis_Remote[2], double TarRVECI[6], double ChaRVECI[6], double MtxECI2VVLH[3][3], double LOS_Remote[9], int TargetFLAG) {
/* 远距离激光测距模拟模块 */
/* 输入量 */
/* TarRVECI 目标惯性系下RV */
/* ChaRVECI 追踪星惯性系下RV */
/* MtxECI2VVLH 追踪星惯性系到轨道系的旋转矩阵Aoi */
/* LOS_Remote 远程测距角度信息 */
/* TargetFLAG 目标选择标志 */
/* 输出量 */
/* Dis_Remote 远距离激光测距信息:标志位和距离*/
double Dis_Remote_Measure = 0.0;
double LOSReal, Dis_Measure, temp[3];
int LOS_Flag, DisRemoteFlag;
static double qbo[4] = { 1, 0, 0, 0 };
double Alpha_Left_remote = LOS_Remote[2];
double Beta_Left_remote = LOS_Remote[1];
int LeftLOSRemoteFlag = LOS_Remote[0];
double Alpha_Body_remote = LOS_Remote[5];
double Beta_Body_remote = LOS_Remote[4];
int BodyLOSRemoteFlag = LOS_Remote[3];
double Alpha_Right_remote = LOS_Remote[8];
double Beta_Right_remote = LOS_Remote[7];
int RightLOSRemoteFlag = LOS_Remote[6];
// 真实值
double RT[3] = { TarRVECI[0], TarRVECI[1], TarRVECI[2] };
double RC[3] = { ChaRVECI[0], ChaRVECI[1], ChaRVECI[2] };
double R_Co5[3] = { 0 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
R_Co5[i] += MtxECI2VVLH[i][j] * (RT[j] - RC[j]);
}
}
double Dis_Body = norm(R_Co5, 3);
double a[3] = { 0, -10.682, 0 };
mtxAdd((double*)temp, (double*)R_Co5, (double*)a, 3, 1);
double Dis_Fan_Left = norm(temp, 3);
double b[3] = { 0, 10.682, 0 };
mtxAdd((double*)temp, (double*)R_Co5, (double*)b, 3, 1);
double Dis_Fan_Right = norm(temp, 3);
// 目标选择0~本体1~左帆板2~右帆板,在OBC里做切换
/*if (TargetFLAG == 0)
{
Dis_Measure = Dis_Body;
LOSReal = fabs(Beta_Body_remote - 90.0);
LOS_Flag = BodyLOSRemoteFlag;
}
else if (TargetFLAG == 1)
{
Dis_Measure = Dis_Fan_Left;
LOSReal = fabs(Beta_Left_remote - 90.0);
LOS_Flag = LeftLOSRemoteFlag;
}
else if (TargetFLAG == 2)
{
Dis_Measure = Dis_Fan_Right;
LOSReal = fabs(Beta_Right_remote - 90.0);
LOS_Flag = RightLOSRemoteFlag;
}*/
Dis_Measure = Dis_Body;
LOSReal = fabs(Beta_Body_remote - 90.0);
LOS_Flag = BodyLOSRemoteFlag;
// 在测角有效、角度在4°以内且距离在一定范围之内测距有效
if (LOS_Flag == 0 || LOSReal > 4.0 || Dis_Measure > 2000)
{
DisRemoteFlag = 0;
}
else
{
DisRemoteFlag = 1;
}
if (DisRemoteFlag == 1)
{
if (Dis_Measure < 2000 && Dis_Measure >= 500)
{
Dis_Remote_Measure = Dis_Measure + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 1.0 / 3.0;
}
else if (Dis_Measure < 500 && Dis_Measure >= 50)
{
Dis_Remote_Measure = Dis_Measure + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 0.1 / 3.0;
}
}
// 返回结果数组
Dis_Remote[0] = DisRemoteFlag;
Dis_Remote[1] = Dis_Remote_Measure;
}
/* 近距离激光测距 */
void GetMeasDISClose(double Dis_Close[2], double TarRVECI[6], double ChaRVECI[6], double MtxECI2VVLH[3][3], double MtxVVLH2Body[3][3], double Euler[3], double R_Plane[2], int TargetFLAG) {
/* 近距离激光测距模拟模块 */
/* 输入量 */
/* TarRVECI 目标惯性系下RV */
/* ChaRVECI 追踪星惯性系下RV */
/* MtxECI2VVLH 追踪星惯性系到轨道系的旋转矩阵Aoi */
/* Euler 姿态角滚俯偏123弧度制 */
/* R_Plane */
/* TargetFLAG 目标选择标志 */
/* 输出量 */
/* Dis_Close 近距离激光测距信息:标志位和距离 */
double Dis_Close_Measure = 0.0;
int DisCloseFlag;
double RVLVLH[6];
double RLVLH[3];
double PointLVLH[3];
double MtxVVLH2LVLH[3][3] = { {0, 0,-1},
{1, 0, 0},
{0,-1, 0} };
// 真实值
double RT[3] = { TarRVECI[0], TarRVECI[1], TarRVECI[2] };
double RC[3] = { ChaRVECI[0], ChaRVECI[1], ChaRVECI[2] };
FunECI2LVLH(RLVLH, RVLVLH, ChaRVECI, TarRVECI);
double R_Co5[3] = { 0 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
R_Co5[i] += MtxECI2VVLH[i][j] * (RT[j] - RC[j]);
}
}
//Euler是偏滚俯这依次需要俯仰和偏航
/*if (R_Co5[0] >= 70)
{
DisCloseFlag = 0;
}
else if (R_Co5[0] < 70 && R_Co5[0] >= 50)
{
Dis_Close_Measure = fabs(R_Co5[0] / (cos(Euler[2] * 3.1415926 / 180.0) * cos(Euler[0] * 3.1415926 / 180.0))) + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 0.02 / 3.0;
}
else if (R_Co5[0] < 50 && R_Co5[0] >= 0)
{
Dis_Close_Measure = fabs(R_Co5[0] / (cos(Euler[2] * 3.1415926 / 180.0) * cos(Euler[0] * 3.1415926 / 180.0))) + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 0.01 / 3.0;
}
else
{
DisCloseFlag = 0;
}*/
if (R_Co5[0] >= 70)
{
DisCloseFlag = 0;
}
else if (R_Co5[0] < 70 && R_Co5[0] >= 50)
{
DisCloseFlag = 1;
Dis_Close_Measure = fabs(R_Co5[0]) + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 0.02 / 3.0;
}
else if (R_Co5[0] < 50 && R_Co5[0] >= 0)
{
DisCloseFlag = 1;
Dis_Close_Measure = fabs(R_Co5[0]) + ((rand() / ((double)RAND_MAX)) * 2.0 - 1.0) * 0.01 / 3.0;
}
else
{
DisCloseFlag = 0;
}
// 判断激光测距是否有效
/*if (TargetFLAG == 1)
{
if (R_Plane[0] < 0)
{
DisCloseFlag = 1;
}
}
else if (TargetFLAG == 2)
{
if (R_Plane[1] > 0)
{
DisCloseFlag = 1;
}
}
else if (TargetFLAG == 0)
{
DisCloseFlag = 1;
}
else
{
DisCloseFlag = 0;
}*/
/************ 2024.12.04 近距离激光是否有效与姿态相关 ************/
double PointBody[3] = { -1, 0, 0 };
double MtxBody2VVLH[3][3], PointVVLH[3], R_Co5_Norm, PointVVLHNorm[3], DeltaPointLVLH[3];
// 计算激光向量在VVLH坐标系下指向
mtxT((double*)MtxBody2VVLH, (double*)MtxVVLH2Body, 3, 3);
mtxMtp((double*)PointVVLH, (double*)MtxBody2VVLH, 3, 3, (double*)PointBody, 3, 1);
// 计算激光向量在LVLH面内投影
R_Co5_Norm = norm(R_Co5, 3);
PointVVLHNorm[0] = PointVVLH[0] * R_Co5_Norm;
PointVVLHNorm[1] = PointVVLH[1] * R_Co5_Norm;
PointVVLHNorm[2] = PointVVLH[2] * R_Co5_Norm;
mtxMtp((double*)PointLVLH, (double*)MtxVVLH2LVLH, 3, 3, (double*)PointVVLHNorm, 3, 1);
mtxSub(DeltaPointLVLH, RLVLH, PointLVLH, 3, 1);
// 判断激光在LVLH面内投影是否落下卫星本体上
// 卫星尺寸 本体1720 * 2400mm 三角长度1370mm 帆板1680 * 6000mm
double a_Body = 1720 / 2 * 1e-3;
double b_Body = 2400 / 2 * 1e-3;
double c_Body = 2200 / 2 * 1e-3;
double a_sanjiao = 1370 * 1e-3;
double a_Left = 6000 / 2 * 1e-3;
double b_Left = 1600 / 2 * 1e-3;
int Flag_Body, Flag_Left;
if ( DisCloseFlag == 1 ) {
// 激光是否落在本体上
if ((fabs(DeltaPointLVLH[2]) <= a_Body) && (fabs(DeltaPointLVLH[0]) <= b_Body)) {
Flag_Body = 1;
Dis_Close_Measure = Dis_Close_Measure - c_Body;
}
else {
Flag_Body = 0;
}
// 激光落在帆板上
if ((fabs(DeltaPointLVLH[2]) >= a_Body) && (fabs(DeltaPointLVLH[2]) <= (a_Body + a_sanjiao + a_Left)) && ((fabs(DeltaPointLVLH[0]) <= b_Left))) {
Flag_Left = 1;
}
else {
Flag_Left = 0;
}
if (Flag_Body == 1 || Flag_Left == 1) {
DisCloseFlag = 1;
}
else {
DisCloseFlag = 0;
}
}
// 返回结果数组
Dis_Close[0] = DisCloseFlag;
Dis_Close[1] = Dis_Close_Measure;
}