lunar mission analysis with the orbit propagator block -凯发k8网页登录
this example shows how to compute and visualize access intervals between the apollo command and service module and a rover on the lunar surface. the module's orbit is modeled using reference trajectory #2 from the nasa report variations of the lunar orbital parameters of the apollo csm-module [2]. this is a lunar orbit studied by nasa for the apollo program.the example uses:
aerospace toolbox™
aerospace blockset™
mapping toolbox™
define mission parameters and module initial conditions
specify the start date and duration for the mission. this example uses matlab® structures to organize mission data. these structures make accessing data later in the example more intuitive. they also help declutter the global base workspace.
mission.startdate = datetime(1969, 9, 20, 5, 10, 12.176); mission.duration = hours(2);
specify keplerian orbital elements for the command and service module (csm) at the mission.startdate
based on reference trajectory #2 [2]. the criteria for the reference trajectories featured in reference 2 are:
the plane of the trajectory must contain a landing site vector on the earth side of the moon, which has a longitude of between 315 and 45 degrees and a latitude of between 5 and -5 degrees in selenographic coordinates. [2]
the plane of the orbit must be oriented so that the lunar landing side doesn't move out of the orbital plane more than 0.5 degrees during the period of 3 to 39 hours after lunar insertion. [2]
csm.semimajoraxis = 1894578.3; % [m] csm.eccentricity = 0.0004197061; csm.inclination = 155.804726; % [deg] csm.raan = 182.414087; % [deg] csm.argofperiapsis = 262.877900; % [deg] csm.trueanomaly = 0.000824; % [deg]
note that the inclination angle is relative to the icrf x-y plane. the icrf x-y axis is normal to earth's north pole. the axial tilt of earth relative to the ecliptic is ~23.44 degrees, while the axial tilt of the moon is ~5.145 degrees. therefore, the axial tilt of the moon relative to the icrf x-y plane varies between approximately degrees. this explains why the orbital inclination of ~155.8 degrees above satisfies the requirement to maintain a latitude of degrees in selenographic coordindates.
specify the latitude and longitude of a rover on the lunar surface to use in the line-of-sight access analysis.
rover.latitude =0; % [deg] rover.longitude =23.5; % [deg]
open and configure the model
open the included simulink® model. this model contains an orbit propagator block connected to output ports. the orbit propagator
block supports vectorization. this allows you to model multiple satellites in a single block by specifying arrays of initial conditions in the block parameters window or using set_param
.
mission.mdl = "lunarorbitpropagatorblockexamplemodel";
open_system(mission.mdl);
use a simulationinput
object to configure the model for our mission. simulationinput
objects provide the ability to configure multiple missions and run simulations with those settings without modifying the model.
mission.sim.in = simulink.simulationinput(mission.mdl);
define the path to the orbit propagator block in the model.
csm.blk = mission.mdl "/orbit propagator";
load moon properties into the base workspace.
moon.f = 0.0012; % moon ellipticity (flattening) (ref 1) moon.r_eq = 1737400; % [m] lunar radius in meters (ref 1) moon.referenceellipsoid = referenceellipsoid("moon","meter"); % moon reference ellipsoid moon.data = matfile("lunargeographicaldata.mat"); % load moon geographical data
set csm initial conditions. to assign the keplerian orbital element set defined in the previous section, use setblockparameter
.
mission.sim.in = mission.sim.in.setblockparameter(... csm.blk, "startdate", string(juliandate(mission.startdate)),... csm.blk, "stateformatnum", "orbital elements",... csm.blk, "orbittype", "keplerian",... csm.blk, "semimajoraxis", string(csm.semimajoraxis),... csm.blk, "eccentricity", string(csm.eccentricity),... csm.blk, "inclination", string(csm.inclination),... csm.blk, "raan", string(csm.raan),... csm.blk, "argperiapsis", string(csm.argofperiapsis),... csm.blk, "trueanomaly", string(csm.trueanomaly));
set the position and velocity output ports of the block to use the moon-fixed frame. the fixed-frame for the moon is the mean earth/pole axis (me) reference system.
mission.sim.in = mission.sim.in.setblockparameter(... csm.blk, "centralbody", "moon",... csm.blk, "outportframe", "fixed-frame");
configure the propagator.
mission.sim.in = mission.sim.in.setblockparameter(... csm.blk, "propagator", "numerical (high precision)",... csm.blk, "gravitymodel", "spherical harmonics",... csm.blk, "moonsh", "lp-100k",... % moon spherical harmonic potential model csm.blk, "shdegree", "100",... % spherical harmonic model degree and order csm.blk, "usemoonlib", "off");
apply model-level solver settings using setmodelparameter. for best performance and accuracy when using a numerical propagator, use a variable-step solver.
mission.sim.in = mission.sim.in.setmodelparameter(... solvertype="variable-step",... solvername="variablestepauto",... reltol="1e-6",... abstol="1e-7",... stoptime=string(seconds(mission.duration)));
save model output port data as a dataset of timetable objects.
mission.sim.in = mission.sim.in.setmodelparameter(... saveoutput="on",... outputsavename="yout",... saveformat="dataset",... datasetsignalformat="timetable");
run the model and collect csm ephemerides
simulate the model using the simulationinput
object defined above. in this example, the orbit propagator block is set to output position and velocity states in the moon-centered fixed coordinate frame.
mission.sim.out = sim(mission.sim.in);
extract the position and velocity data from the model output data structure.
csm.timetablepos = mission.sim.out.yout{1}.values; csm.timetablevel = mission.sim.out.yout{2}.values;
set the start date of the mission in the timetable
object.
csm.timetablepos.properties.starttime = mission.startdate;
process simulation data
compute latitude, longitude, and altitude using lunar equatorial radius and flattening. values are displayed in degrees and meters.
csm.mepos = [csm.timetablepos.data(:,1) ... csm.timetablepos.data(:,2) csm.timetablepos.data(:,3)]; lla = ecef2lla(csm.mepos, moon.f, moon.r_eq); csm.lla = timetable(csm.timetablepos.time, ... lla(:,1), lla(:,2), lla(:,3), ... variablenames=["lat", "lon", "alt"]); clear lla; disp(csm.lla);
time lat lon alt ____________________ _________ _______ __________ 20-sep-1969 05:10:12 -2.3072 175.32 1.5639e 05 20-sep-1969 05:10:22 -2.3039 174.83 1.5639e 05 20-sep-1969 05:11:12 -2.2846 172.39 1.5639e 05 20-sep-1969 05:13:36 -2.2061 165.35 1.5639e 05 20-sep-1969 05:16:00 -2.0947 158.31 1.564e 05 20-sep-1969 05:18:24 -1.952 151.27 1.5641e 05 20-sep-1969 05:20:48 -1.7804 144.24 1.5641e 05 20-sep-1969 05:23:12 -1.5824 137.21 1.5642e 05 20-sep-1969 05:25:36 -1.3608 130.17 1.5641e 05 20-sep-1969 05:28:00 -1.119 123.14 1.5641e 05 20-sep-1969 05:30:24 -0.86057 116.11 1.564e 05 20-sep-1969 05:32:48 -0.58934 109.09 1.564e 05 20-sep-1969 05:35:12 -0.30942 102.06 1.5639e 05 20-sep-1969 05:37:36 -0.025001 95.032 1.5639e 05 20-sep-1969 05:40:00 0.25967 88.006 1.564e 05 20-sep-1969 05:42:24 0.54034 80.978 1.564e 05 20-sep-1969 05:44:48 0.81284 73.951 1.5641e 05 20-sep-1969 05:47:12 1.0732 66.923 1.5642e 05 20-sep-1969 05:49:36 1.3175 59.893 1.5643e 05 20-sep-1969 05:52:00 1.5422 52.863 1.5646e 05 20-sep-1969 05:54:24 1.7439 45.831 1.5649e 05 20-sep-1969 05:56:48 1.9194 38.797 1.5652e 05 20-sep-1969 05:59:12 2.0662 31.763 1.5656e 05 20-sep-1969 06:01:36 2.1821 24.728 1.566e 05 20-sep-1969 06:04:00 2.2652 17.691 1.5664e 05 20-sep-1969 06:06:24 2.3145 10.655 1.5668e 05 20-sep-1969 06:08:48 2.3291 3.6183 1.5673e 05 20-sep-1969 06:11:12 2.309 -3.418 1.5676e 05 20-sep-1969 06:13:36 2.2544 -10.454 1.5679e 05 20-sep-1969 06:16:00 2.1663 -17.489 1.5682e 05 20-sep-1969 06:18:24 2.046 -24.522 1.5683e 05 20-sep-1969 06:20:48 1.8953 -31.554 1.5685e 05 20-sep-1969 06:23:12 1.7163 -38.585 1.5686e 05 20-sep-1969 06:25:36 1.5116 -45.614 1.5686e 05 20-sep-1969 06:28:00 1.2844 -52.642 1.5686e 05 20-sep-1969 06:30:24 1.0381 -59.668 1.5686e 05 20-sep-1969 06:32:48 0.77625 -66.693 1.5685e 05 20-sep-1969 06:35:12 0.50273 -73.718 1.5684e 05 20-sep-1969 06:37:36 0.22159 -80.741 1.5683e 05 20-sep-1969 06:40:00 -0.062926 -87.765 1.5682e 05 20-sep-1969 06:42:24 -0.34651 -94.789 1.568e 05 20-sep-1969 06:44:48 -0.62489 -101.81 1.5677e 05 20-sep-1969 06:47:12 -0.89393 -108.84 1.5673e 05 20-sep-1969 06:49:36 -1.1497 -115.87 1.5669e 05 20-sep-1969 06:52:00 -1.3884 -122.89 1.5664e 05 20-sep-1969 06:54:24 -1.6064 -129.92 1.566e 05 20-sep-1969 06:56:48 -1.8006 -136.96 1.5656e 05 20-sep-1969 06:59:12 -1.9679 -143.99 1.5652e 05 20-sep-1969 07:01:36 -2.1058 -151.03 1.5647e 05 20-sep-1969 07:04:00 -2.212 -158.06 1.5641e 05 20-sep-1969 07:06:24 -2.2849 -165.1 1.5635e 05 20-sep-1969 07:08:48 -2.3235 -172.14 1.563e 05 20-sep-1969 07:10:12 -2.3299 -176.25 1.5626e 05
results
display csm trajectories over the 3-d moon
figure; axis off; colormap gray; view(-5,23); axesm("globe","geoid", moon.referenceellipsoid); geoshow(moon.data.moonalb20c, moon.data.moonalb20cr, displaytype="texturemap"); plot3(csm.mepos(:,1), csm.mepos(:,2), csm.mepos(:,3),"r");
display 2-d projection of csm ground trace and rover position
figure; colormap gray; axesm(mapprojection="robinson"); geoshow(moon.data.moonalb20c, moon.data.moonalb20cr, displaytype="texturemap"); plotm(csm.lla.lat, csm.lla.lon, color="r"); plotm(rover.latitude, rover.longitude, "xy", linewidth=3);
display csm field of view at time of interest
define a time of interest (toi) to anayze. for this example, we select the 30th sample in the dataset.
csm.toi.lla = csm.lla(30,:);
calculate angular radius of orbiter line-of-sight (los) field of view (fov) measured from the moon center.
csm.toi.fov.lambda0 = acosd(moon.r_eq / (moon.r_eq csm.toi.lla.alt)); % [deg] [csm.toi.fov.lats, csm.toi.fov.lons] = ... scircle1(csm.toi.lla.lat, csm.toi.lla.lon, csm.toi.fov.lambda0);
plot toi. the location of the csm is indicated by a green cross, los field of view is indicated by dashed circle.
figure; colormap gray; axesm(mapprojection="robinson"); geoshow(moon.data.moonalb20c, moon.data.moonalb20cr, displaytype="texturemap"); plotm(csm.toi.fov.lats, csm.toi.fov.lons, "g--", linewidth=1); % csm visibility projected onto the map plotm(csm.lla.lat, csm.lla.lon, color="r"); % csm ground trace plotm(csm.toi.lla.lat, csm.toi.lla.lon, "g ", markersize=8); % sub-csm point plotm(rover.latitude, rover.longitude, "xy", linewidth=3);
display csm line-of-sight visibility from rover
estimate access intervals by assuming the moon is spherical.
lambda_all = acosd(moon.r_eq ./ (moon.r_eq csm.lla.alt)); % [deg] angular radius of csm fov measured from moon center d = distance(csm.lla.lat, csm.lla.lon, ... rover.latitude, rover.longitude); % [deg] angular distance between sub-csm point and rover rover.access.inview = csm.lla(lambda_all - d > 0,:); % timetable containing the in view data samples rover.access.inview.time.format = "hh:mm:ss"; clear lambda_all d;
plot access intervals between the orbiting module and rover.
if height(rover.access.inview) ~= 0 % look for breaks in the timestamps to identify pass starts rover.access.startidx = [1, find(diff(rover.access.inview.time) > minutes(5))]; rover.access.starttime = rover.access.inview.time(rover.access.startidx); rover.access.stopidx = [rover.access.startidx(2:end)-1, height(rover.access.inview)]; rover.access.stoptime = rover.access.inview.time(rover.access.stopidx); rover.access.duration = rover.access.stoptime - rover.access.starttime; % show pass intervals in table rover.access.intervaltable = table(rover.access.starttime, rover.access.stoptime, rover.access.duration, ... variablenames=["pass start", "pass end", "duration"]); disp(rover.access.intervaltable); disp(' '); % set up figure window/plot figure; colormap gray; axesm(mapprojection="robinson") geoshow(moon.data.moonalb20c, moon.data.moonalb20cr, displaytype="texturemap") title(join(["passes between", string(csm.lla.time(1)), ... "and", string(csm.lla.time(end))])); % plot inview, rover, and csm orbit plotm(rover.access.inview.lat, rover.access.inview.lon, " g"); plotm(rover.latitude, rover.longitude, "xy", linewidth=3); plotm(csm.lla.lat, csm.lla.lon, color="r"); % plot pass inteval rover.access.edgeindices = rover.access.inview(sort([rover.access.startidx rover.access.stopidx]), :); for j = 1 : height(rover.access.edgeindices) textm(rover.access.edgeindices.lat(j) 10, ... rover.access.edgeindices.lon(j), ... string(rover.access.edgeindices.time(j)), color="y", rotation=30); end else disp("the csm is not visible from the rover during the defined mission time.") end
pass start pass end duration __________ ________ ________ 05:54:24 06:08:48 00:14:24
references
[1] williams, dr. david r. “moon fact sheet”, planetary fact sheets, nssdca, nasa goddard space flight center, 13 january 2020, https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html.
[2] timer, t.p. (nasa mission analysis office) "variations of the lunar orbital parameters of the apollo csm-module", nasa tm x-55460. greenbelt, maryland: goddard space flight center, february 1966.