source: trunk/FACT++/scripts/Main.js@ 15010

Last change on this file since 15010 was 15007, checked in by tbretz, 12 years ago
Added some output before the main loop to simplify detection of wrong schedules.
File size: 27.0 KB
Line 
1/**
2 * @fileOverview This file has functions related to documenting JavaScript.
3 * @author <a href="mailto:thomas.bretz@epfl.ch">Thomas Bretz</a>
4 */
5'use strict';
6
7//this is just the class implementation of 'Observation'
8include('scripts/Observation_class.js');
9
10dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
11
12
13// error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
14// clases: http://www.phpied.com/3-ways-to-define-a-javascript-class/
15//
16// Arguments: TakeFirstDrsCalib
17// To be determined: How to stop the script without foreceful interruption?
18
19// adapt states of drivectrl
20
21//
22// SCRIPTS:
23//
24// - Startup, e.g. do not open LID
25//
26// - Bring telescop to state 'operational', e.g. open lid,
27// when first run != START is detected in the loop
28//
29// - Take data
30//
31// - Shutdown
32//
33// ----> Does smartfact display alarm messages already?
34// ----> How to display errors in smartfact? Is that necessary at all?
35// (red output? maybe just <red>...</red>?
36//
37// ----------------------------------------------------------------
38
39function currentEst(source)
40{
41 var moon = new Moon();
42 if (!moon.isUp)
43 return 7.7;
44
45 var dist = Sky.dist(moon, source);
46
47 var alt = 90-moon.toLocal().zd;
48
49 var lc = dist*alt*pow(Moon.disk(), 6)/360/360;
50
51 var cur = 7.7+4942*lc;
52
53 return cur;
54}
55
56function thresholdEst(source) // relative threshold (ratio)
57{
58 // Assumption:
59 // atmosphere is 70km, shower taks place after 60km, earth radius 6400km
60 // just using the cosine law
61 // This fits very well with MC results: See Roger Firpo, p.45
62 // "Study of the MAGIC telescope sensitivity for Large Zenith Angle observations"
63
64 var c = Math.cos(Math.Pi-source.zd);
65 var ratio = (10*sqrt(409600*c*c+9009) + 6400*c - 60)/10;
66
67 // assumption: Energy threshold increases linearily with current
68 // assumption: Energy threshold increases linearily with distance
69
70 return ratio*currentEst(source)/7.7;
71}
72
73// Ratio in rate would be (estimate, not precise calculation)
74// pow(ratio, -0.7)
75
76// ----------------------------------------------------------------
77
78//DN: the name of the Subscription object 'service_con' is not really
79// telling that its a subscription to FAD_CONTROL/CONNECTIONS
80// fad_connections sound ok for be, since
81// fad_connections.onchange() is pretty clear
82// fad_connections.reconnect() is not really good, but at least it has FAD in it.
83var service_con = new Subscription("FAD_CONTROL/CONNECTIONS");
84/**
85 * call-back function of FAD_CONTROL/CONNECTIONS
86 * store IDs of problematic FADs
87 *
88 */
89service_con.onchange = function(evt)
90{
91 // This happens, but why?
92 if (!evt.obj['status'])
93 return;
94
95 this.reset = [ ];
96
97 for (var x=0; x<40; x++)
98 if (evt.obj['status'][x]!=66 && evt.obj['status'][x]!=67)
99 this.reset.push(x);
100
101 if (this.reset.length==0)
102 return;
103
104 dim.alarm("FAD board loss detected...");
105 dim.send("MCP/RESET");
106 dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
107}
108
109/**
110 * reconnect to problematic FADs
111 *
112 * Dis- and Reconnects to FADs, found to be problematic by call-back function
113 * onchange() to have a different CONNECTION value than 66 or 67.
114 *
115 * @returns
116 * a boolean is returned.
117 * reconnect returns true if:
118 * * nothing needed to be reset --> no problems found by onchange()
119 * * the reconnection went fine.
120 *
121 * reconnect *never returns false* so far.
122 *
123 * @example
124 * if (!service_con.reconnect())
125 * exit();
126 */
127service_con.reconnect = function()
128{
129 // this.reset is a list containing the IDs of FADs,
130 // which have neither CONNECTION==66 nor ==67, whatever this means :-)
131 if (this.reset.length==0)
132 return true;
133
134 console.out(" Reconnect: start ["+this.reset.length+"]");
135
136 for (var i=0; i<this.reset.length; i++)
137 dim.send("FAD_CONTROL/DISCONNECT", this.reset[i]);
138
139 v8.sleep(3000);
140
141 while (this.reset.length)
142 dim.send("FAD_CONTROL/CONNECT", this.reset.pop());
143
144 v8.sleep(1000);
145 dim.wait("FAD_CONTROL", "Connected", 3000);
146
147 console.out(" Reconnect: end");
148
149 return true;
150}
151
152function takeRun(type, count, time)
153{
154 if (!count)
155 count = -1;
156 if (!time)
157 time = -1;
158
159 console.out(" Take run N="+count+" T="+time+"s ["+type+"]");
160 // change rats for cal runs1!!!
161
162 dim.send("MCP/START", time?time:-1, count?count:-1, type);
163
164
165
166 // What could be a reasonable timeout here?
167 // FIXME: Replace by callback?
168 //
169 // DN: I believe instead of waiting for 'TakingData' one could split this
170 // up into two checks with an extra condition:
171 // if type == 'data':
172 // wait until ThresholdCalibration starts:
173 // --> this time should be pretty identical for each run
174 // if this takes longer than say 3s:
175 // there might be a problem with one/more FADs
176 //
177 // wait until "TakingData":
178 // --> this seems to take even some minutes sometimes...
179 // (might be optimized rather soon, but still in the moment...)
180 // if this takes way too long:
181 // there might be something broken,
182 // so maybe a very high time limit is ok here.
183 // I think there is not much that can go wrong,
184 // when the Thr-Calib has already started. Still it might be nice
185 // If in the future RateControl is written so to find out that
186 // in case the threshold finding algorithm does
187 // *not converge as usual*
188 // it can complain, and in this way give a hint, that the weather
189 // might be a little bit too bad.
190 // else:
191 // wait until "TakingData":
192 // --> in a non-data run this time should be pretty short again
193 // if this takes longer than say 3s:
194 // there might be a problem with one/more FADs
195 //
196
197 if (!dim.wait("MCP", "TakingData", -300000) )
198 {
199 console.out("MCP took longer than 5 minutes to start TakingData");
200 console.out("maybe this idicates a problem with one of the FADs?");
201 dimctrl.setState(37);
202 dim.wait("MCP", "TakingData", 500);
203 }
204 dim.wait("MCP", "Idle");
205
206 console.out(" Take run: end");
207
208 // DN: currently reconnect() never returns false
209 // .. but it can fail of course.
210 if (!service_con.reconnect())
211 exit();
212
213 return true;//service_con.reconnect();
214}
215
216// ----------------------------------------------------------------
217
218function doDrsCalibration()
219{
220 console.out(" DRS cal: start");
221 service_feedback.voltageOff();
222
223 while (1)
224 {
225 dim.send("FAD_CONTROL/START_DRS_CALIBRATION");
226 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
227 continue;
228 if (!takeRun("drs-gain", 1000)) // 40 / 20s (50Hz)
229 continue;
230 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
231 continue;
232
233 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
234 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
235 continue;
236 if (!takeRun("drs-time", 1000)) // 40 / 20s (50Hz)
237 continue;
238
239 dim.send("FAD_CONTROL/RESET_SECONDARY_DRS_BASELINE");
240 if (!takeRun("pedestal", 1000)) // 40 / 10s (80Hz)
241 continue;
242
243 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
244 if (!takeRun("pedestal", 1000)) // 40 / 10s (80Hz)
245 continue;
246 // -----------
247 // 4'40 / 2'00
248
249 break;
250 }
251
252 dim.send("RATE_CONTROL/STOP"); // get out of GlobalThresholdSet
253 dim.wait("RATE_CONTROL", "Connected", 3000);
254
255 console.out(" DRS cal: end");
256}
257
258// ----------------------------------------------------------------
259
260function OpenLid()
261{
262 var horizon_parameter = "nautical";
263 while (Sun.horizon( horizon_parameter ).isUp)
264 {
265 var minutes_until_sunset = (Sun.horizon( horizon_parameter ).set - new Date())/60000;
266 console.out("Open Lid - Info: ");
267 console.out(" Sun is above FACT-horizon, lid cannot be opened.");
268 console.out(" sleeping " + minutes_until_sunset + "minutes ...");
269 v8.sleep(60000);
270 }
271
272 console.out("Open lid: start");
273
274 // Wait for lid to be open
275 if (dim.state("LID_CONTROL").name=="Closed")
276 dim.send("LID_CONTROL/OPEN");
277 dim.wait("LID_CONTROL", "Open", 30000);
278 console.out("Open lid: done");
279}
280
281function CloseLid()
282{
283 console.out("Close lid: start");
284
285 // Wait for lid to be open
286 if (dim.state("LID_CONTROL").name=="Open")
287 dim.send("LID_CONTROL/CLOSE");
288 dim.wait("LID_CONTROL", "Closed", 30000);
289
290 console.out("Close lid: end");
291}
292
293// ----------------------------------------------------------------
294
295var service_feedback = new Subscription("FEEDBACK/DEVIATION");
296
297// DN: Why is voltageOff() implemented as
298// a method of a Subscription to a specific Service
299// I naively would think of voltageOff() as an unbound function.
300// I seems to me it has to be a method of a Subscription object, in order
301// to use the update counting method. But does it have to be
302// a Subscription to FEEDBACK/DEVIATION, or could it work with other services as well?
303service_feedback.voltageOff = function()
304{
305 console.out(" Voltage off: start");
306
307 var isOn = dim.state("BIAS_CONTROL").name=="VoltageOn";
308
309 if (isOn)
310 {
311 console.out(" Voltage on: switch off");
312 dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
313 }
314
315 dim.wait("BIAS_CONTROL", "VoltageOff", 5000);
316
317 // FEEDBACK stays in CurrentCtrl when Voltage is off but output enabled
318 // dim.wait("FEEDBACK", "CurrentCtrlIdle", 1000);
319
320 console.out(" Voltage off: end");
321}
322
323// DN: The name of the method voltageOn() in the context of the method
324// voltageOff() is a little bit misleading, since when voltageOff() returns
325// the caller can be sure the voltage is off, but when voltageOn() return
326// this is not the case, in the sense, that the caller can now take data.
327// instead the caller of voltageOn() *must* call waitForVoltageOn() afterwards
328// in order to safely take good-quality data.
329// This could lead to nasty bugs in the sense, that the second call might
330// be forgotten by somebody
331//
332// so I suggest to rename voltageOn() --> prepareVoltageOn()
333// waitForVoltageOn() stays as it is
334// and one creates a third method called:voltageOn() like this
335/* service_feedback.voltageOn = function()
336 * {
337 * this.prepareVoltageOn();
338 * this.waitForVoltageOn();
339 * }
340 *
341 * */
342// For convenience.
343
344service_feedback.voltageOn = function()
345{
346 //if (Sun.horizon("FACT").isUp)
347 // throw new Error("Sun is above FACT-horizon, voltage cannot be switched on.");
348
349 console.out(" Voltage on: start");
350
351 var isOff = dim.state("BIAS_CONTROL").name=="VoltageOff";
352
353 if (isOff)
354 {
355 console.out(" Voltage on: switch on");
356 console.out(JSON.stringify(dim.state("BIAS_CONTROL")));
357
358 dim.send("BIAS_CONTROL/SET_GLOBAL_DAC", 1);
359 }
360
361 // Wait until voltage on
362 dim.wait("BIAS_CONTROL", "VoltageOn", 5000);
363
364 // From now on the feedback waits for a valid report from the FSC
365 // and than switchs to CurrentControl
366 dim.wait("FEEDBACK", "CurrentControl", 60000);
367
368 if (isOff)
369 {
370 this.cnt = this.get().counter;
371 console.out(" Voltage on: cnt="+this.cnt);
372 }
373
374 console.out(" Voltage on: end");
375}
376
377
378
379service_feedback.waitForVoltageOn = function()
380{
381 // waiting 45sec for the current control to stabilize...
382 // v8.sleep(45000);
383
384 // ----- Wait for at least three updates -----
385 // The feedback is started as if the camera where at 0deg
386 // Then after the first temp update, the temperature will be set to the
387 // correct value (this has already happened)
388 // So we only have to wait for the current to get stable.
389 // This should happen after three to five current updates.
390 // So we want one recent temperature update
391 // and three recent current updates
392 console.out(" Voltage wait: start");
393 while (this.cnt==undefined || this.get().counter<=this.cnt+2)
394 v8.sleep();
395 console.out(" Voltage wait: end [cnt="+this.get().counter+"]");
396}
397
398// ================================================================
399// Crosscheck all states
400// ================================================================
401
402include('scripts/Startup.js');//Startup();
403
404/*
405include('scripts/CheckStates.js');
406
407var table =
408[
409 [ "TNG_WEATHER" ],
410 [ "MAGIC_WEATHER" ],
411 [ "CHAT" ],
412 [ "SMART_FACT" ],
413 [ "FSC_CONTROL", [ "Connected" ] ],
414 [ "MCP", [ "Idle" ] ],
415 [ "TIME_CHECK", [ "Valid" ] ],
416 [ "PWR_CONTROL", [ "SystemOn" ] ],
417 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
418 [ "BIAS_CONTROL", [ "VoltageOff" ] ],
419 [ "FEEDBACK", [ "CurrentControl", "CurrentCtrlIdle", "Connected" ] ],
420 [ "RATE_SCAN", [ "Connected" ] ],
421 [ "RATE_CONTROL", [ "Connected" ] ],
422 [ "LID_CONTROL", [ "Open", "Closed" ] ],
423 [ "DRIVE_CONTROL", [ "Armed", "Tracking", "OnTrack" ] ],
424 [ "FTM_CONTROL", [ "Idle", "TriggerOn" ] ],
425 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
426 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
427];
428
429console.out("Checking states.");
430if (!checkStates(table, 10000))
431{
432 throw new Error"Something unexpected has happened. Although the startup-",
433 "procedure has finished, not all servers are in the state",
434 "in which they ought to be. Please, try to find out what",
435 "happened...");
436}
437
438console.out("Checking states: done.");
439*/
440// ----------------------------------------------------------------
441
442console.out("Checking send.");
443checkSend(["MCP", "DRIVE_CONTROL", "LID_CONTROL", "FAD_CONTROL", "FEEDBACK"]);
444console.out("Checking send: done");
445
446// ----------------------------------------------------------------
447
448console.out("Feedback init: start.");
449service_feedback.get(5000);
450
451dim.send("FEEDBACK/ENABLE_OUTPUT", true);
452dim.send("FEEDBACK/START_CURRENT_CONTROL", 0.);
453
454console.out("Feedback init: end.");
455
456// ----------------------------------------------------------------
457// ================================================================
458// ----------------------------------------------------------------
459
460// this file just contains the definition of
461// the variable observations, which builds our nightly schedule, hence the filename
462include('scripts/schedule.js');
463
464// make Observation objects from user input and check if 'date' is increasing.
465for (var i=0; i<observations.length; i++)
466{
467 observations[i] = new Observation(observations[i]);
468
469 // check if the start date given by the user is increasing.
470 if (i>0 && observations[i].start <= observations[i-1].start)
471 {
472 throw new Error("Start time '"+ observations[i].start.toUTCString()+
473 "' in row "+i+" exceeds start time in row "+(i-1));
474 }
475}
476
477
478
479// ----------------------------------------------------------------
480// Bring the system into a well defined state
481// ----------------------------------------------------------------
482
483console.out("Drs runs init: start.");
484
485// FIMXE: Double subscription is not allowed!
486// also Startup needs DRS_RUNS
487var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
488service_drs.get(5000, false);
489
490console.out("Drs runs init: end.");
491
492// FIXME: Check if the last DRS calibration was complete?
493// ----------------------------------------------------------------
494
495// We have to stup a few things here which might not by set by Startup.js
496dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
497
498// ----------------------------------------------------------------
499
500console.out("Start main loop.");
501
502function Startup()
503{
504 /**** dummy ****/
505 console.out(" => [STARTUP] called.");
506}
507
508function Shutdown()
509{
510 /**** dummy ****/
511 //console.out(" => [SHUTDOWN] called.");
512 console.out("Shutdown: start");
513 service_feedback.voltageOff();
514 CloseLid();
515 dim.send("DRIVE_CONTROL/PARK");
516 dim.wait("DRIVE_CONTROL", "Moving", 3000);
517 dim.wait("DRIVE_CONTROL", "Armed", 120000);
518 console.out("Shutdown: end");
519}
520
521// Get the observation scheduled for 'now' from the table and
522// return its index
523function getObservation(now)
524{
525 if (now==undefined)
526 now = new Date();
527
528 if (isNaN(now.valueOf()))
529 throw new Error("Date argument in getObservation invalid.");
530
531 for (var i=0; i<observations.length; i++)
532 if ( now<observations[i].start )
533 return i-1;
534
535 return observations.length-1;
536}
537
538
539// DN: using so called magic numbers to encode certain
540// states of the logic is considered pretty bad coding as far as I understand.
541// the reader at this point has no idea why run is -2 ... this is the first time she
542// reads about this variable and there is not a word of explanation found.
543var run = -2;
544var lastObs;
545
546var test = getObservation();
547if (test!=undefined && test<observations.length)
548{
549 var t = observations[test].start;
550 var n = new Date();
551 if (t>n)
552 console.out(n.toUTCString()+": First observation scheduled for "+t.toUTCString());
553 else
554 console.out(n.toUTCString()+": First observation should start immediately.");
555 if (t>n+12*3600*1000)
556 console.out(n.toUTCString()+": No observations scheduled for the next 12 hours!");
557}
558
559while (1)
560{
561 // Check if observation position is still valid
562 // If source position has changed, set run=0
563 var idxObs = getObservation();
564 if (idxObs===undefined)
565 exit();
566
567 if (idxObs==-1)
568 {
569 v8.sleep(1000);
570 continue;
571 }
572
573 var obs = observations[idxObs];
574 var nextObs = observations[idxObs+1];
575
576 // Check if observation target has changed
577 if (lastObs!=idxObs)
578 {
579 console.out("--- "+idxObs+" ---");
580 console.out("Current time: "+new Date());
581 console.out("Current observation: "+obs);
582 console.out("Next observation: "+nextObs);
583 console.out("");
584
585 // This is the first source, but we do not come from
586 // a scheduled 'START', so we have to check if the
587 // telescop is operational already
588 if (run==-2)
589 {
590 Startup(); // -> Bias On/Off?, Lid open/closed?
591 CloseLid();
592 }
593
594 run = 0;
595 }
596 lastObs = idxObs;
597
598 // We have performed startup or shutdown... wait for next observation
599 if (run==-1)
600 {
601 v8.sleep(1000);
602 continue;
603 }
604
605 // Check if obs.task is one of the one-time-tasks
606 switch (obs.task)
607 {
608 case "STARTUP":
609 console.out(" STARTUP", "");
610 Startup(); // BiasOn/Off?, Lid open/close?
611 CloseLid();
612
613 console.out(" Take DRS calibration.");
614 doDrsCalibration(); // -> VoltageOff
615
616 service_feedback.voltageOn();
617 service_feedback.waitForVoltageOn();
618
619 // Before we can switch to 3000 we have to make the right DRS calibration
620 console.out(" Take single p.e. run.");
621 while (!takeRun("pedestal", 5000));
622
623 service_feedback.voltageOff();
624
625 console.out(" Waiting for first scheduled observation.","");
626 run = -1;
627 continue;
628
629 case "SHUTDOWN":
630 console.out(" SHUTDOWN","");
631 Shutdown();
632
633 console.out(" Waiting for next startup.", "");
634 run = -1;
635 continue;
636
637 case "RATESCAN":
638 console.out(" RATESCAN ");
639
640 dim.send("DRIVE_CONTROL/STOP");
641 dim.wait("DRIVE_CONTROL", "Armed", 5000);
642
643 if (obs.source != undefined)
644 dim.send("DRIVE_CONTROL/TRACK_ON", obs.source);
645 else
646 dim.send("DRIVE_CONTROL/TRACK", obs.ra, obs.dec);
647
648 //OpenLid();
649 dim.wait("DRIVE_CONTROL", "OnTrack", 300000);
650
651 // Checking if system is Ready for Data Taking, which is in this case
652 // the same as Ready for RateScan.
653 //
654 // this part might be simply wrong here, since I should be able to expect
655 // the system to be able for data taking. And if not, then it is not here,
656 // to bring the system into a better state, correct?
657
658 // [TB] Either here the system have to be brought to the correct state, or
659 // it has to be ensured that the previous code brought the system to a correct
660 // state. In this case checkStates could be used (but is a bit of obsolete)
661 // Doing non-throwing checks without checking the return value does not make
662 // sense at all.
663 dim.wait("FEEDBACK", "CurrentControl", -100);
664 dim.wait("BIAS_CONTROL", "VoltageOn", -100);
665 dim.wait("FAD_CONTROL", "Connected", -100);
666
667 dim.wait("RATE_SCAN","Connected", 5000);
668 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 50, 1000, -10);
669
670 // lets wait if the Ratescan really starts .. it should be started after 10sec max.
671 dim.wait("RATE_SCAN", "InProgress", 10000);
672 dim.wait("RATE_SCAN", "Connected", 2700000);
673
674 // this line is actually some kind of hack.
675 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
676 // So I decided to put this line here as a kind of patchwork....
677 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
678
679 console.out("Ratescan done.");
680 run = -1;
681 continue;
682 }
683/*
684 if (Sun.horizon("FACT").isUp)
685 {
686 console.out(" SHUTDOWN","");
687 Shutdown();
688 console.out(" Exit forced due to broken schedule", "");
689 exit();
690 }
691*/
692 // Calculate remaining time for this observation in minutes
693 var remaining = (nextObs.start-new Date())/60000;
694
695 // ------------------------------------------------------------
696
697 // Checking for 'Ramping' in the BIAS_CONTROL is not ideal, but at the moment
698 // it is not possible to distinguish between a real ramping and the short
699 // ramping which takes place whenever the feedback updated the voltages.
700
701 console.out(" Checking states [mainloop]");
702 var table =
703 [
704 [ "TNG_WEATHER" ],
705 [ "MAGIC_WEATHER" ],
706 [ "CHAT" ],
707 [ "SMART_FACT" ],
708 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
709 [ "FSC_CONTROL", [ "Connected" ] ],
710 [ "MCP", [ "Idle" ] ],
711 [ "TIME_CHECK", [ "Valid" ] ],
712 [ "PWR_CONTROL", [ "SystemOn" ] ],
713 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
714 [ "BIAS_CONTROL", [ "VoltageOff", "VoltageOn", "Ramping" ] ],
715 [ "FEEDBACK", [ "CurrentCtrlIdle", "CurrentControl" ] ],
716 [ "RATE_SCAN", [ "Connected" ] ],
717 [ "RATE_CONTROL", [ "Connected", "InProgress" ] ],
718 [ "LID_CONTROL", [ "Open", "Closed" ] ],
719 [ "DRIVE_CONTROL", [ "Armed", "Tracking", "OnTrack" ] ],
720 [ "FTM_CONTROL", [ "Idle", "TriggerOn" ] ],
721 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
722 ];
723
724 if (!checkStates(table))
725 {
726 //dim.alarm("System inconsistent");
727 //dim.alarm();
728 throw new Error("Something unexpected has happened. One of the servers "+
729 "is in a state in which it should not be. Please, "+
730 "try to find out what happened...");
731 }
732
733 console.out(" Checking states: end.");
734
735 // ------------------------------------------------------------
736
737 console.out(" Run #"+run+" ("+parseInt(remaining)+"min)");
738
739 // ----- Time since last DRS Calibration [min] ------
740 var runs = service_drs.get(0, false);
741 var diff = (new Date()-runs.time)/60000;
742
743 // Warning: 'roi=300' is a number which is not intrisically fixed
744 // but can change depending on the taste of the observers
745 var valid = runs.data[1][2]>0 && runs.data[0]==300;
746
747 if (valid)
748 console.out(" Last DRS calib: "+diff+"min ago");
749 else
750 console.out(" No valid drs calibration");
751
752 // Changine pointing position and take calibration...
753 // ...every four runs (every ~20min)
754 // ...if at least ten minutes of observation time are left
755 // ...if this is the first run on the source
756 var point = (run%4==0 && remaining>10) || run==0;
757
758 // Take DRS Calib...
759 // ...every four runs (every ~20min)
760 // ...at last every two hours
761 // ...when DRS temperature has changed by more than 2deg (?)
762 // ...when more than 15min of observation are left
763 // ...no drs calibration was done yet
764 var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
765
766 if (point)
767 {
768 // Change wobble position every four runs,
769 // start with alternating wobble positions each day
770 var wobble = (parseInt(run/4) + parseInt(new Date()/1000/3600/24-0.5))%2;
771
772 //console.out(" Move telescope to '"+source+"' "+offset+" "+wobble);
773 console.out(" Move telescope to '"+obs.source+"' ["+wobble+"]");
774
775 //var offset = observations[obs][2];
776 //var wobble = observations[obs][3 + parseInt(run/4)%2];
777
778 //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
779
780 dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble+1, obs.source);
781
782 // Do we have to check if the telescope is really moving?
783 // We can cross-check the SOURCE service later
784 }
785
786 if (drscal)
787 {
788 console.out(" Take DRS calibration.");
789 doDrsCalibration(); // -> VoltageOff
790 }
791
792 OpenLid();
793
794 // voltage must be switched on after the lid is open for the
795 // feedback to adapt the voltage properly to the night-sky
796 // background light level.
797 service_feedback.voltageOn();
798
799 // This is now th right time to wait for th drive to be stable
800 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
801
802 // Now we have to be prepared for data-taking:
803 // make sure voltage is on
804 service_feedback.waitForVoltageOn();
805
806 // If pointing had changed, do calibration
807 if (point)
808 {
809 console.out(" Calibration.");
810
811 // Calibration (2% of 20')
812 while (1)
813 {
814 if (!takeRun("pedestal", 1000)) // 80 Hz -> 10s
815 continue;
816 if (!takeRun("light-pulser-ext", 1000)) // 80 Hz -> 10s
817 continue;
818 break;
819 }
820 }
821
822 console.out(" Taking data: start [5min]");
823
824 var len = 300;
825 while (len>0)
826 {
827 var time = new Date();
828 if (!takeRun("data", -1, len)) // Take data (5min)
829 len -= parseInt((new Date()-time)/1000);
830 else
831 break;
832 }
833
834 //v8.sleep(360000);
835 console.out(" Taking data: done");
836
837 run++;
838}
839
840service_drs.close();
Note: See TracBrowser for help on using the repository browser.