matlab/matlab-compute-aerospace-environment
> Compute aerospace environment properties including atmosphere (ISA, COESA, NRLMSISE-00, non-standard, CIRA), gravity (spherical harmonic, WGS84, zonal, centrifugal), horizontal wind (HWM), magnetic field (WMM, IGRF), geoid height, geocentric radius, space weather data, planetary ephemeris, Earth orientation (polar motion, nutation, delta-UT1, CIP). Use when computing atmospheric density, temperature, pressure, gravity vectors, wind profiles, magnetic field components, geoid undulation, solar flux indices, planet positions, or Earth orientation parameters for aerospace vehicle analysis, spacecraft environment modeling, or navigation corrections.
npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-compute-aerospace-environment
Calculate environment properties for aerospace vehicle analysis: atmosphere, gravity, wind, magnetic field, geoid, space weather, planetary ephemeris, and Earth orientation using Aerospace Toolbox functions.
matlab-convert-aerospace-coordinates| Need | Function | Key Input |
|------|----------|-----------|
| Standard atmosphere (quick) | atmosisa | altitude (m) |
| 1976 COESA atmosphere | atmoscoesa | altitude (m) |
| NRLMSISE-00 (detailed upper atmosphere) | atmosnrlmsise00 | alt, lat, lon, year, day, UTsec |
| Non-standard atmosphere (MIL-STD) | atmosnonstd | alt + positional string args |
| CIRA 1986 reference atmosphere | atmoscira | lat, ctype, coord, month |
| Lapse rate atmosphere (custom) | atmoslapse | altitude (m) + 9 physical params |
| Pressure altitude | atmospalt | pressure (Pa) |
| Horizontal wind (HWM07/14) | atmoshwm | lat, lon, alt + name-value |
| Spherical harmonic gravity (any planet) | gravitysphericalharmonic | PCPF [x,y,z] (m) |
| WGS84 gravity (Earth, geodetic) | gravitywgs84 | h, lat (+ lon, method, flags) |
| Zonal harmonic gravity (any planet) | gravityzonal | PCPF [x,y,z] (m) |
| Centrifugal acceleration | gravitycentrifugal | PCPF [x,y,z] (m) |
| WMM magnetic field | wrldmagm | height(m), lat, lon, decimalYear |
| IGRF magnetic field | igrfmagm | height(m), lat, lon, decimalYear, generation |
| Geoid height (undulation) | geoidheight | lat, lon |
| Geocentric radius | geocradius | geocentric lat (deg) |
| Read space weather CSV | aeroReadSpaceWeatherData | CSV file path |
| Extract solar flux / Ap indices | fluxSolarAndGeomagnetic | datetime or [year,day,UTCsec], MAT file |
| Planet/Moon position and velocity | planetEphemeris | Julian date, center, target |
| Earth nutation angles | earthNutation | Julian date |
| Moon libration angles | moonLibration | Julian date |
| Earth polar motion | polarMotion | UTC (Julian date) |
| Celestial Intermediate Pole adjustment | deltaCIP | UTC (Julian date) |
| Difference between UT1 and UTC | deltaUT1 | UTC (Julian date) |
| Read IERS Earth orientation data | aeroReadIERSData | folder path |
% International Standard Atmosphere
[T, a, P, rho] = atmosisa(1000);
% 1976 COESA (valid 0-1000 km)
[T, a, P, rho] = atmoscoesa(1000);
Converts pressure (Pa) to altitude (m) using the International Standard Atmosphere.
% Pressure altitude at standard sea-level pressure
alt = atmospalt(101325); % returns 0 m
% Pressure altitude at multiple pressures
alt = atmospalt([101325, 79501, 54048, 26500]);
% Typical use: convert measured pressure to altitude
measuredPressure_Pa = 75000;
pressureAltitude_m = atmospalt(measuredPressure_Pa);
Input: pressure in Pascals. Output: geometric altitude in meters based on 1976 COESA.
Uses positional string arguments — not name-value pairs.
Profile type (single altitude extreme):
[T, a, P, rho] = atmosnonstd(height, 'Profile', extremeParam, frequency, extremeAltitude)
Envelope type (altitude range extreme — NO extremeAltitude argument):
[T, a, P, rho] = atmosnonstd(height, 'Envelope', extremeParam, frequency)
Optional trailing args: action ('Warning'|'Error'|'None'), specification ('310'|'210c').
% Profile: high density, 1% of time, at 5 km altitude (extremeAltitude is NUMERIC)
[T, a, P, rho] = atmosnonstd(5000, 'Profile', 'High density', '1%', 5);
% Envelope: high pressure, 20% of time, MIL-STD-210C
[T, a, P, rho] = atmosnonstd([1000; 11000; 20000], 'Envelope', ...
'High pressure', '20%', 'None', '210c');
Valid extremeParam: 'High temperature', 'Low temperature', 'High density', 'Low density', 'High pressure', 'Low pressure'
Valid frequency: 'Extreme values', '1%', '5%', '10%', '20%'
Valid extremeAltitude (Profile only, numeric): 5, 10, 20, 30, 40
% By geopotential height, monthly mean, October
[T, P, zonalWind] = atmoscira(45, 'GPHeight', 20000, 'Monthly', 10);
% By pressure level
[T, alt, zonalWind] = atmoscira(45, 'Pressure', 101300, 'Monthly', 1);
Arguments: (latitude, ctype, coord, mtype, month) where ctype is 'Pressure' or 'GPHeight'.
% Basic call (uses default flux values)
[T, rho] = atmosnrlmsise00(altitude, latitude, longitude, year, dayOfYear, UTseconds);
% With flux data and no anomalous oxygen
[T, rho] = atmosnrlmsise00(altitude, lat, lon, year, dayOfYear, UTsec, ...
f107Average, f107Daily, magneticIndex, 'NoOxygen');
Output: T is N-by-2 [exospheric temp, local temp]. rho is N-by-9 (densities).
Requires 10 positional arguments — not just altitude. All physical parameters must be specified explicitly.
% TEMPLATE — not executable (shows calling convention)
[T, a, P, rho] = atmoslapse(altitude, g, gamma, R, lapseRate, ...
heightTroposphere, heightTropopause, density0, pressure0, temperature0);
% Example: ISA conditions
[T, a, P, rho] = atmoslapse([0 5000 11000 20000], ...
9.80665, 1.4, 287.0531, 0.0065, 11000, 20000, 1.225, 101325, 288.15);
Arguments: (height, g, heatRatio, gasConstant, lapseRate, hTroposphere, hTropopause, rho0, P0, T0). Use for custom planetary atmospheres or non-standard sea-level conditions.
Uses name-value arguments. Returns M-by-2 array [meridional, zonal] in m/s.
% Total wind with Ap index
wind = atmoshwm(-45, -85, 25000, model='total', day=150, ...
seconds=11*3600, apindex=80);
% Quiet wind at multiple altitudes (day/seconds must match array size)
wind = atmoshwm([50; 50], [-20; -20], [100000; 150000], ...
model='quiet', day=[30; 30], seconds=[0; 0]);
% Disturbed wind
wind = atmoshwm(70, -65, 150000, model='disturbance', day=166, seconds=0);
Name-value options: model ('quiet'|'disturbance'|'total'), day, seconds, apindex, version ('14'|'07').
Input is Planet-Centered Planet-Fixed (PCPF) [x,y,z] coordinates in meters — NOT lat/lon/alt.
% Earth: 25,000 m over South Pole (z-axis = polar axis)
[gx, gy, gz] = gravitysphericalharmonic([0, 0, -(6356752 + 25000)]);
% Mars GMM2B: equator + pole
pos = [3396200 + 15000, 0, 0; % equator
0, 0, 3376200 + 11000]; % north pole
[gx, gy, gz] = gravitysphericalharmonic(pos, 'GMM2B');
Models: 'EGM2008' (default), 'EGM96', 'LP100K', 'LP165P', 'GMM2B', 'EIGENGL04C', 'Custom'.
Note: Polar positions on oblate bodies will trigger a "Radial position is less than equatorial radius" warning — this is expected (polar radius < equatorial radius) and results are still valid.
Uses geodetic coordinates (height in meters, latitude/longitude in degrees).
For the Exact method with optional effects, pass flags as a single vector [noatm, nocent, prec, jd]:
% Taylor series (default) — only h and lat, no method string
g = gravitywgs84(1000, 45);
% CloseApprox — requires lon as 3rd argument
g = gravitywgs84(1000, 45, 20, 'CloseApprox');
% Exact with precession — requires lon + flag vector
[gn, gt] = gravitywgs84(1000, 0, 20, 'Exact', [false, false, true, 2451545]);
Calling conventions:
gravitywgs84(h, lat) — do NOT pass 'TaylorSeries' as a stringgravitywgs84(h, lat, lon, 'CloseApprox') — requires longravitywgs84(h, lat, lon, 'Exact', [noatm, nocent, prec, jd]) — requires lon + flag vectorFlag vector [noatm, nocent, prec, jd]:
noatm: true = exclude atmosphere correctionnocent: true = exclude centrifugal effectprec: true = include precessionjd: Julian date (0 = no precession date)Input is PCPF [x,y,z] in meters. Degree is a numeric scalar.
% Earth, 4th degree, at equator surface
Re = 6378137;
[gx, gy, gz] = gravityzonal([Re, 0, 0], 'Earth', 4);
% Mars at two positions
[gx, gy, gz] = gravityzonal([3396200+15000, 0, 0; 0, 0, 3376200+11000], 'Mars');
Input is PCPF [x,y,z] in meters.
% Earth at equator surface
[gx, gy, gz] = gravitycentrifugal([6378137, 0, 0]);
% Mars
[gx, gy, gz] = gravitycentrifugal([3396200, 0, 0], 'Mars');
Both wrldmagm and igrfmagm take height in meters, latitude/longitude in degrees, and decimal year. Use decyear to convert calendar dates.
% WMM-2025
[XYZ, H, D, I, F] = wrldmagm(1000, 40.44, -79.99, decyear(2025,7,4), '2025');
% IGRF-14
[XYZ, H, D, I, F] = igrfmagm(3000, 41.50, -81.69, decyear(2028,7,4), 14);
Output: XYZ = [North, East, Down] in nT; H = horizontal intensity; D = declination (deg); I = inclination (deg); F = total intensity (nT).
% Geoid undulation (EGM96 default) — longitude must be [0, 360]
N = geoidheight(42.4, 289.0);
% EGM2008
N = geoidheight(42.4, 289.0, 'EGM2008');
% Geocentric radius at multiple latitudes (input: geocentric lat in degrees)
r = geocradius([0, 45, 90]); % default WGS84
r = geocradius([0, 45, 90], 'WGS84'); % explicit model
Ephemeris functions require data from aeroDataPackage. All take Julian dates as time input.
% Planet/Moon position and velocity (km, km/s by default)
jd = juliandate(2022, 10, 27, 12, 0, 0);
[pos, vel] = planetEphemeris(jd, 'Earth', 'Moon');
[pos, vel] = planetEphemeris(jd, 'SolarSystem', 'Mars', '430', 'AU');
% Earth nutation (radians)
[angles, rates] = earthNutation(jd); % angles = [dpsi, depsilon]
% Moon libration (radians)
[angles, rates] = moonLibration(jd); % 3 Euler angles + rates
% Earth polar motion (radians) — input is UTC as Julian date
utc = juliandate(2020, 1, 1);
[pm, pmError] = polarMotion(utc); % pm = [xp, yp]
% Celestial Intermediate Pole adjustment (radians)
[dcip, dcipError] = deltaCIP(utc); % dcip = [dX, dY]
% UT1-UTC difference (seconds)
[dut1, dut1Error] = deltaUT1(utc);
Valid planetEphemeris targets/centers: 'Sun', 'Mercury', 'Venus', 'Earth', 'Moon', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto', 'SolarSystem', 'EarthMoon'.
Models: '405' (default), '421', '423', '430', '432t'.
Note: polarMotion, deltaCIP, and deltaUT1 use IERS data from aeroiersdata.mat (shipped) or a custom source. To get updated IERS data:
% Download latest Earth orientation data and save as MAT file
iersFile = aeroReadIERSData(pwd);
% Then pass to Earth orientation functions via Source name-value
[pm, pmError] = polarMotion(utc, Source=iersFile);
[dcip, dcipError] = deltaCIP(utc, Source=iersFile);
[dut1, dut1Error] = deltaUT1(utc, Source=iersFile);
The full pipeline for realistic NRLMSISE-00 inputs:
% Step 1: Read CSV (downloaded from CelesTrack) into MAT file
% TEMPLATE — requires user-provided CSV file
matFile = aeroReadSpaceWeatherData('spaceWeatherFile.csv');
% Step 2: Extract flux and magnetic indices for a specific date/time
dt = datetime(2022, 10, 27, 6, 30, 0, 'TimeZone', 'UTC');
[f107avg, f107daily, magIdx] = fluxSolarAndGeomagnetic(dt, matFile, ...
F107ExtrapMethod='constant', MagneticIndexExtrapMethod='constant');
% Step 3: Feed into NRLMSISE-00
dayOfYear = day(dt, 'dayofyear');
UTsec = seconds(timeofday(dt));
[T, rho] = atmosnrlmsise00(400e3, 45, -50, dt.Year, dayOfYear, UTsec, ...
f107avg, f107daily, magIdx, 'NoOxygen');
Notes:
aeroReadSpaceWeatherData takes a user-provided CSV (CelesTrack format) — no sample ships with the toolboxfluxSolarAndGeomagneticaeroSpaceWeatherData.mat (via which('aeroSpaceWeatherData.mat')) is available if no CSV is providedfluxSolarAndGeomagnetic accepts either (datetime, matFile) or (year, dayOfYear, UTCseconds, matFile)| Mistake | Why It Fails | Correct Approach |
|---------|-------------|-----------------|
| Passing lat/lon/alt to gravitysphericalharmonic | Expects PCPF [x,y,z] in meters | Convert to Cartesian: equator surface = [Re, 0, 0], pole = [0, 0, Rp] |
| Name-value pairs for atmosnonstd | Uses positional strings, not NV | atmosnonstd(h, 'Envelope', 'High pressure', '20%') |
| Separate boolean args to gravitywgs84 Exact | Flags must be a single vector | gravitywgs84(h, lat, lon, 'Exact', [noatm, nocent, prec, jd]) |
| Passing 'TaylorSeries' as method string | Method argument is third argument when required | Use 2-arg form: gravitywgs84(h, lat) — no method string |
| Calling gravitywgs84(h, lat, 'CloseApprox') without lon | CloseApprox requires longitude | gravitywgs84(h, lat, lon, 'CloseApprox') |
| Including extremeAltitude with Envelope type | Only valid for Profile type | Omit for Envelope: atmosnonstd(h, 'Envelope', param, freq) |
| Using atmosnrlmsise00 for wind | Wrong function | Use atmoshwm for horizontal wind |
| Calling gravitywgs84 for centrifugal effect | No centrifugal-only mode | Use gravitycentrifugal([x, y, z]) |
| Wrong function name gravityzonalharmonic | Does not exist | Use gravityzonal |
| Passing string degree to gravityzonal | Expects numeric scalar | gravityzonal(coords, 'Earth', 4) not '4thDegree' |
| Ignoring aeroReadSpaceWeatherData output | Returns a MAT file containing space weather data | Pass the returned MAT file to fluxSolarAndGeomagnetic |
gravitysphericalharmonic, gravityzonal, gravitycentrifugaldecyear(year, month, day) for magnetic model date inputsday = day of year (1-366); seconds = seconds since midnight UTCgeoidheight longitude: Must be in [0, 360] degrees (east positive). Use mod(lon, 360) to convert from [-180, 180][0, 0, -(Rp + altitude)] where Rp is polar radius[Re + altitude, 0, 0] where Re is equatorial radius----
Copyright 2026 The MathWorks, Inc.
----
Take matlab/matlab-compute-aerospace-environment from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.