1094 lines
37 KiB
C++
1094 lines
37 KiB
C++
|
|
/*******************************************************************************
|
|||
|
|
* 星载硬件仿真系统
|
|||
|
|
*
|
|||
|
|
* 功能:监听串口,解析上层应用指令,调用现有仿真函数生成数据并返回
|
|||
|
|
*
|
|||
|
|
* Created on: 2023-3-9
|
|||
|
|
******************************************************************************/
|
|||
|
|
|
|||
|
|
#include <fcntl.h>
|
|||
|
|
#include <termios.h>
|
|||
|
|
#include <unistd.h>
|
|||
|
|
#include <cstring>
|
|||
|
|
#include <errno.h>
|
|||
|
|
#include <poll.h>
|
|||
|
|
#include <thread>
|
|||
|
|
#include <iostream>
|
|||
|
|
#include <vector>
|
|||
|
|
#include <map>
|
|||
|
|
#include <memory>
|
|||
|
|
#include <atomic>
|
|||
|
|
#include <mutex>
|
|||
|
|
#include <csignal>
|
|||
|
|
#include <chrono>
|
|||
|
|
|
|||
|
|
// 包含现有的硬件仿真头文件
|
|||
|
|
#include "sensor_gnss.h"
|
|||
|
|
#include "sensor_tx2.h"
|
|||
|
|
#include "sensor_optical.h"
|
|||
|
|
#include "sensor_mems.h"
|
|||
|
|
#include "sensor_gyro.h"
|
|||
|
|
#include "sensor_wheel.h"
|
|||
|
|
#include "sensor_star.h"
|
|||
|
|
#include "sensor_thrust.h"
|
|||
|
|
#include "orbit_info.h"
|
|||
|
|
#include "GNCFunction.h"
|
|||
|
|
#include "liblog.h"
|
|||
|
|
|
|||
|
|
using namespace std;
|
|||
|
|
|
|||
|
|
// ==================================== 全局仿真数据结构 ====================================
|
|||
|
|
// 轨道参数
|
|||
|
|
static double TarRVECI[6] = {23621367.9190000, -34592141.8670000, 3657159.91500000,
|
|||
|
|
2548.34575500000, 1736.43994900000, -5.86735000000000};
|
|||
|
|
static double ChaRVECI[6] = {23580586.0537251, -34621080.4670552, 3658341.81666531,
|
|||
|
|
2550.44489430168, 1733.51288095298, -5.46126675290179};
|
|||
|
|
static double AttiVelECI[3] = {0.0, 0.0, 0.0};
|
|||
|
|
static double EulerVVLH[3] = {0.0, 0.0, 0.0};
|
|||
|
|
static double MtxVVLH2Body[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
|
|||
|
|
static double MtxECI2VVLH[3][3] = {{0.8266, 0.5628, -0.0018},
|
|||
|
|
{0.0474, -0.0729, -0.9962},
|
|||
|
|
{-0.5608, 0.8234, -0.087}};
|
|||
|
|
static double QuatECI[4] = {1.0, 0.0, 0.0, 0.0};
|
|||
|
|
static double mjd = 60776.00480324;
|
|||
|
|
static double Epoch2017 = 261130015.0;
|
|||
|
|
|
|||
|
|
// 光电/TX2相关参数
|
|||
|
|
static int TargetFLAG = 0; // 1:左帆板, 0:本体
|
|||
|
|
static double R_Plane[2] = {0.0, 0.0};
|
|||
|
|
static double LOS_Remote[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|||
|
|
|
|||
|
|
// 硬件状态
|
|||
|
|
struct HardwareStatus {
|
|||
|
|
atomic<uint8_t> gnss_onoff{1};
|
|||
|
|
atomic<uint8_t> star_onoff{1};
|
|||
|
|
atomic<uint8_t> gyro_onoff{1};
|
|||
|
|
atomic<uint8_t> mems_onoff{1};
|
|||
|
|
atomic<uint8_t> wheel_onoff{1};
|
|||
|
|
atomic<uint8_t> optical_onoff{1};
|
|||
|
|
atomic<uint8_t> carried_status{0}; // 0:运载模式, 2:独立模式
|
|||
|
|
|
|||
|
|
// 动量轮
|
|||
|
|
double WheelTorqueBody[3] = {0.0, 0.0, 0.0};
|
|||
|
|
double WheelAM[3] = {0.0, 0.0, 0.0};
|
|||
|
|
double CmdWheel[3] = {0.0, 0.0, 0.0};
|
|||
|
|
|
|||
|
|
// 推进
|
|||
|
|
double ThrustTorque[3] = {0.0, 0.0, 0.0};
|
|||
|
|
double SatMtxI[3][3] = {{10.0, 0.0, 0.0}, {0.0, 10.0, 0.0}, {0.0, 0.0, 10.0}};
|
|||
|
|
double ThrustForce[3] = {0.0, 0.0, 0.0};
|
|||
|
|
double CmdJetPWM[12] = {0.0};
|
|||
|
|
double JetPWMPlan[12] = {0.0};
|
|||
|
|
double SatMass = 100.0; // kg
|
|||
|
|
|
|||
|
|
// 载荷
|
|||
|
|
atomic<int> LaunchFlag1{0};
|
|||
|
|
atomic<int> LaunchFlag2{0};
|
|||
|
|
atomic<int> LaunchAlreadyFlag1{0};
|
|||
|
|
atomic<int> LaunchAlreadyFlag2{0};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 数据帧缓冲区
|
|||
|
|
static uint8_t gnss_frame[GPS_Hk_FRAME_LENGTH];
|
|||
|
|
static uint8_t xgd_frame[OPTIC_FRAME_LENGTH];
|
|||
|
|
static uint8_t tx2_frame[VISION_Info_Length];
|
|||
|
|
static uint8_t wheel_frame[WHEEL_FRAME_LENGTH];
|
|||
|
|
static uint8_t gyro_frame[GYRO_FRAME_LENGTH];
|
|||
|
|
static uint8_t mems_frame[MEMS_FRAME_LENGTH];
|
|||
|
|
static uint8_t star_frame[CAK_TLM_1_Info_Length];
|
|||
|
|
static uint8_t photo_frame[249];
|
|||
|
|
static uint8_t orbit_frame[89];
|
|||
|
|
|
|||
|
|
// 全局硬件状态
|
|||
|
|
static HardwareStatus hw_status;
|
|||
|
|
|
|||
|
|
// 全局串口管理器
|
|||
|
|
static map<string, unique_ptr<class SerialPort>> serial_ports;
|
|||
|
|
|
|||
|
|
// ==================================== 串口管理器类 ====================================
|
|||
|
|
class SerialPort {
|
|||
|
|
private:
|
|||
|
|
int fd = -1;
|
|||
|
|
string device_type; // 设备类型,如 "GNSS", "GYRO"等
|
|||
|
|
string device_path;
|
|||
|
|
atomic<bool> running{false};
|
|||
|
|
thread read_thread;
|
|||
|
|
mutex write_mutex;
|
|||
|
|
|
|||
|
|
// 协议解析缓冲区
|
|||
|
|
uint8_t buffer[1024];
|
|||
|
|
uint16_t buffer_index = 0;
|
|||
|
|
|
|||
|
|
public:
|
|||
|
|
SerialPort(const string& type, const string& path)
|
|||
|
|
: device_type(type), device_path(path) {}
|
|||
|
|
|
|||
|
|
~SerialPort() {
|
|||
|
|
stop();
|
|||
|
|
close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool open(int baudrate = 115200) {
|
|||
|
|
// 打开串口设备
|
|||
|
|
fd = ::open(device_path.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
|
|||
|
|
if (fd < 0) {
|
|||
|
|
spdlog::error("无法打开串口 {}: {}", device_path, strerror(errno));
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 配置串口参数
|
|||
|
|
struct termios options;
|
|||
|
|
if (tcgetattr(fd, &options) != 0) {
|
|||
|
|
spdlog::error("获取串口属性失败: {}", strerror(errno));
|
|||
|
|
::close(fd);
|
|||
|
|
fd = -1;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置波特率
|
|||
|
|
speed_t baud;
|
|||
|
|
switch (baudrate) {
|
|||
|
|
case 9600: baud = B9600; break;
|
|||
|
|
case 19200: baud = B19200; break;
|
|||
|
|
case 38400: baud = B38400; break;
|
|||
|
|
case 57600: baud = B57600; break;
|
|||
|
|
case 115200: baud = B115200; break;
|
|||
|
|
case 230400: baud = B230400; break;
|
|||
|
|
case 460800: baud = B460800; break;
|
|||
|
|
case 921600: baud = B921600; break;
|
|||
|
|
default:
|
|||
|
|
spdlog::error("不支持的波特率: {}", baudrate);
|
|||
|
|
::close(fd);
|
|||
|
|
fd = -1;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
cfsetispeed(&options, baud);
|
|||
|
|
cfsetospeed(&options, baud);
|
|||
|
|
|
|||
|
|
// 8位数据,无校验,1位停止位
|
|||
|
|
options.c_cflag &= ~CSIZE;
|
|||
|
|
options.c_cflag |= CS8;
|
|||
|
|
options.c_cflag &= ~PARENB;
|
|||
|
|
options.c_cflag &= ~CSTOPB;
|
|||
|
|
options.c_cflag &= ~CRTSCTS; // 无硬件流控制
|
|||
|
|
|
|||
|
|
// 原始模式
|
|||
|
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
|||
|
|
options.c_oflag &= ~OPOST;
|
|||
|
|
|
|||
|
|
// 设置读取超时
|
|||
|
|
options.c_cc[VMIN] = 0;
|
|||
|
|
options.c_cc[VTIME] = 10; // 1秒超时
|
|||
|
|
|
|||
|
|
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
|||
|
|
spdlog::error("设置串口属性失败: {}", strerror(errno));
|
|||
|
|
::close(fd);
|
|||
|
|
fd = -1;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清除缓冲区
|
|||
|
|
tcflush(fd, TCIOFLUSH);
|
|||
|
|
|
|||
|
|
spdlog::info("串口 {} ({}) 已打开,波特率: {}", device_type, device_path, baudrate);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void close() {
|
|||
|
|
if (fd >= 0) {
|
|||
|
|
::close(fd);
|
|||
|
|
fd = -1;
|
|||
|
|
spdlog::info("串口 {} 已关闭", device_type);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void start() {
|
|||
|
|
if (fd < 0 || running) return;
|
|||
|
|
|
|||
|
|
running = true;
|
|||
|
|
read_thread = thread(&SerialPort::read_loop, this);
|
|||
|
|
spdlog::info("串口 {} 读取线程已启动", device_type);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void stop() {
|
|||
|
|
running = false;
|
|||
|
|
if (read_thread.joinable()) {
|
|||
|
|
read_thread.join();
|
|||
|
|
}
|
|||
|
|
spdlog::info("串口 {} 读取线程已停止", device_type);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ssize_t write(const uint8_t* data, size_t len) {
|
|||
|
|
lock_guard<mutex> lock(write_mutex);
|
|||
|
|
|
|||
|
|
if (fd < 0) {
|
|||
|
|
spdlog::error("串口 {} 未打开,无法写入", device_type);
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ssize_t written = ::write(fd, data, len);
|
|||
|
|
if (written < 0) {
|
|||
|
|
spdlog::error("串口 {} 写入失败: {}", device_type, strerror(errno));
|
|||
|
|
} else if (written != (ssize_t)len) {
|
|||
|
|
spdlog::warn("串口 {} 部分写入: {}/{} 字节", device_type, written, len);
|
|||
|
|
} else {
|
|||
|
|
spdlog::debug("串口 {} 写入 {} 字节成功", device_type, len);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return written;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const string& get_type() const { return device_type; }
|
|||
|
|
const string& get_path() const { return device_path; }
|
|||
|
|
bool is_running() const { return running; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
void read_loop() {
|
|||
|
|
uint8_t read_buffer[1024];
|
|||
|
|
|
|||
|
|
spdlog::debug("串口 {} 读取线程开始", device_type);
|
|||
|
|
|
|||
|
|
while (running) {
|
|||
|
|
// 使用poll检查是否有数据可读
|
|||
|
|
struct pollfd pfd;
|
|||
|
|
pfd.fd = fd;
|
|||
|
|
pfd.events = POLLIN;
|
|||
|
|
|
|||
|
|
int ret = poll(&pfd, 1, 100); // 100ms超时
|
|||
|
|
if (ret < 0) {
|
|||
|
|
spdlog::error("串口 {} poll失败: {}", device_type, strerror(errno));
|
|||
|
|
break;
|
|||
|
|
} else if (ret == 0) {
|
|||
|
|
continue; // 超时,继续循环
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (pfd.revents & POLLIN) {
|
|||
|
|
ssize_t n = read(fd, read_buffer, sizeof(read_buffer));
|
|||
|
|
if (n > 0) {
|
|||
|
|
process_serial_data(read_buffer, n);
|
|||
|
|
} else if (n < 0 && errno != EAGAIN) {
|
|||
|
|
spdlog::error("读取串口 {} 失败: {}", device_type, strerror(errno));
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
spdlog::debug("串口 {} 读取线程结束", device_type);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_serial_data(const uint8_t* data, size_t len) {
|
|||
|
|
spdlog::debug("串口 {} 接收到 {} 字节数据", device_type, len);
|
|||
|
|
|
|||
|
|
// 逐个字节处理数据
|
|||
|
|
for (size_t i = 0; i < len; i++) {
|
|||
|
|
uint8_t value = data[i];
|
|||
|
|
|
|||
|
|
// 根据设备类型调用相应的处理函数
|
|||
|
|
if (device_type == "GNSS") {
|
|||
|
|
process_gnss_data(value);
|
|||
|
|
} else if (device_type == "GYRO") {
|
|||
|
|
process_gyro_data(value);
|
|||
|
|
} else if (device_type == "MEMS") {
|
|||
|
|
process_mems_data(value);
|
|||
|
|
} else if (device_type == "STAR1") {
|
|||
|
|
process_star_1_data(value);
|
|||
|
|
} else if (device_type == "STAR2") {
|
|||
|
|
process_star_2_data(value);
|
|||
|
|
} else if (device_type == "WHEEL1") {
|
|||
|
|
process_wheel_1_data(value);
|
|||
|
|
} else if (device_type == "WHEEL2") {
|
|||
|
|
process_wheel_2_data(value);
|
|||
|
|
} else if (device_type == "WHEEL3") {
|
|||
|
|
process_wheel_3_data(value);
|
|||
|
|
} else if (device_type == "OPTICAL") {
|
|||
|
|
process_optical_data(value);
|
|||
|
|
} else if (device_type == "VISION") {
|
|||
|
|
process_vision_data(value);
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("未知设备类型: {}", device_type);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================================== 协议解析函数 ====================================
|
|||
|
|
void process_gnss_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0xEB) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0x90) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 3;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("GNSS帧头错误: 0xEB 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 3:
|
|||
|
|
if(data == 0x09) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 4;
|
|||
|
|
} else {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 4:
|
|||
|
|
if(data == 0xD7) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
spdlog::info("GNSS数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理GNSS指令并生成响应
|
|||
|
|
handle_gnss_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("GNSS帧尾错误: 0x{:02X}", data);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_gyro_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0x55) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0x68) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
spdlog::info("GYRO数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理GYRO指令并生成响应
|
|||
|
|
handle_gyro_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("GYRO帧头错误: 0x55 0x{:02X}", data);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_mems_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0x55) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0x68) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
spdlog::info("MEMS数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理MEMS指令并生成响应
|
|||
|
|
handle_mems_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("MEMS帧头错误: 0x55 0x{:02X}", data);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_star_1_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0x74) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0xA1) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 3;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("STAR1帧头错误: 0x74 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 3:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 5) {
|
|||
|
|
if(buffer[4] == 0x15) {
|
|||
|
|
spdlog::info("STAR-1数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理STAR-1指令并生成响应
|
|||
|
|
handle_star_1_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("STAR-1帧尾错误: 0x{:02X}", buffer[4]);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_star_2_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0x74) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0xA1) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 3;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("STAR2帧头错误: 0x74 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 3:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 5) {
|
|||
|
|
if(buffer[4] == 0x15) {
|
|||
|
|
spdlog::info("STAR-2数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理STAR-2指令并生成响应
|
|||
|
|
handle_star_2_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("STAR-2帧尾错误: 0x{:02X}", buffer[4]);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_wheel_1_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
static uint8_t checksum = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if((data == 0x58) || (data == 0x59)) {
|
|||
|
|
checksum = 0;
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
checksum += data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 11) {
|
|||
|
|
if(checksum == data) {
|
|||
|
|
spdlog::info("WHEEL-1数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理WHEEL-1指令并生成响应
|
|||
|
|
handle_wheel_1_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("WHEEL-1校验和错误");
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
} else {
|
|||
|
|
checksum += data;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_wheel_2_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
static uint8_t checksum = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if((data == 0x58) || (data == 0x59)) {
|
|||
|
|
checksum = 0;
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
checksum += data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 11) {
|
|||
|
|
if(checksum == data) {
|
|||
|
|
spdlog::info("WHEEL-2数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理WHEEL-2指令并生成响应
|
|||
|
|
handle_wheel_2_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("WHEEL-2校验和错误");
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
} else {
|
|||
|
|
checksum += data;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_wheel_3_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
static uint8_t checksum = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if((data == 0x58) || (data == 0x59)) {
|
|||
|
|
checksum = 0;
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
checksum += data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 11) {
|
|||
|
|
if(checksum == data) {
|
|||
|
|
spdlog::info("WHEEL-3数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理WHEEL-3指令并生成响应
|
|||
|
|
handle_wheel_3_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("WHEEL-3校验和错误");
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
} else {
|
|||
|
|
checksum += data;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
checksum = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_optical_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0xCD) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else if(data == 0xEB) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 12;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0x90) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 3;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("OPTICAL帧头错误: 0xCD 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 3:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 5) {
|
|||
|
|
if(buffer[4] == 0xFF) {
|
|||
|
|
spdlog::info("OPTICAL数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理OPTICAL指令并生成响应
|
|||
|
|
handle_optical_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("OPTICAL帧尾错误: 0x{:02X}", buffer[4]);
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 12:
|
|||
|
|
if(data == 0x90) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 13;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("OPTICAL扩展帧头错误: 0xEB 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 13:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == 8) {
|
|||
|
|
uint8_t checksum = 0;
|
|||
|
|
for(int kc = 0; kc < rec_count - 1; kc++) {
|
|||
|
|
checksum += buffer[kc];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(buffer[7] == checksum) {
|
|||
|
|
spdlog::info("OPTICAL带参指令接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理OPTICAL带参指令
|
|||
|
|
handle_optical_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("OPTICAL带参指令校验错误");
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void process_vision_data(uint8_t data) {
|
|||
|
|
static uint8_t rec_step = 1;
|
|||
|
|
static uint16_t rec_count = 0;
|
|||
|
|
static uint16_t frame_len = 0;
|
|||
|
|
|
|||
|
|
switch(rec_step) {
|
|||
|
|
case 1:
|
|||
|
|
if(data == 0xEB) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 2;
|
|||
|
|
} else {
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 2:
|
|||
|
|
if(data == 0x90) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 3;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("VISION帧头错误: 0xEB 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 3:
|
|||
|
|
if((data == 0x1E) || (data == 0x0F)) {
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 4;
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("VISION指令类型错误: 0x{:02X}", data);
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 4:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
rec_step = 5;
|
|||
|
|
break;
|
|||
|
|
case 5:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
frame_len = (buffer[3] * 256) + buffer[4];
|
|||
|
|
rec_step = 6;
|
|||
|
|
break;
|
|||
|
|
case 6:
|
|||
|
|
buffer[rec_count++] = data;
|
|||
|
|
if(rec_count == (frame_len + 6)) {
|
|||
|
|
uint8_t checksum = 0;
|
|||
|
|
for(int kc = 2; kc < rec_count - 1; kc++) {
|
|||
|
|
checksum += buffer[kc];
|
|||
|
|
}
|
|||
|
|
if(buffer[rec_count - 1] == checksum) {
|
|||
|
|
spdlog::info("VISION数据接收完成, 长度: {}", rec_count);
|
|||
|
|
// 处理VISION指令并生成响应
|
|||
|
|
handle_vision_command();
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("VISION校验和错误");
|
|||
|
|
}
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
frame_len = 0;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
rec_step = 1;
|
|||
|
|
rec_count = 0;
|
|||
|
|
frame_len = 0;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================================== 命令处理函数 ====================================
|
|||
|
|
void handle_gnss_command() {
|
|||
|
|
if (!hw_status.gnss_onoff) {
|
|||
|
|
spdlog::info("GNSS功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的GNSS数据生成函数
|
|||
|
|
generate_gnss_frame(gnss_frame, ChaRVECI, mjd, Epoch2017);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(gnss_frame, GPS_Hk_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送GNSS响应数据,长度: {}", GPS_Hk_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_gyro_command() {
|
|||
|
|
if (!hw_status.gyro_onoff) {
|
|||
|
|
spdlog::info("GYRO功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的GYRO数据生成函数
|
|||
|
|
generate_gyro_frame(gyro_frame, AttiVelECI);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(gyro_frame, GYRO_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送GYRO响应数据,长度: {}", GYRO_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_mems_command() {
|
|||
|
|
if (!hw_status.mems_onoff) {
|
|||
|
|
spdlog::info("MEMS功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的MEMS数据生成函数
|
|||
|
|
generate_mems_frame(mems_frame, AttiVelECI);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(mems_frame, MEMS_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送MEMS响应数据,长度: {}", MEMS_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_star_1_command() {
|
|||
|
|
if (!hw_status.star_onoff) {
|
|||
|
|
spdlog::info("STAR-1功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取四元数
|
|||
|
|
get_orbit_Q(QuatECI);
|
|||
|
|
|
|||
|
|
// 直接调用现有的STAR-1数据生成函数
|
|||
|
|
generate_star_1_frame(star_frame, QuatECI, AttiVelECI);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(star_frame, CAK_TLM_1_Info_Length);
|
|||
|
|
spdlog::info("已发送STAR-1响应数据,长度: {}", CAK_TLM_1_Info_Length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_star_2_command() {
|
|||
|
|
if (!hw_status.star_onoff) {
|
|||
|
|
spdlog::info("STAR-2功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取四元数
|
|||
|
|
get_orbit_Q(QuatECI);
|
|||
|
|
|
|||
|
|
// 直接调用现有的STAR-2数据生成函数
|
|||
|
|
generate_star_2_frame(star_frame, QuatECI, AttiVelECI);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(star_frame, CAK_TLM_1_Info_Length);
|
|||
|
|
spdlog::info("已发送STAR-2响应数据,长度: {}", CAK_TLM_1_Info_Length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_wheel_1_command() {
|
|||
|
|
if (!hw_status.wheel_onoff) {
|
|||
|
|
spdlog::info("WHEEL-1功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析转速命令(从buffer中解析)
|
|||
|
|
if (buffer_index >= 5) {
|
|||
|
|
hw_status.CmdWheel[0] = cal_message_para(buffer[1], buffer[2], buffer[3], buffer[4], WHEEL_EXP);
|
|||
|
|
spdlog::info("WHEEL-1转速命令: {:.2f} rpm", hw_status.CmdWheel[0]);
|
|||
|
|
|
|||
|
|
// 更新动量轮仿真数据
|
|||
|
|
sensor_WheelMeas(hw_status.WheelTorqueBody, hw_status.WheelAM, hw_status.CmdWheel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的WHEEL数据生成函数
|
|||
|
|
generate_wheel_frame(wheel_frame, hw_status.CmdWheel[0]);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(wheel_frame, WHEEL_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送WHEEL-1响应数据,长度: {}", WHEEL_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_wheel_2_command() {
|
|||
|
|
if (!hw_status.wheel_onoff) {
|
|||
|
|
spdlog::info("WHEEL-2功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析转速命令
|
|||
|
|
if (buffer_index >= 5) {
|
|||
|
|
hw_status.CmdWheel[1] = cal_message_para(buffer[1], buffer[2], buffer[3], buffer[4], WHEEL_EXP);
|
|||
|
|
spdlog::info("WHEEL-2转速命令: {:.2f} rpm", hw_status.CmdWheel[1]);
|
|||
|
|
|
|||
|
|
// 更新动量轮仿真数据
|
|||
|
|
sensor_WheelMeas(hw_status.WheelTorqueBody, hw_status.WheelAM, hw_status.CmdWheel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的WHEEL数据生成函数
|
|||
|
|
generate_wheel_frame(wheel_frame, hw_status.CmdWheel[1]);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(wheel_frame, WHEEL_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送WHEEL-2响应数据,长度: {}", WHEEL_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_wheel_3_command() {
|
|||
|
|
if (!hw_status.wheel_onoff) {
|
|||
|
|
spdlog::info("WHEEL-3功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析转速命令
|
|||
|
|
if (buffer_index >= 5) {
|
|||
|
|
hw_status.CmdWheel[2] = cal_message_para(buffer[1], buffer[2], buffer[3], buffer[4], WHEEL_EXP);
|
|||
|
|
spdlog::info("WHEEL-3转速命令: {:.2f} rpm", hw_status.CmdWheel[2]);
|
|||
|
|
|
|||
|
|
// 更新动量轮仿真数据
|
|||
|
|
sensor_WheelMeas(hw_status.WheelTorqueBody, hw_status.WheelAM, hw_status.CmdWheel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接调用现有的WHEEL数据生成函数
|
|||
|
|
generate_wheel_frame(wheel_frame, hw_status.CmdWheel[2]);
|
|||
|
|
|
|||
|
|
// 发送响应
|
|||
|
|
write(wheel_frame, WHEEL_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送WHEEL-3响应数据,长度: {}", WHEEL_FRAME_LENGTH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_optical_command() {
|
|||
|
|
if (!hw_status.optical_onoff) {
|
|||
|
|
spdlog::info("OPTICAL功能已关闭,不生成响应");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 根据指令类型处理
|
|||
|
|
if (buffer_index >= 4) {
|
|||
|
|
if (buffer[2] == 0x06 && buffer[3] == 0x00) {
|
|||
|
|
// 遥测指令 - 直接调用现有的光电数据生成函数
|
|||
|
|
generate_xgd_frame(xgd_frame, TarRVECI, ChaRVECI, MtxECI2VVLH,
|
|||
|
|
MtxVVLH2Body, LOS_Remote, EulerVVLH, R_Plane, TargetFLAG);
|
|||
|
|
write(xgd_frame, OPTIC_FRAME_LENGTH);
|
|||
|
|
spdlog::info("已发送OPTICAL遥测数据,长度: {}", OPTIC_FRAME_LENGTH);
|
|||
|
|
} else if ((buffer[2] == 0x07 && buffer[3] == 0x01) ||
|
|||
|
|
(buffer[2] == 0x08 && buffer[3] == 0x01)) {
|
|||
|
|
// 图像指令 - 直接调用现有的图像生成函数
|
|||
|
|
generate_photo_frame(photo_frame);
|
|||
|
|
write(photo_frame, 249);
|
|||
|
|
spdlog::info("已发送OPTICAL图像数据,长度: 249");
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("未知的OPTICAL指令: 0x{:02X} 0x{:02X}", buffer[2], buffer[3]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void handle_vision_command() {
|
|||
|
|
if (buffer_index >= 3 && buffer[2] == 0x0F) {
|
|||
|
|
// 遥测指令 - 直接调用现有的TX2数据生成函数
|
|||
|
|
generate_tx2_frame(tx2_frame, LOS_Remote, R_Plane, TarRVECI, ChaRVECI,
|
|||
|
|
MtxVVLH2Body, MtxECI2VVLH, TargetFLAG);
|
|||
|
|
write(tx2_frame, VISION_Info_Length);
|
|||
|
|
spdlog::info("已发送VISION遥测数据,长度: {}", VISION_Info_Length);
|
|||
|
|
} else {
|
|||
|
|
spdlog::warn("未知的VISION指令类型: 0x{:02X}", buffer[2]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ==================================== 主初始化函数 ====================================
|
|||
|
|
void initialize_simulation_system() {
|
|||
|
|
cout << "=== 星载硬件仿真系统初始化 ===" << endl;
|
|||
|
|
cout << "初始化Linux串口仿真系统..." << endl;
|
|||
|
|
|
|||
|
|
// 初始化轨道信息
|
|||
|
|
orbit_info_initz("./settings/setting.json");
|
|||
|
|
|
|||
|
|
uint8_t dummy_orbit_frame[89] = {0};
|
|||
|
|
|
|||
|
|
set_orbit_info(dummy_orbit_frame, AttiVelECI, EulerVVLH, MtxVVLH2Body, MtxECI2VVLH);
|
|||
|
|
|
|||
|
|
spdlog::info("初始化后角速度: [{:.6f}, {:.6f}, {:.6f}] 弧度/秒",
|
|||
|
|
AttiVelECI[0], AttiVelECI[1], AttiVelECI[2]);
|
|||
|
|
spdlog::info("转换为度/秒: [{:.6f}, {:.6f}, {:.6f}] 度/秒",
|
|||
|
|
AttiVelECI[0] * 180.0 / M_PI,
|
|||
|
|
AttiVelECI[1] * 180.0 / M_PI,
|
|||
|
|
AttiVelECI[2] * 180.0 / M_PI);
|
|||
|
|
|
|||
|
|
// 获取四元数
|
|||
|
|
get_orbit_Q(QuatECI);
|
|||
|
|
|
|||
|
|
// 串口设备映射配置
|
|||
|
|
cout << "1. 配置串口设备..." << endl;
|
|||
|
|
map<string, string> port_config = {
|
|||
|
|
{"GNSS", "/dev/tnt0"}, // GNSS接收机
|
|||
|
|
{"GYRO", "/dev/tnt2"}, // 陀螺仪
|
|||
|
|
{"MEMS", "/dev/tnt4"}, // MEMS加速度计
|
|||
|
|
{"STAR1", "/dev/tnt6"}, // 星敏感器1
|
|||
|
|
{"STAR2", "/dev/tnt8"}, // 星敏感器2
|
|||
|
|
{"WHEEL1", "/dev/tnt10"}, // 动量轮1
|
|||
|
|
{"WHEEL2", "/dev/tnt12"}, // 动量轮2
|
|||
|
|
{"WHEEL3", "/dev/tnt14"}, // 动量轮3
|
|||
|
|
{"OPTICAL", "/dev/tnt16"}, // 小光电
|
|||
|
|
{"VISION", "/dev/tnt18"} // TX2视觉
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 打开所有串口设备
|
|||
|
|
cout << "2. 开始打开串口设备..." << endl;
|
|||
|
|
int opened_ports = 0;
|
|||
|
|
for (const auto& config : port_config) {
|
|||
|
|
cout << " 尝试打开: " << config.first << " -> " << config.second << "... ";
|
|||
|
|
cout.flush();
|
|||
|
|
|
|||
|
|
auto port = make_unique<SerialPort>(config.first, config.second);
|
|||
|
|
|
|||
|
|
if (port->open(115200)) {
|
|||
|
|
port->start();
|
|||
|
|
serial_ports[config.first] = move(port);
|
|||
|
|
opened_ports++;
|
|||
|
|
cout << "✅ 成功" << endl;
|
|||
|
|
} else {
|
|||
|
|
cout << "❌ 失败" << endl;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cout << "===============================================" << endl;
|
|||
|
|
cout << "✅ 星载硬件仿真系统初始化完成" << endl;
|
|||
|
|
cout << " 成功打开 " << opened_ports << "/" << port_config.size() << " 个串口设备" << endl;
|
|||
|
|
cout << " 系统已就绪,开始监听串口指令..." << endl;
|
|||
|
|
cout << "=== 初始化完成 ===" << endl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================================== 清理函数 ====================================
|
|||
|
|
void cleanup_simulation_system() {
|
|||
|
|
spdlog::info("清理仿真系统资源...");
|
|||
|
|
for (auto& pair : serial_ports) {
|
|||
|
|
spdlog::info("关闭串口: {}", pair.first);
|
|||
|
|
pair.second->stop();
|
|||
|
|
pair.second->close();
|
|||
|
|
}
|
|||
|
|
serial_ports.clear();
|
|||
|
|
spdlog::info("仿真系统资源清理完成");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================================== 主函数 ====================================
|
|||
|
|
int main(int argc, char** argv) {
|
|||
|
|
// 初始化日志系统
|
|||
|
|
spdlog_initz("./settings/setting.json");
|
|||
|
|
|
|||
|
|
cout << "**************************************************" << endl;
|
|||
|
|
cout << "* 星载硬件仿真系统 - 单程序版本 *" << endl;
|
|||
|
|
cout << "* *" << endl;
|
|||
|
|
cout << "* 功能:监听串口 -> 解析指令 -> 调用现有仿真函数*" << endl;
|
|||
|
|
cout << "* *" << endl;
|
|||
|
|
cout << "**************************************************" << endl;
|
|||
|
|
cout << endl;
|
|||
|
|
|
|||
|
|
// 初始化仿真系统
|
|||
|
|
initialize_simulation_system();
|
|||
|
|
|
|||
|
|
// 注册信号处理
|
|||
|
|
std::signal(SIGINT, [](int) {
|
|||
|
|
cout << "\n收到中断信号,正在关闭系统..." << endl;
|
|||
|
|
cleanup_simulation_system();
|
|||
|
|
exit(0);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
std::signal(SIGTERM, [](int) {
|
|||
|
|
cout << "\n收到终止信号,正在关闭系统..." << endl;
|
|||
|
|
cleanup_simulation_system();
|
|||
|
|
exit(0);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 主循环
|
|||
|
|
while (true) {
|
|||
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|