Software
Blog theme updated
by Vern on Mar.07, 2007, under Software
I spent some time recently to create my own WordPress blog theme. I couldn’t resist using Dan Laszlo’s excellent mosaic of Long’s peak and comet McNaught from last January. Dan is a member of one of our local astronomy clubs NCAS in Fort Collins, CO. After the comet disappeared for us in the northern hemisphere a member of the Boulder club, Paul Robinson, determined that it might be possible to still observe the tail and in fact did so. Dan was the first to photograph the comets tail extending above the horizon.
Aurora Add-on for World Wind Updated
by Vern on Mar.06, 2007, under Astronomy, Aurora, NASA World Wind, Software
I’ve updated the Aurora add-on for NASA’s World Wind. The recently released (Feb 14) version 1.4 of World Wind now monitors cache files and updates them if they are expired. The Aurora add-on needed only a minor change to expire the cache so it will retrieve the current Auroral PMAps from NOAA National Weather Service Space Environment Center. You can download the updated plugin from http://www.sec.noaa.gov/pmap/GEpmap/
This works although the Earth/LayerSet.xsd that comes with WW-1.4 should technically disallow the markup within an ImageLayer. Apparently the LayerSet.xsd is not current.

NASA World Wind – Aurora overlay
by Vern on Jul.11, 2006, under Astronomy, Aurora, NASA World Wind, Software
If you haven’t given it a try yet, you might consider giving NASA World Wind a spin or two. It is somewhat similar to GoogleEarth but doesn’t have the privacy issues involved with sending all your clicking habits to Google. World Wind is not Earthbound, you may visit other world’s such as Mars and the Moon. Both GoogleEarth and WorldWind are great applications, each has their own advantages and disadvantages.
Earlier this morning, I completed an overlay for the folks at the National Weather Service’s Space Environment Center. The overlay displays the auroral power influx as measured by NOAA POES satellites, which gives some indication of auroral activity. Current version doesn’t update automatically — I’ll add that shortly.
Information and links for downloading NASA World Wind is available from http://worldwind.arc.nasa.gov/
After you get World Wind installed, you may download the Aurora overlay from the National Weather Service Space Environment Center at http://www.sec.noaa.gov/pmap/GEpmap/
General information about auroras is available at http://www.sec.noaa.gov/pmap

Connect to a GO-TO GPS telescope with JAVA™ applications
by Vern on Sep.11, 2003, under Java, Software
The current generation of “go-to” GPS telescopes are an amazing technological innovation. They combine precise motor controls, position sensors, GPS receivers, and excellent optics into an telescopic instrument that can be enjoyed by both novice users and advanced amateur astronomers. The “go-to” telescope permits the user to view the moon, the planets, nebulas, galaxies, star clusters, and other celestial objects by simply pressing a few buttons. The functionality and ease of use of these telescopes can be futher extended by connecting them to your computer.

The telescope interface presented here will permit Java applications to instruct the telescope to slew or “go to” specified coordinates, to query the telescope’s current position, and obtain other information such as slewing status, the GPS date and time, and the users geographic coordinate. The telescope interface is designed to be extensible, permitting connection from computers running various operating systems to telescopes from various manufactures. The telescope interface is a “pure” Java implementation. It utilizes the “javax.comm” api. (See the resources page at the end of this article for availability).
By using the telescope interface, applications such as star chart programs may be developed to control the telescope. More advanced applications such as augmented displays that combine digitized video output with graphic overlays are possible. Applications such as these will be the subject of future articles over the next several months.
To connect to the Nexstar GPS telescope an adapter cable is required (Celestron Part Number 93920 available from telescope dealers and online suppliers such as Astronomics, Anacortes, A2Z Cables.com, and several others). The cable costs about $20 (US) plus shipping. The cable has a telephone handset plug at one end and a DB-9 connector on the other. The DB-9 Connector is connected to a COM port on the computer and the other is plugged into the end of the telescope hand controller. The telescope interface provides the RS232 communication functions described in Celestron Instruction manuals and a few additional functions such as accessing the GPS as well.
escription of the Telescope Interface
The telescope interface consists of the classes: TelescopeInterface, TelescopeModel, TelescopeFactory, and SerialConnection. For each telescope manufacture, there is a concrete implementation of the TelescopeInterface and supporting classes. The diagram below shows classes to interface the Celestron telescope. (The complete Javadoc is available online as is a source code cross reference).
Class diagram of telescope interface
Figure 1. Class Diagram of the Telescope Interface
The TelescopeInterface class is an interface that defines all the methods that will be publicly available to an application.
The TelescopeModel class is a type-safe enumation of various telescope models. It permits different telescope models from different manufactures to be selected.
The TelescopeFactory class is used by an application to select which telescope commands are to be used.
The CelestronTelescope class is a concrete implementation of the telescope interface. It takes care of all details of setting up the serial port to communicate with the telescope. In addition, it sends commands to the telescope and receives responses.
The CelestronCommand class is a facade used by CelestronNexstar to select command strings that are to be used for a particular telescope model.
The CelestronCoordinateConverter class is used by the CelestronCommand class to convert coordinates for a telescope model.
Though not yet completely implemented or tested, there are equivalent classes for Meade telescopes: MeadeTelescope, MeadeCommand, and MeadeCoordinateConverter.
The SerialConnection class is used to send command strings and receive responses to the telescope through the computers comm port. It provides a buffer to help synchronize commands and responses. It used used to set up communication parameters such as the comm port to be used, the baud rate, stop bits, bits-per-character, and communication handshake to be used.
To use the telescope interface, the application developer needs to write code to do the following:
1. Import the “com.raben.telescope.comm.TelescopeInterface”, “com.raben.telescope.comm.TelescopeModel” and “com.raben.telescope.comm.TelescopeFactory” classes
2. Call the “TelescopeFactory.newInstance” static method and pass the name of a TelescopeModel such as “TelescopeModel.CELSTRON_NEXSTAR_GPS”.
3. Create and instance of java.util.properties and set a key “com.raben.telescope.port” to “COM1″, “COM2″, or whatever comm port is to be used to connect to the telescope.
4. Call the telescope method “setProperties” and pass the comm properties as a parameter
5. Initialize communication to the telescope by calling the “initialize” method.
6. Test whether communication to the telescope has been established by calling the “isCommunicating” method.
7. Implement the application by sending various commands to the telescope such as “go-to” a given coordinate or read the telescopes current position.
8. Call the telescope method “close” to release the comm port connection to the telescope
View Javadoc
1 /*
2 * TestApp.java
3 *
4 * Copyright (c) 2003, Raben Systems, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * Neither the name of Raben Systems, Inc. nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35 package com.raben.telescope.comm;
36 import java.util.Iterator;
37 import java.util.Calendar;
38 import java.util.Properties;
39 import java.util.TimeZone;
40 import java.io.IOException;
41 import java.io.BufferedReader;
42 import java.io.InputStreamReader;
43 import java.text.DateFormat;
44 import java.awt.geom.Point2D;
45
46 /***
47 * Simple test that connects to telescope and checks that it is communicating,
48 * checks if it is aligned, if so reads altitude/azimuth, and right ascension
49 * and declination.
50 * @author Vern Raben
51 * @version $Revision: 1.2 $ $Date: 2003/09/08 16:29:53 $
52 */
53 public class TestApp {
54 /*** UTC Time zone */
55 private static final TimeZone TZ = TimeZone.getTimeZone("UTC");
56
57 /*** Date format to use */
58 private DateFormat dateFormat
59 = DateFormat.getDateTimeInstance();
60
61 /*** Telescope interface */
62 private TelescopeInterface telescope;
63
64 /*** Creates a new instance of TestApp */
65 public TestApp() {
66 dateFormat.setTimeZone(TZ);
67 }
68
69 /***
70 * Test telescope interface
71 * @param modelStr Name of telescope model
72 * @param portName Name of communication port
73 */
74 public void testTelescope(String modelStr, String portName) {
75
76 // First, show a solar hazard warning to user, just in case they are
77 // operating the telescope outside, during the daytime
78 /*
79 if (!isSolarHazardWarningAcknowledged()) {
80 System.out.println("TestApp exit");
81 System.exit(0);
82 }
83 */
84 // Second, get telescope instance from TelescopeFactory
85 if (modelStr != null) {
86 telescope = TelescopeFactory.getInstance(modelStr);
87 } else {
88 telescope = TelescopeFactory.newInstance();
89 }
90
91
92 // Set debug to true to see commands sent and responses received
93 // telescope.setDebug(true);
94
95 try {
96
97 if (telescope == null) {
98 throw new IOException("Telescope model not found");
99 }
100
101 System.out.println("Testing telescope model "
102 + telescope.getTelescopeModel());
103
104 // Third, tell the interface which port to use by setting
105 // property key "com.raben.telescope.port" Not necessary if using
106 // port COM1 (the default)
107 if (portName != null) {
108 Properties props = new Properties();
109 props.setProperty(ScopeKey.PORT, portName);
110 telescope.setProperties(props);
111 }
112
113 // Fourth, initialize communications with telescope
114 telescope.connect();
115 /*
116 // Fifth check if communications is established
117 if ((telescope.isConnected()) && (!telescope.isCommunicating())) {
118 System.out.println(
119 "Telescope is not communicating to computer port "
120 + portName);
121 } else {
122 System.out.println("Telescope is communicating");
123 // If commuicating, check if aligned
124
125 if (telescope.isAligned()) {
126 System.out.println("Telescope is aligned");
127
128 // Test getting azimuth/altitude
129 Point2D azAlt = telescope.getAzimuthAltitude();
130 System.out.println("Telescope current azimuth="
131 + azAlt.getX() + " Altitude=" + azAlt.getY());
132
133 // Test getting right ascension/declination
134 Point2D raDec = telescope.getRightAscensionDeclination();
135 System.out.println("Telescope current right ascension = "
136 + raDec.getX() + " Declination = " + raDec.getY());
137
138 testAzimuthSlewing();
139 testRaSlewing();
140 } else {
141 System.out.println("Telescope is not aligned");
142 }
143
144 testGps();
145
146 }
147 */
148 testUpDown();
149 testLeftRight();
150
151 } catch (IOException e) {
152 System.out.println("Error occurred communicating with telescope "
153 + " error = " + e.getMessage());
154 } finally {
155
156 if (telescope != null) {
157 telescope.close();
158 }
159 }
160
161 System.out.println("Test completed");
162 }
163
164 /***
165 * Test azimuth/altitude slewing
166 * @exception IOException may occur
167 */
168 private void testAzimuthSlewing() throws IOException {
169 // See if we can slew to az 0, alt 0.0
170 System.out.println("Test slewing to azimuth 0, altitude 0");
171 Point2D az = new Point2D.Double(0.0, 0.0);
172 telescope.goToAzimuthAltitude(az);
173 waitForSlew();
174 Point2D az2 = telescope.getAzimuthAltitude();
175 System.out.println("Telescope slewed to azimuth "
176 + az2.getX() + " altitude=" + az2.getY());
177
178 }
179
180 /***
181 * Test slew to right ascension/declination
182 * @exception IOException may occur
183 */
184 private void testRaSlewing() throws IOException {
185 System.out.println("Slew telescope to azimuth 0, altitude 45.0");
186 telescope.goToAzimuthAltitude(new Point2D.Double(0.0, 45.0));
187 waitForSlew();
188 Point2D ra = telescope.getRightAscensionDeclination();
189 ra.setLocation(ra.getX() + 6.0, ra.getY());
190 System.out.println("Test slewing to ra " + ra.getX()
191 + " decl=" + ra.getY());
192
193 telescope.goToRightAscensionDeclination(ra);
194 waitForSlew();
195 Point2D ra2 = telescope.getRightAscensionDeclination();
196 System.out.println("Telescope slewed to ra "
197 + ra2.getX() + " decl " + ra2.getY());
198 }
199
200 /***
201 * Test GPS commands
202 * @exception IOException may occur
203 */
204 private void testGps() throws IOException {
205 // Check if the GPS is linked
206 boolean linked = telescope.isGpsLinked();
207 System.out.println("Testing GPS ");
208 System.out.println(" GPS linked = " + linked);
209
210 if (linked) {
211 Calendar gpsDate = telescope.getGpsDateTime();
212
213 if (gpsDate != null) {
214 System.out.println(" GPS date is "
215 + dateFormat.format(gpsDate.getTime()) + " UTC");
216 }
217
218 Point2D gpsCoord = telescope.getGpsCoordinate();
219 System.out.println(" GPS longitude is " + gpsCoord.getX()
220 + " latitude is " + gpsCoord.getY());
221 }
222
223 System.out.println("GPS test completed");
224 }
225
226 /***
227 * Wait for slew to complete
228 */
229 private void waitForSlew() {
230 boolean slewing = true;
231 System.out.print("Slewing ..");
232
233 try {
234 do {
235 System.out.print(".");
236 System.out.flush();
237 Thread.sleep(2000L);
238 } while (telescope.isSlewing());
239
240 } catch (InterruptedException e) {
241 // Ignore
242 } catch (IOException e) {
243 // ignore
244 }
245 System.out.println();
246 }
247
248
249 /***
250 * @param args the command line arguments
251 * Usage: java -cp TestApp.jar "model" port
252 *
253 * Default telescope model is "Celestron Nexstar GPS", default port is COM1
254 * If this is the case, you do not need to specify any command line args.
255 *
256 * To list available models and ports enter the following:
257 * java -cp TestApp.jar; HELP
258 */
259 public static void main(String[] args) {
260 TestApp testApp = new TestApp();
261
262 if ((args != null) && (args.length > 0)) {
263 String arg0 = args[0].toUpperCase();
264
265 if (("HELP".equals(arg0)) || ("?".equals(arg0))) {
266 showHelp();
267 }
268
269 if (args.length > 1) {
270 testApp.testTelescope(args[0], args[1]);
271 }
272 } else {
273 testApp.testTelescope(null, null);
274 }
275
276 System.out.println("TestApp exit");
277
278 }
279
280 /***
281 * Show how to start the Test application
282 */
283 public static void showHelp() {
284 System.out.println("Usage: java -cp telescope.jar com.raben.telescope.comm.TestApp \"model\" port");
285 System.out.println("Where model is one of:");
286
287 Iterator iter = TelescopeModel.VALUES.iterator();
288
289 while (iter.hasNext()) {
290 System.out.print(" ");
291 System.out.println((TelescopeModel) iter.next());
292 }
293
294 System.out.println(
295 " Be sure to place double quotes (\") around model name");
296
297 String[] ports = SerialConnection.getAvailablePorts();
298
299 if (ports != null) {
300 System.out.println("And where port is one of ");
301
302 for (int i = 0; i < ports.length; i++) {
303 System.out.println(" " + ports[i]);
304 }
305
306 System.out.println();
307 }
308
309 }
310
311 /***
312 * Display warning informing user of the hazards of operating telescope
313 * outside during the daytime
314 * Ask user to acknowledge the warning
315 * @return True if user enter "Y", false otherwise
316 */
317 public boolean isSolarHazardWarningAcknowledged() {
318 boolean acknowledge = false;
319 System.out.println("*************************************************");
320 System.out.println("* !! WARNING !! *");
321 System.out.println("* If you are using a telescope during daytime *");
322 System.out.println("* be sure that you have adequate solar *");
323 System.out.println("* filters securely and properly in place. *");
324 System.out.println("* Failure to do so may result in blindness, *");
325 System.out.println("* severe injuries to yourself, other persons, *");
326 System.out.println("* or other property and equipment. *");
327 System.out.println("* The telescope may slew and point directly at *");
328 System.out.println("* the SUN at anytime, without warning either in *");
329 System.out.println("* response to a command, accidentally or *");
330 System.out.println("* otherwise. *");
331 System.out.println("* Type \"Y\" at the prompt to acknowledge *");
332 System.out.println("* warning. *");
333 System.out.println("*************************************************\n");
334 System.out.print("Do you acknowledge this warning? : ");
335 System.out.flush();
336 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
337
338 try {
339 String str = br.readLine();
340
341 if (str != null) {
342
343 if ("Y".equals(str.toUpperCase())) {
344 acknowledge = true;
345 }
346 }
347 } catch (IOException e) {
348 // Shouldn't occur
349 }
350
351 return acknowledge;
352
353 }
354
355 /*** Test moving telescope left and right in azimuth */
356 public void testUpDown() throws IOException {
357 System.out.println("Testing moving telescope up");
358 telescope.moveInAltitude(true, 9);
359 try {
360 Thread.sleep(3000L);
361 } catch (InterruptedException e) {}
362 System.out.println("send stop command");
363 telescope.moveInAltitude(true, 0);
364
365 System.out.println("Testing moving telescope down");
366 telescope.moveInAltitude(false, 9);
367 try {
368 Thread.sleep(3000L);
369 } catch (InterruptedException e) {}
370 System.out.println("send stop command");
371 telescope.moveInAltitude(false, 0);
372 }
373
374 /*** Test moving telescope up and down in altitude */
375 public void testLeftRight() throws IOException {
376 System.out.println("Testing moving telescope right");
377 telescope.moveInAzimuth(true, 9);
378 try {
379 Thread.sleep(3000L);
380 } catch (InterruptedException e) {}
381 telescope.moveInAzimuth(true, 0);
382
383 System.out.println("Testing moving telescope left");
384 telescope.moveInAzimuth(false, 9);
385 try {
386 Thread.sleep(3000L);
387 } catch (InterruptedException e) {}
388 telescope.moveInAzimuth(false, 0);
389
390
391
392 }
393
394
View Javadoc
/*
2 * PositionDialog.java
3 *
4 * Copyright (c) 2003, Raben Systems, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * Neither the name of Raben Systems, Inc. nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 package com.raben.telescope.comm;
35 import java.util.TimerTask;
36 import java.util.Timer;
37 import java.util.Properties;
38 import java.util.ResourceBundle;
39 import java.util.TimeZone;
40 import java.util.Calendar;
41 import java.util.GregorianCalendar;
42 import java.awt.EventQueue;
43 import java.awt.geom.Point2D;
44 import java.io.IOException;
45 import java.text.MessageFormat;
46 import java.text.DateFormat;
47
48
49 /***
50 *
51 * Display telescope position as local horizontal coordinates and equatorial and
52 * GPS date/time and geographic coordinate
53 * coordinates
54 * @author Vern Raben
55 * @version $Revision: 1.1.1.1 $ $Date: 2003/06/13 04:51:05 $
56 */
57 public class PositionDialog extends javax.swing.JDialog {
58
59 /*** Creates new formPositionDialog
60 * @param parent Reference to parent frame
61 * @param telescope The telescope interface
62 */
63 public PositionDialog(java.awt.Frame parent, TelescopeInterface telescope) {
64 super(parent, false);
65 this.telescope = telescope;
66 initComponents();
67 dateTimeFormat.setTimeZone(TZ);
68
69 // Set connect toggle to current state
70 if (telescope != null) {
71 connectToggle.setSelected(telescope.isConnected());
72 }
73
74 startTelescopeUpdate();
75 }
76
77 /*** This method is called from within the constructor to
78 * initialize the form.
79 * WARNING: Do NOT modify this code. The content of this method is
80 * always regenerated by the Form Editor.
81 */
82 private void initComponents() {//GEN-BEGIN:initComponents
83 jPanel3 = new javax.swing.JPanel();
84 jPanel4 = new javax.swing.JPanel();
85 jLabel5 = new javax.swing.JLabel();
86 gpsDateTimeTextField = new javax.swing.JTextField();
87 jPanel41 = new javax.swing.JPanel();
88 jLabel51 = new javax.swing.JLabel();
89 gpsLongitudeTextField = new javax.swing.JTextField();
90 jLabel511 = new javax.swing.JLabel();
91 gpsLatitudeTextfield = new javax.swing.JTextField();
92 jPanel5 = new javax.swing.JPanel();
93 jPanel6 = new javax.swing.JPanel();
94 jLabel6 = new javax.swing.JLabel();
95 raTextField = new javax.swing.JTextField();
96 jLabel61 = new javax.swing.JLabel();
97 decTextField = new javax.swing.JTextField();
98 jPanel61 = new javax.swing.JPanel();
99 jLabel62 = new javax.swing.JLabel();
100 azmTextField = new javax.swing.JTextField();
101 jLabel611 = new javax.swing.JLabel();
102 altTextField = new javax.swing.JTextField();
103 jPanel8 = new javax.swing.JPanel();
104 cancelButton = new javax.swing.JButton();
105 connectToggle = new javax.swing.JToggleButton();
106
107 getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.Y_AXIS));
108
109 setTitle(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("TELESCOPE_POSITION"));
110 addWindowListener(new java.awt.event.WindowAdapter() {
111 public void windowClosing(java.awt.event.WindowEvent evt) {
112 closeDialog(evt);
113 }
114 });
115
116 jPanel3.setLayout(new javax.swing.BoxLayout(jPanel3, javax.swing.BoxLayout.Y_AXIS));
117
118 jPanel3.setBorder(new javax.swing.border.TitledBorder(null, java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("GPS"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 0, 11), new java.awt.Color(0, 0, 0)));
119 jPanel4.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
120
121 jLabel5.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("DATE_TIME"));
122 jPanel4.add(jLabel5);
123
124 gpsDateTimeTextField.setColumns(18);
125 gpsDateTimeTextField.setEditable(false);
126 gpsDateTimeTextField.setEnabled(false);
127 jPanel4.add(gpsDateTimeTextField);
128
129 jPanel3.add(jPanel4);
130
131 jPanel41.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
132
133 jLabel51.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("LONGITUDE"));
134 jPanel41.add(jLabel51);
135
136 gpsLongitudeTextField.setColumns(10);
137 gpsLongitudeTextField.setEditable(false);
138 gpsLongitudeTextField.setEnabled(false);
139 jPanel41.add(gpsLongitudeTextField);
140
141 jLabel511.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("LATITUDE"));
142 jPanel41.add(jLabel511);
143
144 gpsLatitudeTextfield.setColumns(10);
145 gpsLatitudeTextfield.setEditable(false);
146 gpsLatitudeTextfield.setEnabled(false);
147 jPanel41.add(gpsLatitudeTextfield);
148
149 jPanel3.add(jPanel41);
150
151 getContentPane().add(jPanel3);
152
153 jPanel5.setLayout(new javax.swing.BoxLayout(jPanel5, javax.swing.BoxLayout.Y_AXIS));
154
155 jPanel5.setBorder(new javax.swing.border.TitledBorder(null, java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("TELESCOPE_POSITION"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 0, 11), new java.awt.Color(0, 0, 0)));
156 jPanel6.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
157
158 jPanel6.setBackground(new java.awt.Color(204, 204, 204));
159 jLabel6.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("RA"));
160 jLabel6.setLabelFor(raTextField);
161 jPanel6.add(jLabel6);
162
163 raTextField.setColumns(10);
164 raTextField.setEditable(false);
165 raTextField.setEnabled(false);
166 jPanel6.add(raTextField);
167
168 jLabel61.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("DEC"));
169 jPanel6.add(jLabel61);
170
171 decTextField.setColumns(10);
172 decTextField.setEditable(false);
173 decTextField.setEnabled(false);
174 jPanel6.add(decTextField);
175
176 jPanel5.add(jPanel6);
177
178 jPanel61.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
179
180 jLabel62.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("AZM"));
181 jPanel61.add(jLabel62);
182
183 azmTextField.setColumns(9);
184 azmTextField.setEditable(false);
185 azmTextField.setEnabled(false);
186 jPanel61.add(azmTextField);
187
188 jLabel611.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("ALT"));
189 jPanel61.add(jLabel611);
190
191 altTextField.setColumns(9);
192 altTextField.setEditable(false);
193 altTextField.setEnabled(false);
194 jPanel61.add(altTextField);
195
196 jPanel5.add(jPanel61);
197
198 getContentPane().add(jPanel5);
199
200 jPanel8.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
201
202 cancelButton.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("CANCEL"));
203 cancelButton.addActionListener(new java.awt.event.ActionListener() {
204 public void actionPerformed(java.awt.event.ActionEvent evt) {
205 cancelButtonActionPerformed(evt);
206 }
207 });
208
209 jPanel8.add(cancelButton);
210
211 connectToggle.setText(java.util.ResourceBundle.getBundle("resources/comm/Telescope").getString("CONNECT"));
212 connectToggle.setMargin(new java.awt.Insets(2, 2, 2, 2));
213 connectToggle.addActionListener(new java.awt.event.ActionListener() {
214 public void actionPerformed(java.awt.event.ActionEvent evt) {
215 connectToggleActionPerformed(evt);
216 }
217 });
218
219 jPanel8.add(connectToggle);
220
221 getContentPane().add(jPanel8);
222
223 pack();
224 }//GEN-END:initComponents
225
226 /***
227 * Handle cancel button being pressed
228 * @param evt Not used
229 */
230 private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
231 closeDialog(null);
232 }//GEN-LAST:event_cancelButtonActionPerformed
233
234 /*** Handle connection toggle button being pressed
235 * @param evt Not used
236 */
237 private void connectToggleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectToggleActionPerformed
238 if (connectToggle.isSelected()) {
239 if (showSolarHazardWarning()) {
240 try {
241 if (telescope != null) {
242 telescope.connect();
243 startTelescopeUpdate();
244 }
245 } catch (IOException e) {
246
247 // Show connect error dialog
248 System.out.println(e);
249 }
250 }
251
252
253 } else {
254 stopTelescopeUpdate();
255 telescope.close();
256 connectToggle.setSelected(telescope.isConnected());
257
258 }
259 }//GEN-LAST:event_connectToggleActionPerformed
260
261 /*** Closes the dialog
262 * @param evt (Not used)
263 */
264 private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
265 setVisible(false);
266 dispose();
267 stopTelescopeUpdate();
268
269 if (isStandalone()) {
270 System.exit(0);
271 }
272 }//GEN-LAST:event_closeDialog
273
274 /***
275 * Called when PositionDialog run as standalone program
276 * @param args the command line arguments
277 */
278 public static void main(String args[]) {
279
280 TelescopeInterface telescope = TelescopeFactory.newInstance();
281 PositionDialog positionDialog =
282 new PositionDialog(new javax.swing.JFrame(), telescope);
283 positionDialog.setStandalone(true);
284 positionDialog.show();
285 }
286
287
288 /***
289 * Cancel telescope update info and display tasks and timers
290 */
291 private void stopTelescopeUpdate() {
292 if (telescopeInfoTask != null) {
293 telescopeInfoTask.cancel();
294 telescopeInfoTask = null;
295 }
296
297 if (telescopeInfoTimer != null) {
298 telescopeInfoTimer.cancel();
299 telescopeInfoTimer = null;
300 }
301
302 if (updateDisplayTask != null) {
303 updateDisplayTask.cancel();
304 updateDisplayTask = null;
305 }
306
307 if (updateDisplayTimer != null) {
308 updateDisplayTimer.cancel();
309 updateDisplayTimer = null;
310 }
311 }
312
313 /***
314 * Start update info and display timers and tasks
315 */
316 private void startTelescopeUpdate() {
317 if ((telescope != null) && (telescope.isConnected())) {
318 stopTelescopeUpdate();
319 updateDisplayTask = new UpdateDisplayTask();
320 updateDisplayTimer = new Timer(true);
321 updateDisplayTimer.schedule(updateDisplayTask, 4000L,
322 updateDisplayInterval);
323 telescopeInfoTask = new TelescopeInfoTask();
324 telescopeInfoTimer = new Timer(true);
325 telescopeInfoTimer.schedule(telescopeInfoTask, 200L,
326 telescopeInfoInterval);
327
328 }
329 }
330
331 /***
332 * Display solar hazard warning dialog
333 * @return true if user acknowledges solar hazard
334 */
335 private boolean showSolarHazardWarning() {
336 if (!solarHazardDialog.isAccepted()) {
337 solarHazardDialog.show();
338 connectToggle.setSelected(solarHazardDialog.isAccepted());
339 }
340
341 return solarHazardDialog.isAccepted();
342 }
343
344 /*** Getter for property standalone.
345 * @return Value of property standalone.
346 */
347 public boolean isStandalone() {
348 return this.standalone;
349 }
350
351 /*** Setter for property standalone.
352 * @param standalone New value of property standalone.
353 */
354 public void setStandalone(boolean standalone) {
355 this.standalone = standalone;
356 }
357
358 /***
359 * Get angle as Integer array containg degrees, minues, and seconds
360 * @param angle Angle in degrees
361 * @return An int array containing degres, minutes, and seconds
362 */
363 private Integer[] getDegreesMinutesSeconds(double angle) {
364 Integer[] dms = new Integer[3];
365 dms[0] = new Integer((int) angle);
366 double dmin = 60.0 * (Math.abs(angle) - Math.abs(dms[0].intValue()));
367 dms[1] = new Integer((int) dmin);
368 double dsec = 60.0 * (dmin - dms[1].intValue());
369 dms[2] = new Integer((int) Math.round(dsec));
370 return dms;
371 }
372
373 // Variables declaration - do not modify//GEN-BEGIN:variables
374 private javax.swing.JPanel jPanel8;
375 private javax.swing.JPanel jPanel6;
376 private javax.swing.JPanel jPanel5;
377 private javax.swing.JPanel jPanel4;
378 private javax.swing.JPanel jPanel3;
379 private javax.swing.JPanel jPanel41;
380 private javax.swing.JPanel jPanel61;
381 private javax.swing.JLabel jLabel611;
382 private javax.swing.JTextField decTextField;
383 private javax.swing.JLabel jLabel511;
384 private javax.swing.JTextField gpsLongitudeTextField;
385 private javax.swing.JTextField gpsDateTimeTextField;
386 private javax.swing.JLabel jLabel62;
387 private javax.swing.JLabel jLabel61;
388 private javax.swing.JTextField altTextField;
389 private javax.swing.JToggleButton connectToggle;
390 private javax.swing.JTextField raTextField;
391 private javax.swing.JTextField azmTextField;
392 private javax.swing.JTextField gpsLatitudeTextfield;
393 private javax.swing.JButton cancelButton;
394 private javax.swing.JLabel jLabel6;
395 private javax.swing.JLabel jLabel5;
396 private javax.swing.JLabel jLabel51;
397 // End of variables declaration//GEN-END:variables
398
399 /*** Timer to periodically run DisplayUpdateTask */
400 private Timer updateDisplayTimer = null;
401
402 /*** Task to update telescope status display */
403 private UpdateDisplayTask updateDisplayTask = null;
404
405 /*** Telescope display update interval */
406 private long updateDisplayInterval = 2000L;
407
408 /*** Timer to periodically run TelescopeInfoTask */
409 private Timer telescopeInfoTimer = null;
410
411 /*** Task to retrieve info from telescope */
412 private TelescopeInfoTask telescopeInfoTask = null;
413
414 /*** Telescope information interval */
415 private long telescopeInfoInterval = 4000L;
416
417 /*** Telescope interface */
418 private TelescopeInterface telescope = null;
419
420
421 /*** Telescope properties */
422 private Properties telescopeProperties = new Properties();
423
424 /*** Holds value of property standalone. */
425 private boolean standalone;
426
427 /*** MessageFormat for degrees/minutes/seconds */
428 private MessageFormat dmsFmt = new MessageFormat(
429 ResourceBundle.getBundle("resources/comm/Telescope").getString(
430 "DMS_FORMAT"));
431
432 /*** MessageFormat for hours/minutes/seconds */
433 private MessageFormat hmsFmt = new MessageFormat(
434 ResourceBundle.getBundle("resources/comm/Telescope").getString(
435 "HMS_FORMAT"));
436 /*** Time zone for UTC */
437 private static final TimeZone TZ = TimeZone.getTimeZone("UTC");
438
439 /*** Date/Time Format */
440 private DateFormat dateTimeFormat
441 = DateFormat.getDateTimeInstance();
442
443 /*** Local horizontal coordinate */
444 private Point2D horizCoord = new Point2D.Double(0.0, 0.0);
445
446 /*** Equatorial coordinate */
447 private Point2D eqCoord = new Point2D.Double(0.0, 0.0);
448
449 /*** GSP geographic coordinate */
450 private Point2D gpsCoordinate = new Point2D.Double(0.0, 0.0);
451
452 /*** Flag that indicates whether or not scope is aligned */
453 private boolean aligned = false;
454
455 /*** Flag that indicates whether or not scope is communicating */
456 private boolean communicating = false;
457
458 /*** Flag that indicates whether or not GPS is linked */
459 private boolean gpsLinked = false;
460 /*** GPS Date/Time */
461 private Calendar gpsDateTime = GregorianCalendar.getInstance(TZ);
462 /*** Define longest time that task can be late */
463 private static final long MAX_TARDINESS = 2000L;
464
465 /*** Dialog showing solar hazard warning */
466 private SolarHazardDialog solarHazardDialog
467 = new SolarHazardDialog(null, true);
468
469 /*** Inner class to retrieve information from telescope */
470 class TelescopeInfoTask extends TimerTask {
471 /*** Flag to indicate ok to keep getting info */
472 private boolean ok = true;
473
474 /*** Counter to check status */
475 private int checkCount = 0;
476
477 /*** Called when task is scheduled */
478 public void run() {
479 try {
480 if (System.currentTimeMillis() - scheduledExecutionTime() >=
481 MAX_TARDINESS) {
482 return; // Too late; skip this execution.
483 }
484
485 if ((ok) && (!communicating)) {
486 communicating = telescope.isCommunicating();
487 }
488
489 if ((ok) && (communicating) && (!aligned)) {
490 aligned = telescope.isAligned();
491 gpsLinked = telescope.isGpsLinked();
492 }
493
494 if ((ok) && (aligned)) {
495 synchronized (horizCoord) {
496 horizCoord.setLocation(telescope.getAzimuthAltitude());
497 }
498
499 synchronized (eqCoord) {
500 eqCoord.setLocation(telescope.getRightAscensionDeclination());
501 }
502 }
503
504 if ((ok) && (gpsLinked) && (communicating)) {
505 Calendar cal = telescope.getGpsDateTime();
506
507 synchronized (gpsDateTime) {
508 gpsDateTime.setTime(cal.getTime());
509 }
510
511 synchronized (gpsCoordinate) {
512 gpsCoordinate.setLocation(telescope.getGpsCoordinate());
513 }
514 }
515
516 // Periodically check communications and gps
517 if (ok) {
518 checkCount++;
519
520 if (checkCount > 5) {
521 checkCount = 0;
522 gpsLinked = telescope.isGpsLinked();
523 }
524 }
525
526 } catch (IOException e) {
527 System.out.println(e);
528 }
529 }
530
531 /*** Cancel task
532 @return True when canceled
533 */
534 public boolean cancel() {
535 ok = false;
536 return super.cancel();
537 }
538
539 }
540
541 /*** Inner class to update the display */
542 class UpdateDisplayTask extends TimerTask {
543 /*** Flag to control whether its ok to continue update */
544 private boolean ok = true;
545
546 /*** Called when timer starts task */
547 public void run() {
548 if (!EventQueue.isDispatchThread()) {
549 EventQueue.invokeLater(this);
550 } else {
551 if (ok) {
552 updateDisplay();
553 }
554 }
555 }
556
557 /*** Update the display */
558 private void updateDisplay() {
559 updateGpsTextFieldEnabled();
560 updatePositionTextFieldEnabled();
561
562 if ((ok) && (communicating) && (aligned)) {
563 updateHorizontalCoordinates();
564 updateEquatorialCoordinates();
565 }
566
567 if (gpsLinked) {
568 updateGps();
569 }
570
571 }
572
573 /***
574 * Cancel update
575 * @return True when canceled
576 */
577 public boolean cancel() {
578 ok = false;
579 azmTextField.setEnabled(ok);
580 altTextField.setEnabled(ok);
581 raTextField.setEnabled(ok);
582 decTextField.setEnabled(ok);
583 communicating = false;
584 gpsLinked = false;
585 updateGpsTextFieldEnabled();
586 aligned = false;
587 return super.cancel();
588 }
589
590 /***
591 * Update local horizontal coordinates (azimuth, altitude) display
592 */
593 private void updateHorizontalCoordinates() {
594
595 if (ok) {
596 Integer[] azm = getDegreesMinutesSeconds(horizCoord.getX());
597 azmTextField.setText(dmsFmt.format(
598 ResourceBundle.getBundle("resources/comm/Telescope").getString("DMS_FORMAT"),
599 azm));
600 }
601
602 if (ok) {
603 Integer[] alt = getDegreesMinutesSeconds(horizCoord.getY());
604 altTextField.setText(dmsFmt.format(
605 ResourceBundle.getBundle(
606 "com/raben/telescope/Telescope").getString("DMS_FORMAT"),
607 alt));
608 }
609
610 }
611
612 /***
613 * Update equatorial coordinates (right ascension, declination) display
614 */
615 private void updateEquatorialCoordinates() {
616 if (ok) {
617
618 Integer[] ra = getDegreesMinutesSeconds(eqCoord.getX());
619 raTextField.setText(hmsFmt.format(
620 ResourceBundle.getBundle(
621 "com/raben/telescope/Telescope").getString("HMS_FORMAT"),
622 ra));
623 }
624
625 if (ok) {
626 Integer[] dec = getDegreesMinutesSeconds(eqCoord.getY());
627 decTextField.setText(dmsFmt.format(
628 ResourceBundle.getBundle(
629 "com/raben/telescope/Telescope").getString("DMS_FORMAT"),
630 dec));
631 }
632 }
633
634 /***
635 * Update GPS date/time and geographical coordinate
636 */
637 private void updateGps() {
638 // Update date/time
639 if (ok) {
640 synchronized (gpsDateTime) {
641 gpsDateTimeTextField.setText(dateTimeFormat.format(
642 gpsDateTime.getTime()));
643 }
644 }
645
646 // Update GPS longitude
647 if (ok) {
648 double lat = 0.0;
649 double lon = 0.0;
650
651 synchronized (gpsCoordinate) {
652 lon = gpsCoordinate.getX();
653 lat = gpsCoordinate.getY();
654 }
655
656 Integer[] longitude = getDegreesMinutesSeconds(lon);
657 gpsLongitudeTextField.setText(dmsFmt.format(
658 ResourceBundle.getBundle(
659 "com/raben/telescope/Telescope").getString("DMS_FORMAT"),
660 longitude));
661
662 Integer[] latitude = getDegreesMinutesSeconds(lat);
663 gpsLatitudeTextfield.setText(dmsFmt.format(
664 ResourceBundle.getBundle(
665 "com/raben/telescope/Telescope").getString("DMS_FORMAT"),
666 latitude));
667 }
668
669 }
670
671 /*** Update GPS date/time, latitude, and longitude text field enable */
672 private void updateGpsTextFieldEnabled() {
673 gpsDateTimeTextField.setEnabled(gpsLinked);
674 gpsLongitudeTextField.setEnabled(gpsLinked);
675 gpsLatitudeTextfield.setEnabled(gpsLinked);
676 }
677
678 /*** Update telescope position text field enable */
679 private void updatePositionTextFieldEnabled() {
680 azmTextField.setEnabled(aligned);
681 altTextField.setEnabled(aligned);
682 raTextField.setEnabled(aligned);
683 decTextField.setEnabled(aligned);
684 }
685
686 }
687 }
Resources
Since the interface uses the Java comm api, you will need to download a copy for your computer platform. Follow the instructions included with the download for installation on your platform. The following list are possible sources for the comm api. The only one tested by us so far is the one from Sun Microsystems.
MS Windows and Sun Solaris: http://java.sun.com/products/javacomm
Linux, MS Windows, Mac OS/X: http://www.rxtx.org
Commercial versions for various platforms: http://www.serialio.com
Documentation for the javax api is available from http://java.sun.com/products/javacomm/javadocs/index.html.
Documentation of the “official” Celestron RS232 command sets are available from http://www.celestron.com/telescopes.htm. Product manual can be found by selecting the particlular telescope product.
The “unofficial” auxillary command set is documented at http://www.paquettefamily.ca/nexstar/.
Information regarding the computer interface to the Nexstar is available at http://www.nexstarsite.com/PCControl.htm. There is lots of other useful information about using Nexstar telescopes on this site as well.
Online documentation of the Telescope API is available from http://www.raben.com/articles/TelescopeInterface/apidocs/.
Source code for the example application and interface classes may be viewed in html form in this source xref listing.
Mars Aug 27, 2003 06:50 UTC
Source code and Installation
This project has joined the java.net open source community and is now available at telescope.dev.java.net which is hosted by Sun Microsystems and Oreilly Associates, Inc. From that site you may checkout the source code using CVS, join the development team, and contribute to the future development of the project! The telescope.dev.java.net CVS will be the most recent version of the source code. Instructions on how to use CVS are available at that site. Note — The site does not appear to support anonymous or guest CVS access. You need to register with java.net first and use your registered name to retrieve the code.
The source code may be also be downloaded from http://www.raben.com/downloads/telescope-1.4.1-src.zip
Unzip the zip file in a convenient directory. After unzipping the file you will find a directory called “Telescope-1.4″.
Under that directory you will find the following:
* “License.txt” Text file containing the “BSD” style license. By downloading the zip file you are agreeing to its terms.
* “src” directory containing the source code
* “classes” directory to contain the Java class files produced by compilation
* “dist” directory containing the telescope.jar file
* “build.xml” file to be used by the “Ant” tool
The Java SDK or Java runtime and the java.comm api must already be installed on your system.
If Apache Jakarta Ant has been installed on your computer system, you may re-compile the source code by simply changing to the “Telescope-1.4.1″ directory and executing the command:
ant telescope
The system variable “ANT_HOME” must point to the ant directory. The system variable “JAVA_HOME” must point to the J2SDK directory. Both “java” and “ant” must be in the command line path.
The example applications may be executed by changing to the “dist” directory and executing the following on a MS Windows command line:
The ConfigureDialog may be run as a stand-alone application as (on one line):
java -cp telescope.jar;%COMM_HOME%\comm.jar com.raben.telescope.comm.ConfigureDialog
java -cp telescope.jar;%COMM_HOME%\comm.jar com.raben.telescope.comm.SimplisticTest
java -cp telescope.jar;%COMM_HOME%\comm.jar com.raben.telescope.comm.PositionDialog
On MS Windows XP the variable %COMM_HOME% needs to set to location of the javax.comm distribution. (For reasons not understood — by me at least, the comm.jar doesn’t load automatically as it should from the jre/lib/ext directory — maybe because its is compiled from the old jdk1.6. Even more bizarre, %COMM_HOME% cannot point to the jre/lib/ext/comm.jar either — it must be point elsewhere!! — then it runs fine).
On LINUX and other UNIX platforms, the command is the same except for the classpath (-cp switch) for example:
java -cp telescope.jar:$COMM_HOME/comm.jar com.raben.telescope.comm.PositionDialog
Please send any questions, comments, or suggestions for enhancements to support@raben.com