1=head1 NAME
2
3Astro::App::Satpass2::TUTORIAL - Tutorial on the use of Astro::App::Satpass2
4
5=head1 INTRODUCTION
6
7This package was created to provide a flexible way to predict satellite
8positions, passes, and visibility. Unfortunately, with flexibility comes
9complexity, more often than not. This document's purpose is to get you
10up and running, and walk you through some of the things the package can
11do.
12
13The simplest way to access C<Astro::App::Satpass2> functionality is
14through the F<satpass2> script, and that what this tutorial does.
15
16To get any real use out of this package, you need satellite orbital
17data. The best source is L<https://www.space-track.org/>, but this
18requires registration, so this tutorial will assume you are not
19registered and use data from other sources. Most other sources are
20redistributions of Space Track data, and will not be as up-to-date, but
21are generally good enough for non-critical computations.
22
23=head1 SETUP
24
25The first thing that needs to be done, of course, is to install
26C<Astro::App::Satpass2> itself. The recommended way to do this is
27normally to use one of the F<CPAN> tools. With F<cpan>, the installation
28would be simply
29
30 $ cpan
31 ... front matter ...
32 cpan> install Astro::App::Satpass2
33 ... cpan downloads, tests, and installs this package
34     and all dependencies ...
35 cpan> exit
36
37You could equally well use CPANPLUS (F<cpanp>) or cpanminus (F<cpanm>);
38the choice is yours. If you are using Active State's F<ActivePerl>, you
39should use their F<ppi> tool to install distribution
40F<Astro-App-Satpass2>.
41
42There are several Perl modules that this package considers optional, but
43which will be used if they are available. Unless stated otherwise, the
44examples in this tutorial assume that optional module
45L<Astro::SpaceTrack|Astro::SpaceTrack> is installed, so that you can
46download satellite orbital data directly into C<Astro::App::Satpass2>.
47
48The author also recommends optional module L<Date::Manip|Date::Manip>,
49but since the latest version of this module only installs under Perl
505.10 and above, this tutorial will not assume it is installed. When it
51is not, C<Astro::App::Satpass2> uses a home-grown ISO-8601-ish date
52parser. All dates specified in the examples will be compatible with both
53date parsers.
54
55It does not matter whether you install optional modules before or after
56installing C<Astro::App::Satpass2>; it will use them if it finds them.
57
58=head1 CONFIGURATION
59
60There are several possibilities for configuring C<Astro::App::Satpass2>.
61This tutorial will cover the following:
62
63=head2 Configuring from a F<satpass> initialization file
64
65If you already have configured the initialization file for the
66F<satpass> script packaged in the C<Astro-satpass> distribution,
67C<Astro::App::Satpass2> will read this script, making allowances for at
68least some of the incompatibilities between the two tools.
69
70Since the intent is to remove the F<satpass> compatibility when
71F<satpass> is retired, you may at some time wish to convert your
72F<satpass> initialization file to a C<Astro::App::Satpass2>
73initialization file. To do this from inside the F<satpass2> script,
74simply issue the command
75
76 satpass2> save -changes
77
78The name and location of the saved file depend on your operating system,
79but will be reported when you issue this command. Once the file is
80saved, you can display its location using
81
82 satpass2> initfile
83
84The configuration file's location is actually determined using
85C<< File::HomeDir->my_dist_config( 'Astro-App-Satpass2' ) >>. See the
86L<File::HomeDir|File::HomeDir> documentation for details.
87
88Subsequent runs of the F<satpass2> script will initialize from the new
89file. This form of the C<save> command just saves changes from the
90default configuration. If you wish to save all configuration, omit the
91C<-changes> option.
92
93Be aware that C<save> only saves the configuration of the
94C<Astro::App::Satpass2> object and its related helper objects. If your
95initialization file does other things, like download data and make
96predictions, these will not be written to the new file, and you must add
97them back by hand.
98
99=head2 Configuring manually
100
101Before you do any predictions, C<Astro::App::Satpass2> needs to know
102where you are. The embedded L<Astro::SpaceTrack|Astro::SpaceTrack>
103object will also need some configuration so it knows how to fetch data
104from its various sources.
105
106Specifically, you need your latitude, longitude (from Greenwich
107England), and height above sea level. The height is least critical, and
108any reasonable guess will probably work.
109
110Latitude and longitude can be specified in either decimal degrees (e.g.
11140.5) or degrees, minutes and seconds (e.g. 40d30m0s). B<South> latitude
112and B<West> longitude are negative.
113
114Height is assumed to be in meters, but you can be specify it in feet by
115appending 'ft'. For example, '10' specifies 10 meters, as does '10m',
116but '10ft' specifies 10 feet.
117
118Because it would be painful to specify your position every time you use
119it, C<Astro::App::Satpass2> allows a configuration file. The example
120that follows will end by creating a configuration file and storing the
121configuration in it.
122
123And here, finally, is the example. We make the egregious assumption that
124the President of the United States uses this software, so we use the
125executive mansion as our location.
126
127 $ satpass2
128 ... front matter displayed ...
129 satpass2>
130 satpass2> # This is a comment, as is any line beginning
131 satpass2> # with a hash mark ('#'). Comments and blank
132 satpass2> # lines are ignored.
133 satpass2>
134 satpass2> # Enter the name of our location. This is for
135 satpass2> # information only, and will be displayed by
136 satpass2> # the location command. Command arguments that
137 satpass2> # contain spaces need to be quoted.
138 satpass2> set location '1600 Pennsylvania Ave, Washington DC'
139 satpass2>
140 satpass2> # Set our latitude and longitude.
141 satpass2> set latitude 38d53m55.5s longitude -77d2m15.7s
142 satpass2>
143 satpass2> # Set our height above sea level.
144 satpass2> set height 54.72ft
145 satpass2>
146 satpass2> # Some of our data sources will try to fetch
147 satpass2> # their data from Space Track when we ask for
148 satpass2> # it. We are assuming no Space Track username,
149 satpass2> # so we tell them to just give us what they have.
150 satpass2> spacetrack set direct 1
151 satpass2>
152 satpass2> # Some data sources come either with or without the
153 satpass2> # actual name of the spacecraft. We want the name
154 satpass2> # if it is available.
155 satpass2> spacetrack set with_name 1
156 satpass2>
157 satpass2> # Save our configuration. All we really need to
158 satpass2> # save are the changes from the default.
159 satpass2> save -changes
160 satpass2>
161 satpass2> # We can now exit. When we restart, we will get
162 satpass2> # the configuration we just set up.
163 satpass2> exit
164
165=head2 Geocoding the address
166
167Looking up a latitude and longitude can be a bit of a pain. If you live
168in the United States, C<Astro::App::Satpass2> can geocode your address,
169and then query the U. S. Geological Survey for your height above sea
170level.
171
172This requires two more optional modules:
173L<Geo::Coder::OSM|Geo::Coder::OSM> and
174L<Geo::WebService::Elevation::USGS|Geo::WebService::Elevation::USGS>.
175With these installed, the address entry in the previous example becomes
176
177 satpass2> geocode '1600 Pennsylvania Ave NW, Washington DC USA'
178
179When you issue this command, the geocoded location is displayed,
180formatted as C<set> commands:
181
182 set location '1600 Pennsylvania Avenue Northwest,
183   Washington, District of Columbia USA'
184 set latitude 38.8976989
185 set longitude -77.036553192281
186 set height 18.81
187
188If more than one result is returned, all are displayed but no location
189is set. If no result is returned, an exception is raised.
190
191=head1 PREDICTING PASSES
192
193The main use of this package is probably predicting when satellites are
194going to pass over the observer.
195
196=head2 Visible Passes
197
198This is the functionality that tells you when you can go out and see a
199satellite, assuming clear skies and a satellite large enough to be
200visible. Visible passes require three things to happen:
201
202* The satellite must be above the horizon (of course!),
203
204* The Sun must be shining on the satellite (they do not have lights),
205and
206
207* The Sun must not be shining where you are (otherwise the sky is too
208bright to see the satellite).
209
210The example is for the International Space Station, and we will
211use NASA's predictions of its orbit over the next week as a starting
212point.
213
214 $ satpass
215 ... front matter ...
216 satpass2>
217 satpass2> # Tell the Astro::SpaceTrack object to fetch us
218 satpass2> # all the predicted orbital elements from NASA's
219 satpass2> # Human Space Flight web site. We include the
220 satpass2> # effective date, since the data may include
221 satpass2> # planned changes in orbit.
222 satpass2> spacetrack spaceflight -all -effective
223 satpass2>
224 satpass2> # Make the default pass prediction, which is for
225 satpass2> # seven days starting today at noon.
226 satpass2> pass
227
228You may want to print this information and stick it on your
229refrigerator. C<Astro::App::Satpass2> has something a bit like Unix
230output redirection to get your information into a file:
231
232 satpass2> pass >pass.txt
233
234After which you open F<pass.txt> in some simple editor and print it. A
235word-processing editor will probably not work satisfactorily unless you
236set the entire document to a mono-space font.
237
238You may want a prediction for some specific date. The following example
239does a prediction for the night of April 1 2011 (specifically, for one
240day starting at noon on that day) and saves the output in
241F<april_fool.txt>.
242
243 satpass2> pass '2011/4/1 12:00:00' +1 >april_fool.txt
244
245Note that the date is quoted because of the space between the date and
246the time. If you had L<Date::Manip|Date::Manip> installed, you could
247specify the date more flexibly, as (say) C<'1-Apr-2011 noon'>.
248
249=head2 Different Viewing Conditions
250
251C<Astro::App::Satpass2> assumes a few things about viewing conditions
252where you are. These may or may not be true. If they are not, you can
253change them.
254
255The settings discussed below are part of your configuration, and can be
256saved using
257
258 satpass2> save -changes
259
260as discussed above. If you have already saved your configuration you
261will be asked whether you want to overwrite the old configuration. Any
262answer beginning with 'y' (case-insensitive) will be considered true.
263Any other answer will be considered false.
264
265=head3 The horizon
266
267C<Astro::App::Satpass2> assumes that you do not have a very good
268horizon, and that you can not see a satellite until it is at least 20
269degrees above the horizon, and therefore does not report passes that do
270not get at least 20 degrees above the horizon. If you are at the beach
271you may be able to see to within 5 degrees of the horizon. You can
272configure C<Astro::App::Satpass2> to report passes more than 5 degrees
273above the horizon by
274
275 satpass2> set horizon 5
276
277If you are on the top of a mountain, you may even be able to see a bit
278over the normal horizon. If you can see 2 degrees over the horizon,
279
280 satpass2> set horizon -2
281
282=head3 Twilight
283
284C<Astro::App::Satpass2> does not predict visible passes that occur
285during the day, and it defines day as any time after the start of
286morning twilight and before the end of evening twilight. These in turn
287are defined as the point when the upper limb of the Sun passes above or
288below a given distance below the horizon.
289
290By default, C<Astro::App::Satpass2> uses civil twilight to decide
291whether it is day or night. This is defined as the point at which the
292upper limb of the Sun is 6 degrees below the horizon. For a dimmer
293satellite, you may want to use nautical twilight (9 degrees below the
294horizon) or astronomical twilight (12 degrees below the horizon). You
295can change to nautical twilight using
296
297 satpass2> set twilight nautical
298
299and similarly for astronomical. Or, you can define your own twilight by
300entering it in degrees, remembering that degrees below the horizon are
301negative. If you are looking for the International Space Station, you
302may be able to spot it with the Sun only 3 degrees below the horizon:
303
304 satpass2> set twilight -3
305
306=head2 All Passes
307
308If you are interested in communicating with the satellite rather than
309looking at it, all you care about is whether the satellite is above the
310horizon, not whether it is day or night or whether the satellite is
311illuminated by the Sun. In this case you want to
312
313 satpass2> set visible 0
314
315which turns off the latter two checks and reports any pass of the
316satellite over your location, visible or not. To go back to predicting
317just visible passes,
318
319 satpass2> set visible 1
320
321=head1 IRIDIUM FLARES
322
323I know of no scientific value to these, but they are fun to watch. The
324Iridium constellation is 66 satellites (plus spares) used for satellite
325telephone service. The original-design Iridium satellites are triangular
326prisms, with one main mission antenna leaning out from each face of the
327prism. The main mission antennae are about the size of a door, flat, and
328shiny, and because the satellites are maintained in a precise
329orientation in orbit, it can be predicted when one of these antennae
330will reflect the Sun to a given position. A bright flare can be brighter
331than Venus at its brightest, and under good conditions is visible during
332the day.
333
334=head2 Predicting Flares
335
336Predicting flares is a bit like predicting satellite passes - you
337download the orbital data and predict the flare from the data.
338
339 $ satpass2
340 ... front matter ...
341 satpass2>
342 satpass2> # Download the data on Iridium satellites.
343 satpass2> spacetrack celestrak iridium
344 satpass2>
345 satpass2> # Predict flares for the next seven days,
346 satpass2> # starting today at noon.
347 satpass2> flare
348
349This will take a while, because it has to cover all 66 in-service
350Iridium satellites, 24 hours per day. And this does not include spares,
351which are usually kept under control, just to prove that they work. If
352you want them as well,
353
354 satpass2> flare -spare
355
356If you want a copy of all this to stick on your refrigerator door,
357capture it to a file in the same way you captured the pass data:
358
359 satpass2> flare >flare.txt
360
361If you want to append it to the F<pass.txt> file created for satellite
362passes,
363
364 satpass2> flare >>pass.txt
365
366just as you would under Unix.
367
368But maybe you are not interested in daylight flares. If not,
369
370 satpass2> flare -noday
371
372If you are also not interested in flares at 4:00 AM,
373
374 satpass2> flare -noam -noday
375
376or equivalently,
377
378 satpass2> flare -pm
379
380The C<-am>, C<-day>, and C<-pm> options select which flares are
381reported, by time.  The C<-am> option selects flares from midnight until
382the start of morning twilight; C<-day> selects flares from the start of
383morning twilight to the end of evening twilight, and C<-pm> selects
384flares from the end of evening twilight until midnight.
385
386The options can be negated by prefixing C<no> to the option name (e.g.
387C<-noday>). If you specify no options, they are all considered to be
388asserted. If you specify no asserted options, all unspecified options
389are considered to be asserted.  Otherwise, only explicitly-asserted
390options are considered to be asserted.
391
392If you do not want flares for a particular part of the day, calculations
393for that part of the day are not done. This can speed the prediction
394process.
395
396=head2 Different Flare Visibility
397
398Flare brightness is measured in magnitude, a system used by astronomers
399to measure the brightness of stars. This system goes back a couple
400thousand years, and originally classified the brightest stars as first
401magnitude, the less-bright stars as second magnitude, and so on. The
402system has been formalized to a logarithmic scale in which a brightness
403difference of five magnitudes represents a light intensity difference of
404a factor of 100. Brighter stars may have negative magnitudes (Sirius is
405about -1.4).
406
407Obviously a flare that would be fairly bright at night might be
408completely invisible during the day, so day and night have separate
409settings to control the minimum reportable brightness.
410C<Astro::App::Satpass2> uses the C<flare_mag_day> setting to determine
411the dimmest reportable flare during the day; this defaults to C<-6>. The
412dimmest reportable flare at night is determined by the
413C<flare_mag_night> setting, which defaults to C<0>.
414
415In order to duplicate (fairly closely) the Iridium flares reported by
416L<https://www.heavens-above.com/>, you will want to tweak
417C<Astro::App::Satpass2>'s settings a bit:
418
419 satpass2> set twilight -1.8 flare_mag_night -1
420
421seems to come fairly close.
422
423=head1 OTHER CUSTOMIZATIONS
424
425There are other customizations of the output that you may want.
426
427=head2 Location
428
429If you want to display your location, just issue the
430
431 satpass2> location
432
433command. The output of this can be directed to a file, just as the
434output of any other command. For a nice list of passes and flares for
435your refrigerator door, you can do something like this:
436
437 satpass2> location >this_week.txt
438 satpass2> spacetrack spaceflight -all -effective
439 satpass2> pass >>this_week.txt
440 satpass2> spacetrack celestrak iridium
441 satpass2> flare -pm >>this_week.txt
442 satpass2> exit
443
444=head2 Date and Time Format
445
446By default, date and time are displayed in an ISO-8601-ish format. If
447you want something friendlier, you can specify a C<strftime (3)> format
448independently for the date and the time. These settings can be saved to
449your initialization file just like any other setting.
450
451The date and time format settings belong to the formatter object, which
452is a separate subsystem all to itself. So:
453
454 satpass2>
455 satpass2> # Display the date as weekday day-month-year
456 satpass2> formatter date_format '%a %d-%b-%Y'
457 satpass2>
458 satpass2> # Display the time as 1-12 AM or PM
459 satpass2> formatter time_format '%I:%M:%S %p'
460 satpass2>
461 satpass2> # Save the configuration, overwriting any previous one
462 satpass2> save -changes -overwrite
463
464=head2 The Julian Calendar
465
466No, there were no satellites in orbit when the last known holdout
467(Romania) adopted the Gregorian calendar. But the Sun and Moon have been
468rising and setting much longer than satellites have.
469
470If you install
471L<DateTime::Calendar::Christian|DateTime::Calendar::Christian> and
472properly configure C<satpass2>, you will be able to both parse and
473display dates in both the Gregorian and Julian calendars.
474
475=head3 Parsing Julian Calendar Dates
476
477The primary date parser is L<Date::Manip|Date::Manip>, which does not
478support Julian dates. But if you use the C<ISO8601> parser, you can
479configure it to parse a date as either Julian or Gregorian, depending on
480the date itself.
481
482What you have to do, in general, is use date parser
483L<Astro::App::Satpass2::ParseTime::ISO8601>, and set its
484L<back_end|Astro::App::Satpass2::Utils/back_end> attribute
485to C<'DateTime::Calendar::Christian'>. You must, of course have this
486module installed, and you can shorten the setting to just
487C<'Christian'>.  You should see the documentation for full details, but
488with the C<satpass2> script the configuration would look something like
489this:
490
491 satpass2> # Configure the ISO8601 parser, with back end
492 satpass2> set time_parser ISO8601,back_end=Christian
493
494The L<DateTime::Calendar::Christian|DateTime::Calendar::Christian>
495module takes, as one of the arguments to C<new()>, a reform date, which
496defaults to the date it was first adopted in Italy, on October 15 1582
497(Gregorian). If you want something different you can append it to the
498value of C<back_end> and quote the whole value. The quotes must be
499either escaped or surrounded with outer quotes to protect them from the
500command parser. For example, to set the UK reform date, use
501
502 satpass2> set time_parser "ISO8601,back_end='Christian,reform_date=uk'"
503
504=head3 Formatting Julian Calendar Dates
505
506Here, you need to use the C<DateTime> date formatter, which will be the
507default if the L<DateTime|DateTime> module is installed. Since
508L<DateTime|DateTime> is a prerequisite for
509L<DateTime::Calendar::Christian|DateTime::Calendar::Christian>,
510installing this will make the proper date formatter the default. But
511before you can actually get Julian output dates, you need to configure
512the time formatter to use this class.  Because the date formatter is
513managed by the formatter object, the C<satpass2> commands to configure
514it are
515
516 satpass2> # Configure the time formatter and reform date
517 satpass2> formatter time_formatter \
518 > DateTime::Strftime,back_end=Christian
519
520A non-default reform date is specified the same way as for the parser,
521and the two reform dates need not be the same.
522
523The C<DateTime> C<strftime> formatter also supports, as a special case,
524format pattern C<'%{calendar_name}'>, which renders as either
525C<'Julian'> or C<'Gregorian'> as appropriate. Given
526
527 satpass2> formatter time_format \
528 > '%{year_with_era}-%m-%d %{calendar_name}'
529
530The date of the assassination of Julius Caesar would be displayed as
531
532 '44BC-03-15 Julian'
533
534In point of fact, the way the C<%{calendar_name}> machinery works is
535that if the back end provides the C<is_julian()> method, you get
536C<'Julian'> if that method returns a true value, and C<'Gregorian'> if
537it does not. If the back end does not provide the C<is_julian()> method,
538whatever follows C<'DateTime::Calendar::'> in the back end's class name
539is used. If the back end does not begin with C<'DateTime::Calendar::'>,
540C<'Gregorian'> is used.
541
542Formatting Julian calendar dates in
543L<Astro::App::Satpass2::FormatTime::DateTime::Cldr|Astro::App::Satpass2::FormatTime::DateTime::Cldr>
544is unsupported, because
545L<DateTime::Calendar::Christian|DateTime::Calendar::Christian> lacks the
546C<format_cldr()> method. You may find that it works, because this module
547patches in C<format_cldr()> when it loads
548L<DateTime::Calendar::Christian|DateTime::Calendar::Christian> if it
549finds that that method does not already exist. But you may find that it
550does not work, because the patch messes with the internals of
551L<DateTime::Calendar::Christian|DateTime::Calendar::Christian>, and
552those might change without warning. I<Caveat coder.>
553
554=head1 INTERMEDIATE TOPICS
555
556This section covers things that are beyond just getting the application
557up and running.
558
559=head2 Time Zones
560
561By default, times are reported in your local zone. Summer time/daylight
562saving time is accounted for (unless the underlying Perl is broken),
563even when predictions cross the boundary between standard and summer
564time. But you may want some other zone. There are two cases here,
565depending on what optional modules you have installed.
566
567Without any optional modules, the only supported zone other than your
568default local zone is GMT. You can get GMT output by
569
570 satpass2> formatter gmt 1
571
572The default ISO-8601-ish time parser does not have a corresponding
573setting, but does allow you to append a C<'Z'> to the time to specify
574GMT.
575
576The default formatter object also has a C<tz> setting, but this is
577unsupported because it relies on the C<TZ> environment variable, and the
578author has no control over whether your OS' POSIX code supports this.
579You can try it with something like
580
581 satpass2> formatter tz MST7MDT
582
583(for Mountain time). If it works, fine. If not, you can make it work by
584installing L<DateTime|DateTime> and
585L<DateTime::TimeZone|DateTime::TimeZone>. Doing this also gives you the
586Olson database zone names (e.g. C<America/New_York>) if you prefer
587these.
588
589Similarly, if you install the optional L<Date::Manip|Date::Manip>
590module, you can set a default input zone other than your own by
591something like
592
593 satpass2> time_parser tz MST7MDT
594
595The C<time_parser> and C<formatter> time zones are set separately not
596only so that you can make them different, but because the author can not
597guarantee that the underlying modules will accept the same settings.
598
599=head2 Command Macros
600
601A command macro is simply a named set of C<Astro::App::Satpass2>
602commands, somewhat like a C<bash> shell function. A command macro is
603executed by giving its name, so in essence command macros are ways of
604creating new commands.
605
606The definition of a macro is simply the list of commands it issues. Each
607command is a single argument, and therefore probably needs to be quoted.
608When the command to be issued itself contains quotes, you either use a
609different style (single versus double quotes) or you escape the quote
610mark with a back slash (C<'\'>). A simple macro definition would be
611something like
612
613 satpass2> macro defined hi 'echo "Hello world!"'
614
615When a command macro is executed it can be passed arguments. The details
616of how these work will be deferred for the sake of getting on with the
617tutorial, but a case of interest is the fact that C<"$@"> (the quotes
618being part of the syntax) expands to all the arguments passed to the
619macro.
620
621=head2 Multiple Locations
622
623What this topic actually describes is a way to have multiple locations
624on tap, so that if you are going to be at point 'A' from Monday through
625Wednesday, and point 'B' Thursday and Friday you can easily switch
626between them.
627
628The first thing our hypothetical user needs is a command macro to set
629the location to his or her home location. The definition comes from our
630first example:
631
632 satpass2> macro define home \
633 > "set location '1600 Pennsylvania Ave, Washington DC'" \
634 > "set latitude 38d53m55.5s longitude -77d2m15.7s" \
635 > "set height 54.72ft"
636 satpass2>
637
638Normally, this would all have to go on the same line, but
639C<Astro::App::Satpass2> recognizes an end-of-line back slash as a
640continuation mark, so all four lines above are parsed as though they are
641the same line. C<Astro::App::Satpass2> changes the prompt for a
642continuation line, just to keep you on your toes.
643
644Now we need another place to visit -- say, the residence of the Prime
645Minister of Canada:
646
647 satpass2> macro define sussex_drive \
648 > "set location '24 Sussex Drive, Ottawa, ON'" \
649 > "set latitude 45.444348 longitude -75.693934" \
650 > "set height 50m"
651 satpass2>
652
653Now, to switch locations to the Prime Minister's residence, just say
654
655 satpass2> sussex_drive
656 satpass2>
657 satpass2> # and to confirm it,
658 satpass2> location
659 Location: 24 Sussex Drive, Ottawa, ON
660           Latitude 45.4443, longitude -75.6939, height 50 m
661 satpass2>
662
663And to return home, just say
664
665 satpass2> home
666
667Of course, these are really only useful if they are in your
668initialization file. And they can be, with the usual incantation:
669
670 satpass2> save -changes -overwrite
671
672=head2 Temporary Settings
673
674As you recall from the section on L<IRIDIUM FLARES|/IRIDIUM FLARES>, if
675you are trying to imitate the results from Heavens Above you have to
676tweak the default settings a bit. These settings stay tweaked until you
677put them back to their original values. If you always want the tweaks
678when you do Iridium flare predictions, you can put them into a command
679macro along with the flare prediction. Values of settings can be
680localized to a macro (among other things), so that the old values are
681restored when the macro exits. The example could be defined as a command
682macro like this:
683
684 satpass2> macro define iridium_flare \
685 > 'localize twilight flare_mag_night' \
686 > 'set twilight -1.8 flare_mag_night -1' \
687 > 'flare "$@"'
688 satpass2>
689
690Note the use of single quotes rather than double quotes to enclose the
691C<flare> command. In double quotes, or outside quotes altogether, the
692C<$> is magical, and introduces something to be interpolated into the
693command. Exactly what is interpolated depends on what follows the C<$>.
694The C<$@> is replaced by the arguments of the command macro (or
695whatever), but we do not want this to happen until the command macro is
696expanded. Enclosing the C<$@> in double quotes ensures that macro
697arguments containing spaces remain single arguments; without the double
698quotes they would become multiple arguments.
699
700So if you say
701
702 satpass2> iridium_flare -noam 'today 12:00' +3
703
704The C<twilight> and C<flare_mag_night> settings will be changed, the
705flare prediction will be run, and the old C<twilight> and
706C<flare_mag_night> settings will be restored. Because the macro
707arguments get passed to the C<flare> command, the prediction will be for
708the three days starting at noon today, and will exclude flares occurring
709between midnight and the beginning of morning twilight.
710
711Note that B<only> attributes of the C<Astro::App::Satpass2> object
712(those set with a C<set> command) can be localized; attributes of helper
713objects can not be. But you B<can> localize the entire helper object.
714For example, for a temporary change to the
715L<Astro::SpaceTrack|Astro::SpaceTrack> object,
716
717 satpass2> localize spacetrack
718
719inside the appropriate scope. Yes, you can localize outside a command
720macro (or any other localization scope, such as inside a C<source> file
721or a C<begin>-C<end> block), but it does no good to do so, because the
722old value is not restored until you exit, and what good is that?
723
724=head2 Reporting Position
725
726By default, anything that reports a satellite position does it in
727elevation, azimuth and range. You may want some other units, such as
728right ascension and declination.
729
730Deciding what to display is the job of the C<formatter> helper object.
731Normally this is an
732L<Astro::App::Satpass2::Format::Template|Astro::App::Satpass2::Format::Template>,
733and for the full story you should see the documentation to that class.
734
735But there are a number of prepackaged coordinate sets:
736
737 az_rng --------- azimuth (with bearing) and range
738 azel ----------- elevation and azimuth (with bearing)
739 azel_rng ------- elevation, azimuth (with bearing) and range
740 equatorial ----- right ascension and declination
741 equatorial_rng - right ascension, declination and range
742
743By default, you get C<azel_rng>, but you can get any of the others via
744the L<local_coord()|Astro::App::Satpass2::Format/local_coord>
745method of the formatter object. For example, if you want right
746ascension, declination and range, just
747
748 satpass2> formatter local_coord equatorial_rng
749
750=head2 User-defined Position Coordinates
751
752L<Astro::App::Satpass2::Format::Template|Astro::App::Satpass2::Format::Template>
753defines these local coordinates in terms of L<Template-Toolkit|Template>
754templates, so you can add definitions, or change the existing
755definitions, in the same way that you would change one of the reporting
756templates, using that formatter's
757L<template()|Astro::App::Satpass2::Format::Template/template> method.
758For example, to make C<azel> report azimuth first,
759
760 satpass2> formatter template azel <<'EOD'
761 > [% data.azimuth( bearing = 2 ) %]
762 >     [%= data.elevation %]
763 > EOD
764
765See the
766L<Astro::App::Satpass2::FormatValue|Astro::App::Satpass2::FormatValue>
767documentation for what format effectors are available. Inside the
768template, the C<data> object will contain the data you want to format.
769
770=head1 ADVANCED TOPICS
771
772=head2 Code Macros
773
774In addition to L<Command Macros|/Command Macros>, a macro can be defined
775using Perl code. This allows one to add new functionality to
776C<Astro::App::Satpass2>, over and above that provided by interactive
777methods.
778
779Code macros are currently unsupported, though it might be better to call
780them experimental. The real situation is that I have been looking for
781ways to plug bits of code into the system, and handling them like macros
782seemed to be the best way. So I knocked something together along those
783lines, and played with it. Further experience may show that the
784interface or the implementation was ill-chosen, or even that there is
785something deeply flawed about the whole idea. The bottom line is that if
786you want this to become supported, you should tell me what you like or
787do not like about it.
788
789In order to implement code macros, a number of previously-private
790methods of L<Astro::App::Satpass2|Astro::App::Satpass2> have been
791exposed. The names of these begin with a double underscore (C<__>), and
792these are documented as unsupported. These will not go away even if code
793macros do, but their calling sequences may change. On the other hand, if
794code macros become fully supported, these will too.
795
796A code macro is simply a Perl subroutine which is called by
797C<Astro::App::Satpass2> more or less as though it were an interactive
798method. In the following discussion, some words are used with particular
799meanings:
800
801=over
802
803=item must
804
805means that the code macro will not work unless this is done;
806
807=item should
808
809means that the code macro will work without doing this, but you might
810not like the results;
811
812=item may
813
814means that the code macro will work without doing this, but you might
815want the functionality described.
816
817=back
818
819Now, Perl subroutines do not live in a vacuum. They in fact live in Perl
820modules; that is, F<.pm> files defining a C<package> whose name reflects
821the path name of the file. A module that defines a code macro can be
822installed like a normal Perl module, but can also live in the F<lib/>
823directory in the user's C<Astro::App::Satpass2> configuration directory
824(which is the default for C<< $satpass2->macro( load => ... ) >>), or
825anywhere if you specify the location via the C<lib> option (e.g.
826C<< $satpass2->macro( load => { lib => something }, ... >>).
827
828In addition to the things that go into making a Perl module, a module
829that provides code macros:
830
831=over
832
833=item must be a subclass of C<Astro::App::Satpass2>;
834
835=item must import C<__arguments()> from C<Astro::App::Satpass2::Utils>.
836
837=back
838
839In order to work as a code macro, a subroutine:
840
841=over
842
843=item must have the C<Verb()> attribute
844
845Subroutine attributes are declared after the name (and signature if any)
846and a colon.
847
848The contents of the parentheses that follow the attribute name will be
849split on white space and used as L<Getopt::Long|Getopt::Long> option
850specifications should these be needed to process the subroutine's
851arguments.
852
853=item may have the C<Configure()> attribute
854
855If this attribute is present, the contents of the parentheses will be
856used to configure the L<Getopt::Long|Getopt::Long> object prior to
857processing the subroutine's arguments.
858
859=item must call C<__arguments()> to unpack C<@_>
860
861This subroutine is imported from
862L<Astro::App::Satpass2::Utils|Astro::App::Satpass2::Utils>. See this
863documentation for details of its use.
864
865=item should report warnings and exceptions properly
866
867In order to have warnings and exceptions be handled consistently with
868the rest of C<Astro::App::Satpass2>, C<< $self->whinge() >> should be
869called instead of C<warn> or C<Carp::carp()>, C<< $self->wail() >>
870should be called instead of C<die> or C<Carp::croak() >>, and
871C<< $self->weep() >> instead of C<Carp::confess() >>.
872
873=item must return human-readable results
874
875This almost goes without saying, since it is the string returned by the
876subroutine which will be displayed.
877
878=back
879
880The arguments passed to your code macro will be, in order, the invoking
881C<Astro::App::Satpass2> object, a reference to the hash generated by
882parsing the arguments, and the non-option arguments, in order.
883
884Your package B<may> define a  code macro named C<after_load()>. If this
885is defined, it will be called as soon as the package has been
886successfully loaded. The arguments will be those of the C<macro load>
887itself.
888
889You should be aware that the first argument to your code macro
890subroutine is the C<Astro::App::Satpass2> object that called it. This is
891B<not> reblessed into the package that contains the code macro, so it is
892not an invocant in the usual sense. This has several implications,
893including:
894
895=over
896
897=item * You can not call other code in your module as methods;
898
899This is a direct result of the "invocant" not being blessed into the
900name space of your module.
901
902=item * Your code macro can not be called as a method;
903
904This is because nothing has been done to make it appear in the
905invocant's name space.
906
907=item * Your code can not recurse, even indirectly via a command macro.
908
909This is because all macros become undefined within the scope of their
910own execution, so that a macro of any sort that redefines an interactive
911method has access to the original method.
912
913=back
914
915If you want to call your code macro from inside Perl code, you must call
916it as
917
918 $satpass2->dispatch( your_code_macro => ... );
919
920and capture any output that is returned. Note that you can still specify
921options either command-line style or as a hash reference in the second
922argument to C<dispatch()>.
923
924You should be cautious about calling C<dispatch()> inside your code
925macro, except perhaps as C<< return $self->dispatch( ... ) >>. If you
926call it internally, you probably need to be sure you concatenate the
927output of your calls, and return that.
928
929A number of methods of L<Astro::App::Satpass2|Astro::App::Satpass2> may
930be useful in your code macro, and in fact were exposed for the use of
931code macros. These include:
932
933=over
934
935=item L<__choose()|Astro::App::Satpass2/__choose>
936
937This can be used to obtain bodies from the observing list or the sky,
938optionally filtered. See especially the C<bodies> and C<sky> options.
939
940=item L<__format_data()|Astro::App::Satpass2/__format_data>
941
942This can be used to pass the raw data generated by your code macro to a
943C<Template-Toolkit> template. It returns the resultant text.
944
945=item L<__parse_angle()|Astro::App::Satpass2/__parse_angle>
946
947This can be used to parse angle arguments. The return is (usually) the
948angle in degrees.
949
950=item L<__parse_distance()|Astro::App::Satpass2/__parse_distance>
951
952This can be used to parse distance arguments. The return is the distance
953in kilometers.
954
955=item L<__parse_time()|Astro::App::Satpass2/__parse_time>
956
957This can be used to parse time arguments. The return is a Perl time.
958
959=back
960
961=head1 AUTHOR
962
963Thomas R. Wyant, III F<wyant at cpan dot org>
964
965=head1 COPYRIGHT AND LICENSE
966
967Copyright (C) 2011-2021 by Thomas R. Wyant, III
968
969This program is free software; you can redistribute it and/or modify it
970under the same terms as Perl 5.10.0. For more details, see the full text
971of the licenses in the directory LICENSES.
972
973This program is distributed in the hope that it will be useful, but
974without any warranty; without even the implied warranty of
975merchantability or fitness for a particular purpose.
976
977=cut
978
979# ex: set textwidth=72 autoindent :
980