Simulate ONS for a solar sail near the L1 Lagrange point
This only simulates the orbital motion.
Contents
%-------------------------------------------------------------------------- % Copyright (c) 2021 Princeton Satellite Systems, Inc. % All rights reserved. %--------------------------------------------------------------------------
Constants
rE = Constant('equatorial radius earth'); rS = Constant('sun radius'); muSun = Constant('mu sun'); aU = Constant('au'); secToDay = 1/86400; secInYear = 365.26*86400; kEarth = 3; % SPICE numbering 1-9 are the planets, 10 is the moon earth = 1; sun = 2; % Get the defaults dRHS = RHSHelioMission;
Script control
viewersOn = true; printAll = false; % acceleration model massFuel = 0; % kg dRHS.mD = 100; % kg dRHS.uE = inf; % solar sail parameters area = 1650; % m2 optical = struct('sigmaS',[0.898 0.865],... 'sigmaD',[0.02 0.035],... 'sigmaA',[0.08 0.098]); emissivity = [0 0.3]; % Add Earth for CRTBP? plotRef = {'Sun' 'Earth'}; % Initialize the ephemeris PlanetPosJPL( 'initialize', kEarth ) % yDot = RHSCRTBP( t, y, mu ) % Initialize the state dRHS.ref = sun; jD0 = Date2JD([2024 8 3 0 0 0]); dT = 10000; tEnd = 5*2e6; % sec, 3e7 % This halo state does not take into account the sail's force [r0, mu, v0] = PlanetPosJPL( 'update', jD0 ); [rH,vH,p] = HALOState( 0.005,0.01,0,0, 'SEM', 1, 0 ); % non-dimensional rH = rH*Mag(r0); vH = vH*aU/Constant('earth year')*2*pi; % TransSEMRToHelio this was using the unit vector of the sun backwards!! % deltas from Earth position may be in ecliptic [rECI,vECI] = TransSEMRToEq( jD0, rH, vH ); x = [rECI;vECI;massFuel]; dRHS.mu(1) = mu; % set the mu for the right planet % Set the Julian date for the dynamical model dRHS.jD0 = jD0; % Simulation steps n = ceil(tEnd/dT);
Setup the camera data structure
dCam = NavigationCamera; dGPS = MeasGPS; dGS = MeasRangeGroundStation; dOM = MeasStarAngleAndChord;
Add noise
dCam.camera.sigmaXY = 1; dCam.camera.noise = true; dCam.namePlanet = {'Earth' 'Sun'}; % Earth? dCam.radiusPlanet = [rE rS];
Set up the displays
TimeDisplay('initialize','ONS Simulation',n); if( viewersOn ) hNav = StarCameraViewer('initialize','Navigation Camera', n ); %#ok<*UNRCH> end % The time vector t = (0:n-1)*dT;
Setup Optical Navigation
dONS = OpticalNavigation; r = x(1:3); v = x(4:6); dONS.ukf.fData = RHSUKFHelioMission; dONS.ukf.fData.jD0 = dRHS.jD0; dONS.target = sun; % 1 or 2? dONS.ukf.fData.ref = sun; % Initialize ONS dONS = OpticalNavigation( 'initialize', dONS, r, v, dT ); meas.optical = NavigationCamera( r, dCam ); % Set up the parameters in ONS dONS.t = t(1); dONS.useUKF = true; dONS.ukf.useOptical = false; dONS.ukf.useState = false; dONS.ukf.usePos = false; dONS.ukf.f = @RHSUKFHelioMission; dONS.aBody1 = rE; dONS.aBody2 = rS; dONS.rSwitch = 1e10; % km Switching distance between the two targets % Plotting arrays xP = zeros(21,n); target = zeros(1,n); type = zeros(1,n); nStars = zeros(1,n);
Run the simulation
hLast = dT; for k = 1:n % ONS simulation TimeDisplay('update',k); % Determine if the spacecraft has hit the ground h = Mag(x(1:3))-rS; % Get data for plotting [~,~,~,acc] = RHSHelioMission(x,t(k),dRHS); % Get the location and velocity of Earth [rEarth,~,vEarth] = PlanetPosJPL( 'update', jD0 + t(k)*secToDay ); if( dRHS.ref == earth ) dCam.xPlanet = [[0;0;0] -rEarth]; rEarth = [0;0;0]; vEarth = [0;0;0]; else dCam.xPlanet = [rEarth [0;0;0]]; end % Stop on landing if( h <= 0 ) break; end % The camera boresight points at the target xCam is in the ECI frame rCam = x(1:3); vCam = x(4:6); % Needed to point the camera dONS = OpticalNavigation( 'get unit vector', dONS, rEarth, vEarth, rCam, vCam ); % Get the measurements meas.jD0 = jD0 + t(k)*secToDay; meas.state = x(1:6); meas.acc = acc; dCam.q = U2Q(dONS.uC,[0;0;1]); dOM.cam = NavigationCamera( rCam, dCam ); dOM.type = dONS.type; dOM.target = dONS.target; dOM.ref = dRHS.ref; dOM.uCamera = dONS.uCamera; dOM.aBody1 = dONS.aBody1; dOM.aBody2 = dONS.aBody2; dOM.r1 = rEarth; dOM.v1 = vEarth; meas.state = x(1:6); meas.acc = acc; % Spacecraft non-gravitational acceleration meas.gps = MeasGPS( x, dGPS ); meas.gs = MeasRangeGroundStation( x, dGS ); meas.optical = MeasStarAngleAndChord( [rCam;vCam], dOM ); % ONS dONS.cam = dOM.cam; dONS.ref = dRHS.ref; dONS.r1 = dOM.r1; dONS.v1 = dOM.v1; dONS.t = t(k); dONS = OpticalNavigation( 'update', dONS, meas, rEarth, vEarth, rCam, vCam ); target(k) = dONS.target; type(k) = dONS.type; nStars(k) = dONS.ukf.optical.nStars; % Display the cameras if( viewersOn ) StarCameraViewer('update', dOM.cam, [], hNav, dCam, k); end xP(:,k) = [x;rEarth;dRHS.thrust;dRHS.ref;h;dONS.x]; % Propagate the state uSun = -Unit(rCam); % SJT is this always true? nB = uSun; % guidance would go here, rotating off sun vector flux = SolarFlx( Mag(rCam)/aU ); [f, T, fT] = SolarPressureForce( area, nB, uSun, flux, optical, emissivity ); dRHS.thrust = fT*1e-3; %x = RK4(@RHSHelioMission,x,dT,t(k),dRHS); [x,hLast] = RK45(@RHSHelioMission,x,hLast,dT,0.1*dT,[],t(k),dRHS); end TimeDisplay('close');
Plotting
% Shorten the vectors if it hits the ground j = 1:k; xP = xP(:,j); t = t(j); target = target(j); type = type(j); nStars = nStars(j); % Make earth and sun referenced positions rSun = zeros(3,k); rEarth = zeros(3,k); j = find(xP(14,:) == earth ); rEarth(:,j) = xP(1:3,j); rSun(:,j) = xP(8:10,j) - rEarth(:,j); j = find(xP(14,:) == sun ); rSun(:,j) = xP(1:3,j); rEarth(:,j) = xP(8:10,j) - rSun(:,j); % Sun/Mars plot HelioPlot( 3, t(end)/secInYear, jD0, xP(1:3,:), {'Spacecraft'} ) PlotSEMTraj( xP(1:3,:), 'ECI', jD0+t*secToDay ) % Time histories [t,tL] = TimeLabl(t); yL = {'x (km)' 'y (km)' 'z (km)'}; yD = {'a_x (km/s^2)' 'a_y (km/s^2)' 'a_z (km/s^2)' 'H (km)' '|a| (km/s^2)'}; yS = {'x (km)' 'y (km)' 'z (km)' 'v_x (km/s)' 'v_y (km/s)' 'v_z (km/s)'}; Plot2D(t,xP(1:6,:),tL,yS,'State'); Plot2D(t,rSun, tL,yL,'Sun Referenced Position'); Plot2D(t,rEarth,tL,yL,'Earth Referenced Position'); Plot2D(t,xP(16:21,:) - xP(1:6,:),tL,yS,'Navigation Error'); Plot2D(t,xP(16:21,:),tL,yS,'Navigation Solution'); NewFig('Targeting') subplot(3,1,1); h = plot(t,target); set(h,'linewidth',2); grid on XLabelS(tL); YLabelS('Target') set(gca,'ytick',[1 2],'yticklabel',{'Mars' 'Sun'}); subplot(3,1,2); h = plot(t,type); set(h,'linewidth',2); grid on XLabelS(tL); YLabelS('Measurement Type') set(gca,'ytick',[1 2],'yticklabel',{'Horizon' 'Center'}); subplot(3,1,3); h = plot(t,nStars); set(h,'linewidth',2); grid on XLabelS(tL); YLabelS('Stars') Figui if( printAll ) n = get(gcf,'number'); for k = 1:n PrintFig(1,4,k,sprintf('%s%d',simName,k)); end end function [rEq,vEq] = TransSEMRToEq(jD, rSEMR, vSEMR) % Transform from SEMR to equatorial, sun-centered frame mu = Constant('mu sem'); % non-dimensional system mass parameter L = Constant('au'); % length unit (1 AU) (km) T = Constant('earth year'); % time unit (Earth year) (sec) muSun = Constant('mu sun'); % km rEq = 0*rSEMR; vEq = 0*vSEMR; for k = 1:length(jD) m{k} = CEcl2Eq(jD(k)); rECI = m{k}*( rSEMR(:,k) - [1-mu; 0; 0]*L ); % position vECI = m{k}*( vSEMR(:,k) );% + [0; 1-mu; 0]*L*2*pi/T ); % velocity [u, r] = SunV2( jD(k), [0;0;0] ); % current sun vector from Earth sunDist = -u*r; % position of Earth rel to sun in km rEq(:,k) = rECI + sunDist; vDirection = m{k}*cross(-u, [0; 0; 1]); % from ecliptic to equatorial vDirection = vDirection/norm(vDirection); vMag = sqrt(muSun/L); vEq(:,k) = vECI - vDirection*vMag; end end %--------------------------------------
ans = Figure (PlotPSS) with properties: Number: 6 Name: 'ECI' Color: [0 0 0] Position: [560 528 560 420] Units: 'pixels' Use GET to show all properties