feat: 更新 TLE 数据处理和示例,完善卫星轨道参数解析逻辑
Some checks are pending
/ lint-build-and-check (push) Successful in 2m35s
/ depcheck (push) Successful in 2m38s
/ playwright (push) Waiting to run
/ surge (push) Successful in 2m33s
/ build-and-deploy-to-vercel (push) Successful in 3m10s

This commit is contained in:
严浩
2025-03-12 19:02:11 +08:00
parent 447907aa7c
commit 8b702826b3
2 changed files with 166 additions and 62 deletions

View File

@ -18,3 +18,10 @@
- https://blog.csdn.net/m0_54849806/article/details/126070809
- https://juejin.cn/post/6969838266182795278
- https://blog.csdn.net/CSDNqinzhike/article/details/139587028
## TLE
- https://en.wikipedia.org/wiki/Two-line_element_set#Format
- https://grok.com/share/bGVnYWN5_f2c51def-f941-4c75-b020-e76534ba5c5e
- https://celestrak.org/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=tle
- https://celestrak.org/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=json

View File

@ -1,109 +1,206 @@
// eslint-disable no-unused-vars
/* eslint-disable perfectionist/sort-objects */
// eslint-disable no-unused-vars
import { twoline2satrec } from 'satellite.js';
// https://en.wikipedia.org/wiki/Two-line_element_set#Format
// https://celestrak.org/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=tle
const longstr1 = `1 63157U 25045A 25069.35219743 .00000545 -65692-6 00000+0 0 9992`;
const longstr2 = `2 63157 19.0062 64.6364 7327661 179.7218 141.4162 2.26206155 28`;
const longstr1 = `1 62949U 25029B 25070.91668981 .00039463 00000+0 99294-3 0 9990`;
const longstr2 = `2 62949 53.1596 120.9032 0001355 101.1211 35.9659 15.39574303 5809`;
export const TLE_LIST = [
/* `ISS (ZARYA)
1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927
2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537`, */
`2025-045A
`STARLINK-32857
${longstr1}
${longstr2}`,
`STARLINK-11371 [DTC]
1 62879U 25024A 25062.93300820 .00003305 00000+0 21841-4 0 9995
2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`,
`STARLINK-32915
1 63152U 25043W 25070.91668981 .00451203 87802-4 12020-2 0 9994
2 63152 43.0011 279.4620 0003944 269.6759 119.1758 15.93738994 2341`,
`STARLINK-32915 [测修改1]
1 00000U 00000W 25070.91668981 .00000000 00000-0 00000-0 0 0000
2 00000 43.0011 279.4620 0003944 269.6759 119.1758 15.93738994 0000`,
];
// https://celestrak.org/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=json
export const TLE_LIST_JSON = [
{
OBJECT_NAME: '2025-045A',
OBJECT_ID: '2025-045A',
EPOCH: '2025-03-10T08:27:09.857952',
MEAN_MOTION: 2.26206155, // 平均运动Mean Motion单位是圈/天,表示卫星每天绕地球运行的圈数,此处约为 2.26 圈(周期约 10.6 小时)。
ECCENTRICITY: 0.7327661, // 偏心率Eccentricity无单位科学记数法为 0.7327661,表示轨道是一个高度椭圆的形状(接近 1 表示非常扁平)。
INCLINATION: 19.0062, // 轨道倾角Inclination单位是度表示轨道平面与地球赤道的夹角。此处为 19.0062°,属于低倾角轨道。
RA_OF_ASC_NODE: 64.6364, // 升交点赤经RAAN, Right Ascension of Ascending Node单位是度表示轨道平面在赤道上的交叉点位置。
ARG_OF_PERICENTER: 179.7218, // 近地点角距Argument of Perigee单位是度表示近地点相对于升交点的角度。
MEAN_ANOMALY: 141.4162, // 平近点角Mean Anomaly单位是度表示卫星在轨道上的位置。
EPHEMERIS_TYPE: 0, // 轨道模型类型(通常为 0表示 SGP4 模型)。
CLASSIFICATION_TYPE: 'U', // U 表示未分类(可能是临时编号)。
NORAD_CAT_ID: 63157, // NORAD
ELEMENT_SET_NO: 999, // 校验码或元素集编号,表示这是第 999 次更新的 TLE 数据。
REV_AT_EPOCH: 2, // Checksum 校验和
BSTAR: 0, // 轨道模型类型0=SGP4模型
MEAN_MOTION_DOT: 5.45e-6, // 0.00000545 // 平均运动的一阶导数(每天的轨道变化率),单位是圈/天²,这里非常小,表示轨道衰减缓慢
CLASSIFICATION_TYPE: 'U', // U 表示未分类(可能是临时编号)
ECCENTRICITY: 0.732_766_1, // 偏心率Eccentricity无单位科学记数法为 0.7327661,表示轨道是一个高度椭圆的形状(接近 1 表示非常扁平)。
ELEMENT_SET_NO: 999, // 校验码或元素集编号,表示这是第 999 次更新的 TLE 数据。
EPHEMERIS_TYPE: 0, // 轨道模型类型(通常为 0表示 SGP4 模型)。
EPOCH: '2025-03-10T08:27:09.857952',
INCLINATION: 19.0062, // 轨道倾角Inclination单位是度表示轨道平面与地球赤道的夹角。此处为 19.0062°,属于低倾角轨道。
MEAN_ANOMALY: 141.4162, // 平近点角Mean Anomaly单位是度表示卫星在轨道上的位置。
MEAN_MOTION: 2.262_061_55, // 平均运动Mean Motion单位是圈/天,表示卫星每天绕地球运行的圈数,此处约为 2.26 圈(周期约 10.6 小时)。
MEAN_MOTION_DDOT: -6.5692e-7, // 平均运动的二阶导数(科学记数法:-6.5692 × 10⁻⁶表示轨道受摄动如大气阻力的加速度变化。
MEAN_MOTION_DOT: 5.45e-6, // 0.00000545 // 平均运动的一阶导数(每天的轨道变化率),单位是圈/天²,这里非常小,表示轨道衰减缓慢。
NORAD_CAT_ID: 63_157, // NORAD
OBJECT_ID: '2025-045A',
OBJECT_NAME: '2025-045A',
RA_OF_ASC_NODE: 64.6364, // 升交点赤经RAAN, Right Ascension of Ascending Node单位是度表示轨道平面在赤道上的交叉点位置。
REV_AT_EPOCH: 2, // Checksum 校验和
},
];
// 为了twoline2satrec函数需要哪些参数
// https://github.com/shashwatak/satellite-js/blob/0e921026d20b75f42553366994af70eed63a304f/src/io.js#L62
function twoline2satrecFake(longstr1: string, longstr2: string) {
console.group('twoline2satrec');
console.group('twoline2satrecFake');
const satrec = {} as Record<string, any>;
satrec.error = 0;
satrec.satnum = longstr1.substring(2, 7);
console.debug(`longstr1.substring(2, 7) :>> `, `"${longstr1.substring(2, 7)}"`);
satrec.satnum = longstr1.slice(2, 7);
console.debug(`longstr1.substring(2, 7) :>>`, `"${longstr1.slice(2, 7)}"`);
satrec.epochyr = parseInt(longstr1.substring(18, 20), 10);
console.debug(`longstr1.substring(18, 20) :>> `, `"${longstr1.substring(18, 20)}"`);
satrec.epochyr = Number.parseInt(longstr1.slice(18, 20), 10);
console.debug(`longstr1.substring(18, 20) :>>`, `"${longstr1.slice(18, 20)}"`);
satrec.epochdays = parseFloat(longstr1.substring(20, 32));
console.debug(`longstr1.substring(20, 32) :>> `, `"${longstr1.substring(20, 32)}"`);
satrec.epochdays = Number.parseFloat(longstr1.slice(20, 32));
console.debug(`longstr1.substring(20, 32) :>>`, `"${longstr1.slice(20, 32)}"`);
satrec.ndot = parseFloat(longstr1.substring(33, 43));
console.debug(`longstr1.substring(33, 43) :>> `, `"${longstr1.substring(33, 43)}"`);
satrec.ndot = Number.parseFloat(longstr1.slice(33, 43));
console.debug(`longstr1.substring(33, 43) :>>`, `"${longstr1.slice(33, 43)}"`);
satrec.nddot = parseFloat(`.${parseInt(longstr1.substring(44, 50), 10)}E${longstr1.substring(50, 52)}`);
console.debug(`longstr1.substring(44, 50) :>> `, `"${longstr1.substring(44, 50)}"`);
console.debug(`longstr1.substring(50, 52) :>> `, `"${longstr1.substring(50, 52)}"`);
satrec.nddot = Number.parseFloat(`.${Number.parseInt(longstr1.slice(44, 50), 10)}E${longstr1.slice(50, 52)}`);
console.debug(`longstr1.substring(44, 50) :>>`, `"${longstr1.slice(44, 50)}"`);
console.debug(`longstr1.substring(50, 52) :>>`, `"${longstr1.slice(50, 52)}"`);
satrec.bstar = parseFloat(
`${longstr1.substring(53, 54)}.${parseInt(longstr1.substring(54, 59), 10)}E${longstr1.substring(59, 61)}`,
satrec.bstar = Number.parseFloat(
`${longstr1.slice(53, 54)}.${Number.parseInt(longstr1.slice(54, 59), 10)}E${longstr1.slice(59, 61)}`,
);
console.debug(`longstr1.substring(53, 54) :>> `, `"${longstr1.substring(53, 54)}"`);
console.debug(`longstr1.substring(54, 59) :>> `, `"${longstr1.substring(54, 59)}"`);
console.debug(`longstr1.substring(59, 61) :>> `, `"${longstr1.substring(59, 61)}"`);
console.debug(`longstr1.substring(53, 54) :>>`, `"${longstr1.slice(53, 54)}"`);
console.debug(`longstr1.substring(54, 59) :>>`, `"${longstr1.slice(54, 59)}"`);
console.debug(`longstr1.substring(59, 61) :>>`, `"${longstr1.slice(59, 61)}"`);
// satrec.satnum = longstr2.substring(2, 7);
satrec.inclo = parseFloat(longstr2.substring(8, 16));
console.debug(`longstr2.substring(8, 16) :>> `, `"${longstr2.substring(8, 16)}"`);
satrec.inclo = Number.parseFloat(longstr2.slice(8, 16));
console.debug(`longstr2.substring(8, 16) :>>`, `"${longstr2.slice(8, 16)}"`);
satrec.nodeo = parseFloat(longstr2.substring(17, 25));
console.debug(`longstr2.substring(17, 25) :>> `, `"${longstr2.substring(17, 25)}"`);
satrec.nodeo = Number.parseFloat(longstr2.slice(17, 25));
console.debug(`longstr2.substring(17, 25) :>>`, `"${longstr2.slice(17, 25)}"`);
satrec.ecco = parseFloat(`.${longstr2.substring(26, 33)}`);
console.debug(`longstr2.substring(26, 33) :>> `, `"${longstr2.substring(26, 33)}"`);
satrec.argpo = parseFloat(longstr2.substring(34, 42));
console.debug(`longstr2.substring(34, 42) :>> `, `"${longstr2.substring(34, 42)}"`);
satrec.mo = parseFloat(longstr2.substring(43, 51));
console.debug(`longstr2.substring(43, 51) :>> `, `"${longstr2.substring(43, 51)}"`);
satrec.no = parseFloat(longstr2.substring(52, 63));
console.debug(`longstr2.substring(52, 63) :>> `, `"${longstr2.substring(52, 63)}"`);
satrec.ecco = Number.parseFloat(`.${longstr2.slice(26, 33)}`);
console.debug(`longstr2.substring(26, 33) :>>`, `"${longstr2.slice(26, 33)}"`);
satrec.argpo = Number.parseFloat(longstr2.slice(34, 42));
console.debug(`longstr2.substring(34, 42) :>>`, `"${longstr2.slice(34, 42)}"`);
satrec.mo = Number.parseFloat(longstr2.slice(43, 51));
console.debug(`longstr2.substring(43, 51) :>>`, `"${longstr2.slice(43, 51)}"`);
satrec.no = Number.parseFloat(longstr2.slice(52, 63));
console.debug(`longstr2.substring(52, 63) :>>`, `"${longstr2.slice(52, 63)}"`);
console.groupEnd();
return satrec;
}
// console.debug(`twoline2satrecFake(longstr1, longstr2) :>> `, twoline2satrecFake(longstr1, longstr2));
const satrec1 = twoline2satrec(longstr1, longstr2);
const satrec2 = twoline2satrec(
// if ($__DEV__)
// console.debug(
// `twoline2satrecFake(longstr1, longstr2) :>>`,
// twoline2satrecFake(longstr1, longstr2),
// );
const = twoline2satrec(
`1 63157 25069.35219743 .00000545 -65692-6 00000+0 `,
`2 19.0062 64.6364 7327661 179.7218 141.4162 2.26206155 `,
);
const item = {
gdzj: '7',
wxzj: '2025029F',
wxmc: 'STARLINK-32884',
wxbh: '62953',
lysj: '25070.91668981',
ysjbh: '999',
xllx: '0',
bstarqzxt: '-0.01591824',
pjyddyjds: '-0.01591824',
drry: null,
drsj: null,
xgry: null,
xgsj: null,
isFlag: 0,
pjyddejds: '0',
gdqj: '53.1597',
sjdcj: '125.942',
pxl: '0.0001413',
jddfj: '92.4266',
pjdj: '189.6779',
pjyd: '15.48632226',
fsyldgdqs: '556',
};
const r = {
ARG_OF_PERICENTER: 101.1211,
BSTAR: 0.00099294,
CLASSIFICATION_TYPE: 'U',
ECCENTRICITY: 0.0001355,
ELEMENT_SET_NO: 999,
EPHEMERIS_TYPE: 0,
EPOCH: '2025-03-11T22:00:01.999584',
INCLINATION: 53.1596,
MEAN_ANOMALY: 35.9659,
MEAN_MOTION: 15.39574303,
MEAN_MOTION_DDOT: 0,
MEAN_MOTION_DOT: 0.00039463,
NORAD_CAT_ID: 62949,
OBJECT_ID: '2025-029B',
OBJECT_NAME: 'STARLINK-32857',
RA_OF_ASC_NODE: 120.9032,
REV_AT_EPOCH: 580,
};
const satrec1 = twoline2satrec(longstr1, longstr2); // 正确结果
let line1 = '';
line1 += '1'; //
line1 += ' '; //
line1 += '62949'; // 卫星编号
line1 += 'U'; // 卫星分类
line1 += ' ';
line1 += '25';
line1 += '029';
line1 += 'B'.padEnd(3, ' ');
line1 += ' ';
line1 += '25070.91668981'; // 🛰️ 历元时间 25070.91668981(年份 2025第 70 天加 0.91668981 天)
line1 += ' ';
line1 += '.00039463'.padStart(10, ' '); //
line1 += '00000+0'.padStart(9, ' '); //
line1 += '99294-3'.padStart(9, ' '); //
line1 += ' ';
line1 += '0';
line1 += ' ';
line1 += '999'.padStart(4, ' ');
line1 += '0';
let line2 = '';
line2 += '2';
line2 += ' ';
line2 += '62949';
line2 += ' ';
line2 += '53.1596'.padStart(8, ' '); // 🛰️ 轨道倾角(度)
line2 += ' ';
line2 += '120.9032'; // 🛰️ 升交点赤经(度)
line2 += ' ';
line2 += '0001355'; // 🛰️ 偏心率
line2 += ' ';
line2 += '101.1211'; // 🛰️ 近地点角距(度)
line2 += ' ';
line2 += '35.9659'.padStart(8, ' '); // 🛰️ 平近点角(度)
line2 += ' ';
line2 += '15.39574303'; // 🛰️ 平均运动(圈/天)
line2 += '580'.padStart(5, ' ');
line2 += '9';
// console.debug(`xxxline2 :>>`, `"${line2}"`);
// console.debug('正确↓');
// console.debug(`longstr2 :>>`, `"${longstr2}"`);
// twoline2satrecFake('', line2);
// twoline2satrecFake('', longstr2);
// const numbers = '0123456789';
// twoline2satrecFake(
// `${numbers}${numbers}${numbers}${numbers}${numbers}${numbers}`,
// '',
// );
const satrec2 = twoline2satrec(
`1 62949 25070.91668981 .00039463 00000+0 99294-3 `,
`2 53.1596 120.9032 0001355 101.1211 35.9659 15.39574303 `,
);
const satrec1_str = JSON.stringify(satrec1, null, 2);
const satrec2_str = JSON.stringify(satrec2, null, 2);
if ($__DEV__) console.debug(`satrec1_str === satrec2_str :>> `, satrec1_str === satrec2_str);
if ($__DEV__) console.debug(`satrec1_str === satrec2_str :>>`, satrec1_str === satrec2_str);
// longstr1.substring(2, 7) :>> "63157"
// longstr1.substring(18, 20) :>> "25"