Scripting Guide - Kick Start

Note: Most of the samples shown here are complete scripts. You can type them into Notepad, save them, and run them from the ACP scripting window. Of course, you can use the "meat" of the example in your own scripts. I used VBScript for the samples, as it is the simplest of the languages, and this section is for beginners.

An Old Salt's Tips for Learning and Having Fun

I wrote my first computer program (for the IBM 1401) when I was 18. I've been programming computers continuously ever since. Obviously I love it. Along the way, I've had to learn tons of languages, operating systems, development systems, and new ways of thinking about things. Learning doesn't have to be scary, it can be fun. Amateur astronomy is about learning and doing as well, right? Those of us over 50 know that learning is what keeps us from rusting out! For younger people, learning is what creates new opportunities. OK, enough soap box.

Once you learn your second computer language, or your second operating system, you discover that it's not nearly as painful as the first. Subsequent ones become even easier. All of these systems and languages have commonalties, just like spoken languages and socio-economic systems.

  1. The keys to any new system are contained in the documentation. Here's the first and most important tip:
    Skim read the documentation first thing, before doing any designing or coding.

    This is extremely important. Skim-read, don't try to remember anything, just expose yourself to what's there. If you relax and browse through the docs, you'll subconsciously absorb key concepts and form abstract ideas. Later on, while you're designing and coding, you'll face situations where you need to do something that appears difficult. Quite often a light bulb will go off: "I remember seeing something about ____ in the docs. Let's see now..." You know where things are more or less, and you know that there is a nugget in there somewhere. Discovery is fun!

  2. You can't learn to drive a car from a book, right? Here's my second tip:
    Play with the system, language, and samples before tackling your primary project.

    The chances of your designing and coding something useful are nil if you think you can read the docs and then build the program. Forget it. You really need to play around with the development system, the language, the samples(!), and the "library" and/or "object models". Write some small programs that do simple things. Play with the debugger if that's available. This isn't contradictory to (1); I said "skim read" there.

  3. It's virtually impossible to understand the depth and character of the problem until you try to solve it. Writing a program to handle a task always uncovers things about the task that you didn't understand when you started. So here's my third tip:
    Plan to throw the first one away.

    and its corollary

    Never make a prototype good enough to ship.

    When you get to the point where you're saying to yourself "If I'd only known that I would have done things differently!"... consider doing things differently. This is what I did in moving from ACP4 to ACP5, with a whole new engine under the hood and the new "Web 2.0" web content. Be a pro. As said in The Gambler, learn to know when to hold 'em and when to fold 'em. And if you're working for someone else as a programmer, don't ever let them ship your prototype. They will do it if possible, and blame you for the results.

Choice of Language

Although VBScript is used for the examples in this document, I strongly recommend that you consider using JScript for all of your scripting work. If you have any doubts, spend some time looking at the observing plan compiler in Plan.wsc, and the observing engine in AcquireImages.js. JScript (also known as ECMAScript and JavaScript) is an enormously powerful and flexible language. The error handling (try/catch/finally) is reason enough to dump VBScript for JScript. Add the 'expando' properties on objects, the superior structured programming statements, and the fact that all scripts, components, and web Active Server Pages for ACP in the future will be done in JScript makes it irresistible.

What's with the dots? Objects and Components

You may be wondering what the dots mean in the sample programs. Object oriented systems deal with objects which have properties and methods. In ACP scripts, for example, there is a Telescope object, which represents an ASCOM compatible programmable telescope (the one currently configured and connected via ACP). To find out what your scope's current right ascension is, you use the Telescope.RightAscension property:

  RA = Telescope.RightAscension
For properties, the dot is sort of like the possessive apostrophe in English. You can read Telescope.Declination as "the scope's current declination". I read it "telescope dot declination" because I am a propeller head.

A method is like a function call, except it is offered or supported by a specific object. Different objects may have methods with the same name. To call a method, prefix the method call with the object name and a dot. For example, to move the scope to a given RA and Dec:

  Telescope.SlewToCoordinates(RA, Dec)
or
  Telescope.TargetRightAscension = RA
  Telescope.TargetDeclination = Dec
  Telescope.SlewToTarget

With this in mind, consider the various objects out there as widgets that represent something, provide some related services, etc. Each object has its set of properties and methods. Some properties can only be read. Telesccope.RightAscension is read-only. Now skim-read the documentation on each of ACP's built-in objects and for the ASCOM Standard Telescope interface (included in ACP online help). Be a pro, skim-read the docs before diving in.

Get typed input from the script console

Have a look at Console.ReadLine, and Console.PrintLine.
Sub Main()
  Console.ReadLine "Enter some text:", 3     ' OK button only
  Console.PrintLine Console.LastReadResult
End Sub
Try different values for the second parameter to Console.ReadLine.

Speak the scope's current RA and Dec

Here's how to use the Voice.SpeakHours() and Voice.SpeakDegrees() methods for speaking hours and angles in "sexagesimal" form. Note that the Telescope.RightAscension and Telescope.Declination properties are double-precision numbers, not text. Connect ACP to your scope or use the Telescope Simulator, then run this:
Sub Main()
  Voice.Speak "RA is "
  Voice.SpeakHours Telescope.RightAscension
  Voice.Speak ", deck is "
  Voice.SpeakDegrees Telescope.Declination
End Sub

Creating an Object for Use

Before using some objects, you first need to create an instance for your use. The Console and Voice objects used above are pre-created ("intrinsic") by ACP for all scripts running in the ACP console. To use other objects, you need to create an instance. For example, to read a text file, you use the Scripting Runtime objects (as described in the VBScript and JScript documentation). The following script simply echoes the contents of a file (the script itself) to the ACP script console. Create the script and call it self.vbs (save it in ACP's scripts subdirectory) then run it from the console.
Sub Main()
  Dim f, fso
  Set fso = CreateObject("Scripting.FileSystemObject")
  Set f = fso.OpenTextFile(ACPApp.Path & "\scripts\self.vbs")
  While Not f.AtEndOfStream
    Console.PrintLine f.ReadLine()
  Wend
  f.Close
End Sub
Note the use of Set in creating the FileSystemObject object, and assigning the TextStream object returned by the OpenTextFile() method. In VBScript, you need Set any time you assigning an object to a variable! This will annoy you till you get used to it. This is not needed in JavaScript. Other languages handle object variable assignment in various ways.

Mine the Web for Data in 4 lines

This little script uses the Microsoft Internet Transfer Control to grab data from a web site. In this case, the data is the weather at the remote controlled Berkeley/Lick KAIT telescope, which is used for supernova hunting. NOTE: The XMLHTTP object is part of the Microsoft XML engine 4.
Sub Main()
  Set x = CreateObject("MSXML2.XMLHTTP")
  x.open "Get", "http://astron.berkeley.edu/~bait/weather/weatherd.dat", False
  x.send
  If x.Status = 200 Then
    Console.PrintLine x.ResponseText
  Else
    Console.PrintLine x.Status & " " & x.StatusText
  End If
End Sub

Convert J2000 coordinates to local topocentric

This illustrates using an external ASCOM gadget, the USNO NOVAS-COM Astrometric Component (see the docs in the Program Files\Common Files\ASCOM\NOVAS\Doc directory). We use the VBScript CreateObject() function to create a couple of the objects supported by NOVAS-COM: a Site object and a Star object. We set the properties of each, then use Star.GetTopocentricPosition() method to create a PositionVector object containing the star's coordinates for the current date/time and observing site. Note the computation of the Terrestrial Julian Date. Check out the ACP docs covering Date and Time Systems at the beginning of the Util object info.

The results are suitable for high-precision pointing operations. The corrections include precession, nutation and proper motion. The transformation is for Altair. See the comments in the code for additional tidbits.

Study this at length. It is meaty. Run it and see how much the correction is (it won't be much). Play around with the Julian date by replacing Util.SysJulianDate with an arbitrary Julian date and see how the correction changes.

Sub Main()

  ' Site represents the scope's current site location
  Set Site = CreateObject("NOVAS.Site")
  Site.Latitude = Telescope.SiteLatitude
  Site.Longitude = Telescope.SiteLongitude
  Site.Height = 0     ' Should be height in meters MSL

  ' UJD is the current UTC-based Julian Date
  ' TJD represents the current Terrestrial Julian Date
  ujd = Util.SysJulianDate
  ' Util.DeltaT is in seconds, convert to days
  tjd = ujd + (Util.DeltaT(ujd) / 86400)

  ' Star represents Altair (J2000 epoch)
  ' Data taken from FK5 (high prec)
  Set Star = CreateObject("NOVAS.Star")    
  Star.RightAscension = 19.8463894444 ' hours
  Star.Declination = 8.8683416667     ' degrees
  Star.ProperMotionRA = 3.63          ' sec/century
  Star.ProperMotionDec = 38.6         ' arcsec/century
  Star.Parallax = (16.6 / 3.262)      ' parsec (16.6ly)
  Star.RadialVelocity = -26           ' KM/sec
    
  ' Creating a vaPositionVector for Topocentric coords
  Set StarTopo = Star.GetTopocentricPosition(tjd, Site)

  ' Print Results
  Console.PrintLine "J2000 coordinates for Altair:"
  Console.PrintLine "RA  = " & Hours_HMS(Star.RightAscension)
  Console.PrintLine "Dec = " & Degrees_DMS(Star.Declination)
  Console.PrintLine "Topo position at UTC Julian date " & ujd
  Console.PrintLine "RA  = " & Hours_HMS(StarTopo.RightAscension)
  Console.PrintLine "Dec = " & Degrees_DMS(StarTopo.Declination)

End Sub

Start Excel, open a spreadsheet, and get data from it

Suppose you have a catalog or observing list in an Excel spreadsheet. On the right is a snippet of an Excel spreadsheet called my-cat.xls.

Here is a very simple script that grabs the data directly from the cells of the spreadsheet and prints it on the ACP scripting console:

Sub Main()
  Set sheet = GetObject("c:\my-cat.xls").ActiveSheet
  For i = 2 to 3
    Console.PrintLine _
          "Obj: " & sheet.cells(i,1) & vbCrLf & _
          "RA:  " & (sheet.cells(i,2) * 24) & vbCrLf & _
          "Dec: " & sheet.cells(i,3) & vbCrLf
  Next
End Sub
This will reference whatever sheet appears when the file is first opened. If you have more than one worksheet in the XLS file, specify the sheet by replacing .ActiveSheet with .Sheet("SheetName"). Why the multiplication by 24 for the RA? The RA in the spreadsheet is in the form of a Date/Time, which is represented internally in Excel (and VB and all scripting languages as well) as a "date serial", in units of days. A time with no date has 0 days plus a fractional number representing the part of a day that the time represents. To get hours, multiply by 24.