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