You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析TLE文件时核心变量为空的技术问题求助

TLE解析变量为空问题排查与解决

问题核心原因

  1. 行参数传递错误:原代码中Satellite类初始化时,误将卫星名字行当作TLE数据行解析,从非数据行提取的内容无法转换为数字,导致变量返回None。
  2. 未处理空行:原解析函数未过滤TLE文件中的空行,导致读取的行序列混乱,无法拿到正确的TLE数据行。

修复后的代码

import requests
from sqlalchemy import create_engine, Column, Integer, Float, String
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker

class Satellite:
    def __init__(self, name, tle_line1, tle_line2):
        self.name = name
        self.tle_line1 = tle_line1
        self.tle_line2 = tle_line2
        
        # 从TLE第一行解析字段
        self.satellite_catalog_number = self.parse_int(tle_line1[2:7])
        self.classification = tle_line1[7]
        self.international_designator = tle_line1[9:17]
        self.epoch_year = self.parse_int(tle_line1[18:20])
        self.epoch_day = self.parse_float(tle_line1[20:32])
        self.first_derivative_mean_motion = self.parse_float(tle_line1[33:43])
        # 处理二阶导数的科学计数法格式
        second_deriv = tle_line1[44:52].strip()
        self.second_derivative_mean_motion = self.parse_float(self.convert_sci_notation(second_deriv))
        # 处理B*的科学计数法格式
        bstar_val = tle_line1[53:61].strip()
        self.bstar = self.parse_float(self.convert_sci_notation(bstar_val))
        self.element_set_number = self.parse_int(tle_line1[64:68])

        # 从TLE第二行解析字段
        self.inclination = self.parse_float(tle_line2[8:16])
        self.raan = self.parse_float(tle_line2[17:25])
        self.eccentricity = self.parse_float(f"0.{tle_line2[26:33]}")
        self.arg_of_perigee = self.parse_float(tle_line2[34:42])
        self.mean_anomaly = self.parse_float(tle_line2[43:51])
        self.mean_motion = self.parse_float(tle_line2[52:63])
        self.revolution_number = self.parse_int(tle_line2[63:68])

    def convert_sci_notation(self, value):
        # 转换TLE特有的科学计数格式(如00000-0 → 0e-0,98086-4 → 98086e-4)
        if not value:
            return "0"
        if '-' in value:
            parts = value.split('-')
            return f"{parts[0]}e-{parts[1]}" if len(parts) ==2 else value
        if '+' in value:
            parts = value.split('+')
            return f"{parts[0]}e+{parts[1]}" if len(parts)==2 else value
        return value

    def parse_float(self, value):
        try:
            return float(value.strip())
        except (ValueError, TypeError):
            return None

    def parse_int(self, value):
        try:
            return int(value.strip())
        except (ValueError, TypeError):
            return None

    def __str__(self):
        return f"Name: {self.name}\nSatellite Catalog Number: {self.satellite_catalog_number}\n" \
               f"Classification: {self.classification}\nInternational Designator: {self.international_designator}\n" \
               f"Epoch Year: {self.epoch_year}\nEpoch Day: {self.epoch_day}\n" \
               f"First Derivative of Mean Motion: {self.first_derivative_mean_motion}\n" \
               f"Second Derivative of Mean Motion: {self.second_derivative_mean_motion}\n" \
               f"B* Drag Term: {self.bstar}\nElement Set Number: {self.element_set_number}\n\n" \
               f"Inclination: {self.inclination}\nRAAN: {self.raan}\nEccentricity: {self.eccentricity}\n" \
               f"Argument of Perigee: {self.arg_of_perigee}\nMean Anomaly: {self.mean_anomaly}\n" \
               f"Mean Motion: {self.mean_motion}\nRevolution Number: {self.revolution_number}\n"


def parse_tle_file(file_path):
    with open(file_path, 'r') as file:
        # 过滤空行,仅保留有效数据行
        lines = [line.strip() for line in file if line.strip()]

    satellites = []
    i = 0
    # 每3行对应一组卫星数据:名字行、TLE行1、TLE行2
    while i + 2 < len(lines):
        name_line = lines[i]
        tle_line1 = lines[i+1]
        tle_line2 = lines[i+2]
        
        if name_line.startswith('0') and tle_line1.startswith('1') and tle_line2.startswith('2'):
            name = name_line[2:].strip()
            satellite = Satellite(name, tle_line1, tle_line2)
            satellites.append(satellite)
        
        i += 3

    return satellites


# 使用示例
tle_file_path = 'C:/Users/avelascoe/Documents/Indra/BaseTLELEO/Follow/3le20210612.txt'
satellites = parse_tle_file(tle_file_path)

for satellite in satellites:
    print(satellite)


# 数据库连接配置
mydb = {
    "user": "root",
    "password": "root",
    "host": "localhost",
    "port": "3306",
    "database": "prueba",
}

connection_string = f'mysql+mysqlconnector://{mydb["user"]}:{mydb["password"]}@{mydb["host"]}:{mydb["port"]}/{mydb["database"]}'
engine = create_engine(connection_string)

Base = declarative_base()

class SatelliteModel(Base):
    __tablename__ = 'satellites2'

    id = Column(Integer, primary_key=True)
    name = Column(String(255))
    satellite_catalog_number = Column(Integer)
    classification = Column(String(1))
    international_designator = Column(String(8))
    epoch_year = Column(Integer)
    epoch_day = Column(Float)
    first_derivative_mean_motion = Column(Float)
    second_derivative_mean_motion = Column(Float)
    bstar = Column(Float)
    element_set_number = Column(Integer)
    inclination = Column(Float)
    raan = Column(Float)
    eccentricity = Column(Float)
    arg_of_perigee = Column(Float)
    mean_anomaly = Column(Float)
    mean_motion = Column(Float)
    revolution_number = Column(Integer)

    def __init__(self, satellite):
        self.name = satellite.name
        self.satellite_catalog_number = satellite.satellite_catalog_number
        self.classification = satellite.classification
        self.international_designator = satellite.international_designator
        self.epoch_year = satellite.epoch_year
        self.epoch_day = satellite.epoch_day
        self.first_derivative_mean_motion = satellite.first_derivative_mean_motion
        self.second_derivative_mean_motion = satellite.second_derivative_mean_motion
        self.bstar = satellite.bstar
        self.element_set_number = satellite.element_set_number
        self.inclination = satellite.inclination
        self.raan = satellite.raan
        self.eccentricity = satellite.eccentricity
        self.arg_of_perigee = satellite.arg_of_perigee
        self.mean_anomaly = satellite.mean_anomaly
        self.mean_motion = satellite.mean_motion
        self.revolution_number = satellite.revolution_number

    def __str__(self):
        return f"Name: {self.name}\nSatellite Catalog Number: {self.satellite_catalog_number}\n" \
               f"Classification: {self.classification}\nInternational Designator: {self.international_designator}\n" \
               f"Epoch Year: {self.epoch_year}\nEpoch Day: {self.epoch_day}\n" \
               f"First Derivative of Mean Motion: {self.first_derivative_mean_motion}\n" \
               f"Second Derivative of Mean Motion: {self.second_derivative_mean_motion}\n" \
               f"B* Drag Term: {self.bstar}\nElement Set Number: {self.element_set_number}\n\n" \
               f"Inclination: {self.inclination}\nRAAN: {self.raan}\nEccentricity: {self.eccentricity}\n" \
               f"Argument of Perigee: {self.arg_of_perigee}\nMean Anomaly: {self.mean_anomaly}\n" \
               f"Mean Motion: {self.mean_motion}\nRevolution Number: {self.revolution_number}\n"


Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

for satellite in satellites:
    satellite_entry = SatelliteModel(satellite)
    session.add(satellite_entry)

session.commit()
session.close()

关键修复点

  • 行参数修正:Satellite类现在接收正确的TLE数据行(tle_line1和tle_line2)进行字段解析,不再使用名字行。
  • 空行过滤:解析函数先过滤文件中的空行,确保每3行是一组完整的卫星数据。
  • 科学计数法转换:新增convert_sci_notation方法,将TLE特有的科学计数格式转换为Python可识别的格式,避免转换失败。

验证结果

修复后运行代码,所有目标字段(satellite_catalog_number、epoch_year、mean_motion等)都会正确提取并转换,不再为空,且能正常存入数据库。

内容的提问来源于stack exchange,提问作者Sly_Cooper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:32:09