Code covered by the BSD License  

Highlights from
Giove-A/B Orbit Simulator

from Giove-A/B Orbit Simulator by Thibault Bautze
Real-time and offline orbit simulation of the Giove-A and Giove-B satellites.

gioveabsim
function gioveabsim


% GIOVEABSIM
% June 2009
%
% This function has no input or output arguments.
% It opens a GUI allowing to follow the actual positions of the
% GIOVE-A and GIOVE-B satellites. Screen resultion of 1300 by 900
% is recommended.
% 
% The actual version requires the following MATLAB toolboxes:
% - Mapping toolbox (for elevation())
% - Image Processing Toolbox (for imshow())
% A providing of toolbox independent functions would be greatly 
% acknowledged.
%
% You may tweak the sourcecode to adjust the following information:
% - Receiver Position
% - Receiver Time offset to GMT
% - Path of ephemerides file
% - Path for satellite track recordings
%
% Ephemerides are taken from 
% http://www.celestrak.com/NORAD/elements/galileo.txt
% and should be updated from time to time
%
% The satellite position calculation (calc_satposition_ecef.m) is based 
% on a program from the Institute of Systems Optimization (ITE) at the 
% University of Karlsruhe, Germany (http://www.ite.uni-karlsruhe.de/).
% 
% The calculation of the sidereal time is based on a script from John
% Promersberger (http://www.mathworks.com/matlabcentral/fileexchange/7927).
%
% Transformation from ECEF to LLA is performed with a script from Michael
% Kleder (http://www.mathworks.com/matlabcentral/fileexchange/7941).
%
% This software comes as it is; no warranty is given for any kind of result
% caused by this software. 
%
% Thibault Bautze
% thibault@bautze.com
%


% USERSETTINGS - RECEIVER POSITION
 usersettings.lat = -39.92; %Receiver position (latitude) [deg]
 usersettings.lon = 116.38;  %Receiver position (longitude) [deg]
 usersettings.alt = 0; %Receiver height [m]
 usersettings.gmtd = 1; %Receiver time zone difference to GMT [h]

 % Your ephemerides file
 ephemeridesfile = '.\Subfunctions\galileo.txt';
 
 % Destination of track recordings
 savedatafile = '.\Recordings\GioveAB'; 
 
 % Add path for additional functions 
 path(path,'.\Subfunctions\');



if 1==1 % INIT THE GUI
    f = figure('Visible','off','Position',[60,60,1300,900]);
    set(f,'Name','Giove-A/B Simulator');
    movegui(f,'center'); 

    usersettings.htext.title = uicontrol('Style','text',...
    'String','Giove-A/B Orbit Simulator',...
    'Position',[60,40,700,50],'FontSize',30,...
    'BackgroundColor',[.8 .8 .8]);

    usersettings.htext.title2 = uicontrol('Style','text',...
    'String','User Settings',...
    'Position',[520,350,200,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);
    usersettings.htext.lat = uicontrol('Style','text',...
    'Position',[520,320,200,15]);
    usersettings.htext.lon = uicontrol('Style','text',...
    'Position',[520,300,200,15]);
    usersettings.htext.height = uicontrol('Style','text',...
    'Position',[520,280,200,15]); 




    simustats.htext.title = uicontrol('Style','text',...
    'String','Sim Stats',...
    'Position',[520,200,200,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);
    simustats.htext.counter = uicontrol('Style','text',...
    'Position',[520,180,200,15]);
    simustats.htext.iteration = uicontrol('Style','text',...
    'Position',[520,160,200,15]);
    simustats.htext.time = uicontrol('Style','text',...
    'Position',[520,140,200,15]);
    simustats.htext.empty = uicontrol('Style','text',...
    'Position',[520,120,200,15]); 





    giovea.htext.title = uicontrol('Style','text',...
    'String','Giove-A',...
    'Position',[60,350,200,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);
    giovea.htext.vel = uicontrol('Style','text',...
    'Position',[60,320,200,15]);
    giovea.htext.lat = uicontrol('Style','text',...
    'Position',[60,300,200,15]);
    giovea.htext.lon = uicontrol('Style','text',...
    'Position',[60,280,200,15]);
    giovea.htext.height = uicontrol('Style','text',...
    'Position',[60,260,200,15]);
    giovea.htext.elev = uicontrol('Style','text',...
    'Position',[60,240,200,15]);
    giovea.htext.azim = uicontrol('Style','text',...
    'Position',[60,220,200,15]);
    giovea.htext.range = uicontrol('Style','text',...
    'Position',[60,200,200,15]);
    giovea.htext.relvel = uicontrol('Style','text',...
    'Position',[60,180,200,15]);
    giovea.htext.ephemdate = uicontrol('Style','text',...
    'Position',[60,160,200,15]);

    gioveb.htext.title = uicontrol('Style','text',...
    'String','Giove-B',...
    'Position',[290,350,200,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);
    gioveb.htext.vel = uicontrol('Style','text',...
    'Position',[290,320,200,15]);
    gioveb.htext.lat = uicontrol('Style','text',...
    'Position',[290,300,200,15]);
    gioveb.htext.lon = uicontrol('Style','text',...
    'Position',[290,280,200,15]);
    gioveb.htext.height = uicontrol('Style','text',...
    'Position',[290,260,200,15]);
    gioveb.htext.elev = uicontrol('Style','text',...
    'Position',[290,240,200,15]);
    gioveb.htext.azim = uicontrol('Style','text',...
    'Position',[290,220,200,15]);
    gioveb.htext.range = uicontrol('Style','text',...
    'Position',[290,200,200,15]);
    gioveb.htext.relvel = uicontrol('Style','text',...
    'Position',[290,180,200,15]);
    gioveb.htext.ephemdate = uicontrol('Style','text',...
    'Position',[290,160,200,15]);

    simsettings.htext.title = uicontrol('Style','text',...
    'String','Sim Settings',...
    'Position',[780,350,200,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);


    onoffbutton = uibuttongroup('visible','on',...
    'unit','pixels','Position',[800 310 150 30]);
    u0 = uicontrol('Style','Radio','String','Online',...
    'pos',[5 5 70 15],'parent',onoffbutton,'HandleVisibility','on');
    u1 = uicontrol('Style','Radio','String','Offline',...
    'pos',[75 5 70 15],'parent',onoffbutton,'HandleVisibility','on');
    set(onoffbutton,'Visible','on');


    timebutton = uibuttongroup('visible','on',...
    'unit','pixels','Position',[800 270 150 30]);
    u0 = uicontrol('Style','Radio','String','Realtime',...
    'pos',[5 5 70 15],'parent',timebutton,'HandleVisibility','on');
    u1 = uicontrol('Style','Radio','String','Set time',...
    'pos',[75 5 70 15],'parent',timebutton,'HandleVisibility','on');
    set(timebutton,'Visible','on');


    savedatabutton = uibuttongroup('visible','on',...
    'unit','pixels','Position',[800 230 150 30]);
    savedatacheck = uicontrol('Style','checkbox','String','Save offline data',...
    'pos',[5 5 140 15],'parent',savedatabutton,'HandleVisibility','on');
    set(savedatabutton,'Visible','on');




    offline.htext.starttimeyear = uicontrol('Style','edit',...
    'Position',[780,190,25,19],'FontSize',12,...
    'String','09');      
    offline.htext.starttimemonth = uicontrol('Style','edit',...
    'Position',[810,190,25,19],'FontSize',12,...
    'String','05'); 
    offline.htext.starttimeday = uicontrol('Style','edit',...
    'Position',[840,190,25,19],'FontSize',12,...
    'String','28');      
    offline.htext.starttimehour = uicontrol('Style','edit',...
    'Position',[870,190,25,19],'FontSize',12,...
    'String','10');      
    offline.htext.starttimeminutes = uicontrol('Style','edit',...
    'Position',[900,190,25,19],'FontSize',12,...
    'String','20'); 
    offline.htext.starttimeseconds = uicontrol('Style','edit',...
    'Position',[930,190,25,19],'FontSize',12,...
    'String','0');    


    offline.htext.endtimeyear = uicontrol('Style','edit',...
    'Position',[780,160,25,19],'FontSize',12,...
    'String','09');      
    offline.htext.endtimemonth = uicontrol('Style','edit',...
    'Position',[810,160,25,19],'FontSize',12,...
    'String','05'); 
    offline.htext.endtimeday = uicontrol('Style','edit',...
    'Position',[840,160,25,19],'FontSize',12,...
    'String','30');      
    offline.htext.endtimehour = uicontrol('Style','edit',...
    'Position',[870,160,25,19],'FontSize',12,...
    'String','10');      
    offline.htext.endtimeminutes = uicontrol('Style','edit',...
    'Position',[900,160,25,19],'FontSize',12,...
    'String','20'); 
    offline.htext.endtimeseconds = uicontrol('Style','edit',...
    'Position',[930,160,25,19],'FontSize',12,...
    'String','0');    



    simsetting.htext.timeresolutiontext = uicontrol('Style','text',...
    'String','Time Resolution [s]:',...
    'Position',[780,115,120,30],'FontSize',9,...
    'BackgroundColor',[.8 .8 .8]);
    simsetting.htext.timeresolution = uicontrol('Style','edit',...
    'Position',[910,130,40,19],'FontSize',12,...
    'String','1');  
    simsetting.htext.acceltext = uicontrol('Style','text',...
    'String','Time gain:',...
    'Position',[780,85,120,30],'FontSize',9,...
    'BackgroundColor',[.8 .8 .8]);
    simsetting.htext.accel = uicontrol('Style','edit',...
    'Position',[910,100,40,19],'FontSize',12,...
    'String','1');  


    simsetting.htext.startbutton = uicontrol('Style', 'pushbutton',...
    'String', 'Start!','Callback',{@startsimcallback},...
    'Position', [830 40 70 25]);        

    

 simsettings.htext.help = uicontrol('Style','text',...
    'String','Help',...
    'Position',[980,350,100,30],'FontSize',20,...
    'BackgroundColor',[.8 .8 .8]);

NL = sprintf('\n');
helptext = ['Online: Display the track of the satellites and update their data for the actual or a set time. Cancel by closing window.',NL,NL,...
'Offline: Raw position calculation for the set start and end time.',NL,NL,...
'Realtime: Uses actual time, based on computer time. Ignored in offline mode.',NL,NL,...
'Set time: specify the start and end time of the simulation for online and offline mode.',NL,NL,...
'Save offline data: check to save satellite positions in ECEF format.',NL,NL,...
'Time resolution: in online mode, advices to wait during two iterations; in offline mode it''s the sampling rate.',NL,NL,...
'Time gain: accelerated time for online mode.'];

simsettings.htext.helptext = uicontrol('Style','text',...
    'String',helptext,...
    'Position',[970,30,270,300],...
    'BackgroundColor',[.8 .8 .8]);

    iptsetpref('ImshowAxesVisible','on');
    hearth = axes('Units','Pixels','Position',[60,440,583,448]); 
    hpolar = axes('Units','Pixels','Position',[730,440,450,450]); 
    % from left, from bottom, width, height
    %    align([hsurf,hmesh,hcontour,giovea.htext.vel,hpopup],'Center','None');


    earthmap=imread('.\Subfunctions\earthstreched.jpg');
    latitude=linspace(-90,90,size(earthmap,1));
    longitude=linspace(-180,180,size(earthmap,2));
    axes(hearth);
    imshow(earthmap,'InitialMagnification',100,'XData',[-180 180],'YData',[-90 90],'Parent', hearth);
    axis normal;
    title('Earth view'); 
    xlabel('Longitude'); 
    ylabel('Latitude');
    hold on;


    axes(hpolar);
    polar(0,80);
    view([90 -90]);
    hold on;


    %Make the GUI visible.
    set(f,'Visible','on')
end
   

% Update the GUI with the Usersettings
    usersettings.y = -usersettings.lat;
    usersettings.x = usersettings.lon;
    if usersettings.x>179 
        usersettings.x = usersettings.x-360; 
    end;

    set (usersettings.htext.lat, 'String' , [ 'Latitude [deg]: ', int2str(usersettings.lat)])
    set (usersettings.htext.lon, 'String' , [ 'Longitude [deg]: ', int2str(usersettings.lon)])
    set (usersettings.htext.height, 'String' , [ 'Altitude [m]: ', int2str(usersettings.alt)])

    oldacttime = zeros(1,6);
    giovea.old_sat_position_ecef = zeros(3,1);
    giovea.oldslantrange = 0;
    gioveb.old_sat_position_ecef = zeros(3,1);
    gioveb.oldslantrange = 0;

    axes(hearth);
    plot(usersettings.x,usersettings.y,'c.');
    drawnow;
    hold on;

  
function startsimcallback(source,eventdata) % Main function
    starttime(1,1) = 2000+str2double(get(offline.htext.starttimeyear,'String'));
    starttime(1,2) = str2double(get(offline.htext.starttimemonth,'String'));
    starttime(1,3) = str2double(get(offline.htext.starttimeday,'String'));
    starttime(1,4) = str2double(get(offline.htext.starttimehour,'String'));
    starttime(1,5) = str2double(get(offline.htext.starttimeminutes,'String'));
    starttime(1,6) = str2double(get(offline.htext.starttimeseconds,'String'));

     %local time, GMT correction comes later
     endtime(1,1) = 2000+str2double(get(offline.htext.endtimeyear,'String'));
     endtime(1,2) = str2double(get(offline.htext.endtimemonth,'String'));
     endtime(1,3) = str2double(get(offline.htext.endtimeday,'String'));
     endtime(1,4) = str2double(get(offline.htext.endtimehour,'String'));
     endtime(1,5) = str2double(get(offline.htext.endtimeminutes,'String'));
     endtime(1,6) = str2double(get(offline.htext.endtimeseconds,'String'));
     endtime(4) = endtime(4) -usersettings.gmtd;  

  if  strcmp('Online',(get(get(onoffbutton,'SelectedObject'),'String')))
     simmode = 'freerun'; 
     if  strcmp('Realtime',(get(get(timebutton,'SelectedObject'),'String')))
         starttime = clock;
         starttime(4) = starttime(4)-usersettings.gmtd;  
         stopsim = 0;
         accel=str2double(get(simsetting.htext.accel,'String'));;
         acttime = starttime;
         pausetime = str2double(get(simsetting.htext.timeresolution,'String'));
     else
         accel=str2double(get(simsetting.htext.accel,'String'));;
         starttime(4) = starttime(4)-usersettings.gmtd;  
         acttime = starttime;
         pausetime = str2double(get(simsetting.htext.timeresolution,'String'));
         stopsim = 1;
      end; 
  else
        simmode = 'offline';
        starttime(4) = starttime(4)-usersettings.gmtd;  
        acttime = starttime;
        pausetime = str2double(get(simsetting.htext.timeresolution,'String'));
        steps=fix(etime(endtime,starttime)/pausetime); 
        savedatacontent.giovea.time=zeros(steps,6);
        savedatacontent.giovea.sat_position_ecef=zeros(3,steps);
        savedatacontent.gioveb.time=zeros(steps,6);
        savedatacontent.gioveb.sat_position_ecef=zeros(3,steps);

  end;

  % Start the simulation subfunction
  giovesim(source,eventdata); 

      
    function giovesim(source,eventdata) %Simuation subfunction
        iteration=0;
        try 
            load '.\Subfunctions\simstats.mat';
            simstats.counter=simstats.counter+1;
            save '.\Subfunctions\simstats.mat' simstats;
        catch ME
            simstats.counter=1;
            save '.\Subfunctions\simstats.mat' simstats;
        end;
     
        set (simustats.htext.counter,  'String',[ 'Simulation #: ', int2str(simstats.counter)]);
        set (simsetting.htext.startbutton,  'String','Running...');

        giovea.ephem = twolines2kepler(ephemeridesfile, 'giovea');  %loading giove-a kepler elements
        gioveb.ephem = twolines2kepler(ephemeridesfile, 'gioveb');  %loading giove-b kepler elements
        set (giovea.htext.ephemdate, 'String' , ['Ephem. date: ' datestr(giovea.ephem.ref_time,31)]);
        set (gioveb.htext.ephemdate, 'String' , ['Ephem. date: ' datestr(gioveb.ephem.ref_time,31)]);
 
        tic;
        
        
        while 1 %beginn while loop

            
            iteration=iteration+1;
                        
            if strcmp(simmode,'freerun')
                pause(pausetime); 
                acttime = starttime;
                acttime(6) = acttime(6) + toc*accel;
                acttime = datevec(datenum(acttime));
                set (simustats.htext.time, 'String' , [ 'Time: ', int2str(acttime)]);
                set (simustats.htext.iteration, 'String' , [ 'Iteration #: ', int2str(iteration)]);
                if (etime(acttime,endtime)>0 && stopsim) 
                    break
                end
            else
                if iteration==steps+1
                    break
                end
                acttime(6) = acttime(6) + pausetime;
                acttime = datevec(datenum(acttime));
                if 0==mod(iteration,100)
                    set (simustats.htext.iteration,  'String',[ 'Progress [%]: ', int2str(iteration/steps*100)]);
                    drawnow;
                end
            end
            
            giovea.sat_position_ecef = calc_satposition_ecef(acttime,'giovea',giovea.ephem);
            gioveb.sat_position_ecef = calc_satposition_ecef(acttime,'gioveb',gioveb.ephem);
            
            if strcmp(simmode,'freerun')
                
                % GIOVE-A CALCULATIONS
                
                giovea.sat_position_lla = ecef2lla(giovea.sat_position_ecef);
                giovea.y=-giovea.sat_position_lla.lat/pi*180;
                giovea.x=giovea.sat_position_lla.lon/pi*180;
                if giovea.x>179 
                    giovea.x=giovea.x-360; 
                end;
                giovea.distance=sqrt(sum((giovea.sat_position_ecef-giovea.old_sat_position_ecef).^2));
                giovea.speed=giovea.distance/etime(acttime,oldacttime);
                giovea.old_sat_position_ecef = giovea.sat_position_ecef;
                [giovea.elevationangle, giovea.slantrange, giovea.azimuthangle] = elevation(usersettings.lat,usersettings.lon,usersettings.alt,giovea.sat_position_lla.lat/pi*180,giovea.sat_position_lla.lon/pi*180, giovea.sat_position_lla.alt);
                giovea.relvel=(giovea.slantrange-giovea.oldslantrange)/etime(acttime,oldacttime);
                giovea.oldslantrange = giovea.slantrange;
                
                % GIOVE-B CALCULATIONS
                
                gioveb.sat_position_lla = ecef2lla(gioveb.sat_position_ecef);
                gioveb.y=-gioveb.sat_position_lla.lat/pi*180;
                gioveb.x=gioveb.sat_position_lla.lon/pi*180;
                if gioveb.x>179 
                    gioveb.x=gioveb.x-360; 
                end;
                gioveb.distance=sqrt(sum((gioveb.sat_position_ecef-gioveb.old_sat_position_ecef).^2));
                gioveb.speed=gioveb.distance/etime(acttime,oldacttime);
                gioveb.old_sat_position_ecef = gioveb.sat_position_ecef;
                [gioveb.elevationangle, gioveb.slantrange, gioveb.azimuthangle] = elevation(usersettings.lat,usersettings.lon,usersettings.alt,gioveb.sat_position_lla.lat/pi*180,gioveb.sat_position_lla.lon/pi*180, gioveb.sat_position_lla.alt);
                gioveb.relvel=(gioveb.slantrange-gioveb.oldslantrange)/etime(acttime,oldacttime);
                gioveb.oldslantrange = gioveb.slantrange;
                
                oldacttime = acttime;
                % UPDATE DISPLAY
                
                 plotsatorbit(giovea, gioveb);
                
                 set (giovea.htext.vel, 'String' , [ 'Velocity [m/s]: ', int2str(giovea.speed)])
                 set (giovea.htext.lat, 'String' , [ 'Latitude [deg]: ', int2str(giovea.sat_position_lla.lat/pi*180)])
                 set (giovea.htext.lon, 'String' , [ 'Longitude [deg]: ', int2str(giovea.sat_position_lla.lon/pi*180)])
                 set (giovea.htext.height, 'String' , [ 'Altitude [km]: ', int2str(giovea.sat_position_lla.alt/1000)])
                 set (giovea.htext.elev, 'String' , [ 'Elevation [deg]: ', int2str(giovea.elevationangle)])
                 set (giovea.htext.azim, 'String' , [ 'Azimuth [deg]: ', int2str(giovea.azimuthangle)])
                 set (giovea.htext.range, 'String' , [ 'Slant range [km]: ', int2str(giovea.slantrange/1000)])
                 set (giovea.htext.relvel, 'String' , [ 'Relative velocity [m/s]: ', int2str(giovea.relvel)])
                 
                 set (gioveb.htext.vel, 'String' , [ 'Velocity [m/s]: ', int2str(gioveb.speed)])
                 set (gioveb.htext.lat, 'String' , [ 'Latitude [deg]: ', int2str(gioveb.sat_position_lla.lat/pi*180)])
                 set (gioveb.htext.lon, 'String' , [ 'Longitude [deg]: ', int2str(gioveb.sat_position_lla.lon/pi*180)])
                 set (gioveb.htext.height, 'String' , [ 'Altitude [km]: ', int2str(gioveb.sat_position_lla.alt/1000)])
                 set (gioveb.htext.elev, 'String' , [ 'Elevation [deg]: ', int2str(gioveb.elevationangle)])
                 set (gioveb.htext.azim, 'String' , [ 'Azimuth [deg]: ', int2str(gioveb.azimuthangle)])
                 set (gioveb.htext.range, 'String' , [ 'Slant range [km]: ', int2str(gioveb.slantrange/1000)])
                 set (gioveb.htext.relvel, 'String' , [ 'Relative velocity [m/s]: ', int2str(gioveb.relvel)])
                 drawnow;
            else
                savedatacontent.giovea.sat_position_ecef(:,iteration) = giovea.sat_position_ecef;
                savedatacontent.gioveb.sat_position_ecef(:,iteration) = gioveb.sat_position_ecef;
                savedatacontent.giovea.time(iteration,:) = acttime; 
                savedatacontent.gioveb.time(iteration,:) = acttime; 
            end
            
                       
        end % holly while-loop
        
                % Do some post-processing tasks
        simduration=toc;
        if strcmp(simmode,'offline')
             set (simustats.htext.iteration,  'String',['Completed in ' num2str(fix(simduration)) ' Seconds']);
            if strcmp(num2str(get(savedatacheck,'Value')),'1')
                eval(['save ',savedatafile,'_',int2str(simstats.counter),'.mat savedatacontent']); %save the data
            end
        end    
         
    end % End simulation subfunction (giovesim)
    set (simsetting.htext.startbutton,  'String','Start!');
end % End main function (startsimcallback)
   
function plotsatorbit(giovea,gioveb) % Subfunction to display satellite track

        axes(hearth);
        plot(giovea.x,giovea.y,'r.');
        plot(gioveb.x,gioveb.y,'b.');
        drawnow;
        legend('Receiver','Giove-A','Giove-B');

        axes(hpolar);
        if giovea.elevationangle>10
            polar(giovea.azimuthangle/180*pi,90-giovea.elevationangle,'r.');
        end;

        if gioveb.elevationangle>10
            polar(gioveb.azimuthangle/180*pi,90-gioveb.elevationangle,'b.');
        end;
        drawnow;
    end % End subfunction (plotsatorbit)

end %gioveabsim

Contact us at files@mathworks.com