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

Last change on this file since 15002 was 14998, checked in by tbretz, 13 years ago
Worked around the problem that sometimes (reason still to be found) obj['status'] is undefined; wait for the Rate control to really get to Idle afte a DRS calibration; throw an error rather than printing an error message. we are not yet there that we do not have to alarm the shifters by a red exception message; slightly increased the timeout after a STOP has been sent to the drive (it seems 3s was not enough, although I do not understand why it could take 4.2s, but it did); added Ramping state to the list of allowed states. That's not ideal, but it is pretty unlikely that the system is errornously in Ramping. This can only happen if somebody manually interacts with the system
File size: 26.4 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
546while (1)
547{
548 // Check if observation position is still valid
549 // If source position has changed, set run=0
550 var idxObs = getObservation();
551 if (idxObs===undefined)
552 exit();
553
554 if (idxObs==-1)
555 {
556 v8.sleep(1000);
557 continue;
558 }
559
560 var obs = observations[idxObs];
561 var nextObs = observations[idxObs+1];
562
563 // Check if observation target has changed
564 if (lastObs!=idxObs)
565 {
566 console.out("--- "+idxObs+" ---");
567 console.out("Current time: "+new Date());
568 console.out("Current observation: "+obs);
569 console.out("Next observation: "+nextObs);
570 console.out("");
571
572 // This is the first source, but we do not come from
573 // a scheduled 'START', so we have to check if the
574 // telescop is operational already
575 if (run==-2)
576 {
577 Startup(); // -> Bias On/Off?, Lid open/closed?
578 CloseLid();
579 }
580
581 run = 0;
582 }
583 lastObs = idxObs;
584
585 // We have performed startup or shutdown... wait for next observation
586 if (run==-1)
587 {
588 v8.sleep(1000);
589 continue;
590 }
591
592 // Check if obs.task is one of the one-time-tasks
593 switch (obs.task)
594 {
595 case "STARTUP":
596 console.out(" STARTUP", "");
597 Startup(); // BiasOn/Off?, Lid open/close?
598 CloseLid();
599
600 console.out(" Take DRS calibration.");
601 doDrsCalibration(); // -> VoltageOff
602
603 service_feedback.voltageOn();
604 service_feedback.waitForVoltageOn();
605
606 // Before we can switch to 3000 we have to make the right DRS calibration
607 console.out(" Take single p.e. run.");
608 while (!takeRun("pedestal", 5000));
609
610 service_feedback.voltageOff();
611
612 console.out(" Waiting for first scheduled observation.","");
613 run = -1;
614 continue;
615
616 case "SHUTDOWN":
617 console.out(" SHUTDOWN","");
618 Shutdown();
619
620 console.out(" Waiting for next startup.", "");
621 run = -1;
622 continue;
623
624 case "RATESCAN":
625 console.out(" RATESCAN ");
626
627 dim.send("DRIVE_CONTROL/STOP");
628 dim.wait("DRIVE_CONTROL", "Armed", 5000);
629
630 if (obs.source != undefined)
631 dim.send("DRIVE_CONTROL/TRACK_ON", obs.source);
632 else
633 dim.send("DRIVE_CONTROL/TRACK", obs.ra, obs.dec);
634
635 //OpenLid();
636 dim.wait("DRIVE_CONTROL", "OnTrack", 300000);
637
638 // Checking if system is Ready for Data Taking, which is in this case
639 // the same as Ready for RateScan.
640 //
641 // this part might be simply wrong here, since I should be able to expect
642 // the system to be able for data taking. And if not, then it is not here,
643 // to bring the system into a better state, correct?
644
645 // [TB] Either here the system have to be brought to the correct state, or
646 // it has to be ensured that the previous code brought the system to a correct
647 // state. In this case checkStates could be used (but is a bit of obsolete)
648 // Doing non-throwing checks without checking the return value does not make
649 // sense at all.
650 dim.wait("FEEDBACK", "CurrentControl", -100);
651 dim.wait("BIAS_CONTROL", "VoltageOn", -100);
652 dim.wait("FAD_CONTROL", "Connected", -100);
653
654 dim.wait("RATE_SCAN","Connected", 5000);
655 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 50, 1000, -10);
656
657 // lets wait if the Ratescan really starts .. it should be started after 10sec max.
658 dim.wait("RATE_SCAN", "InProgress", 10000);
659 dim.wait("RATE_SCAN", "Connected", 2700000);
660
661 // this line is actually some kind of hack.
662 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
663 // So I decided to put this line here as a kind of patchwork....
664 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
665
666 console.out("Ratescan done.");
667 run = -1;
668 continue;
669 }
670/*
671 if (Sun.horizon("FACT").isUp)
672 {
673 console.out(" SHUTDOWN","");
674 Shutdown();
675 console.out(" Exit forced due to broken schedule", "");
676 exit();
677 }
678*/
679 // Calculate remaining time for this observation in minutes
680 var remaining = (nextObs.start-new Date())/60000;
681
682 // ------------------------------------------------------------
683
684 // Checking for 'Ramping' in the BIAS_CONTROL is not ideal, but at the moment
685 // it is not possible to distinguish between a real ramping and the short
686 // ramping which takes place whenever the feedback updated the voltages.
687
688 console.out(" Checking states [mainloop]");
689 var table =
690 [
691 [ "TNG_WEATHER" ],
692 [ "MAGIC_WEATHER" ],
693 [ "CHAT" ],
694 [ "SMART_FACT" ],
695 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
696 [ "FSC_CONTROL", [ "Connected" ] ],
697 [ "MCP", [ "Idle" ] ],
698 [ "TIME_CHECK", [ "Valid" ] ],
699 [ "PWR_CONTROL", [ "SystemOn" ] ],
700 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
701 [ "BIAS_CONTROL", [ "VoltageOff", "VoltageOn", "Ramping" ] ],
702 [ "FEEDBACK", [ "CurrentCtrlIdle", "CurrentControl" ] ],
703 [ "RATE_SCAN", [ "Connected" ] ],
704 [ "RATE_CONTROL", [ "Connected", "InProgress" ] ],
705 [ "LID_CONTROL", [ "Open", "Closed" ] ],
706 [ "DRIVE_CONTROL", [ "Armed", "Tracking", "OnTrack" ] ],
707 [ "FTM_CONTROL", [ "Idle", "TriggerOn" ] ],
708 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
709 ];
710
711 if (!checkStates(table))
712 {
713 //dim.alarm("System inconsistent");
714 //dim.alarm();
715 throw new Error("Something unexpected has happened. One of the servers "+
716 "is in a state in which it should not be. Please, "+
717 "try to find out what happened...");
718 }
719
720 console.out(" Checking states: end.");
721
722 // ------------------------------------------------------------
723
724 console.out(" Run #"+run+" ("+parseInt(remaining)+"min)");
725
726 // ----- Time since last DRS Calibration [min] ------
727 var runs = service_drs.get(0, false);
728 var diff = (new Date()-runs.time)/60000;
729
730 // Warning: 'roi=300' is a number which is not intrisically fixed
731 // but can change depending on the taste of the observers
732 var valid = runs.data[1][2]>0 && runs.data[0]==300;
733
734 if (valid)
735 console.out(" Last DRS calib: "+diff+"min ago");
736 else
737 console.out(" No valid drs calibration");
738
739 // Changine pointing position and take calibration...
740 // ...every four runs (every ~20min)
741 // ...if at least ten minutes of observation time are left
742 // ...if this is the first run on the source
743 var point = (run%4==0 && remaining>10) || run==0;
744
745 // Take DRS Calib...
746 // ...every four runs (every ~20min)
747 // ...at last every two hours
748 // ...when DRS temperature has changed by more than 2deg (?)
749 // ...when more than 15min of observation are left
750 // ...no drs calibration was done yet
751 var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
752
753 if (point)
754 {
755 var wobble = parseInt(run/4)%2;
756
757 //console.out(" Move telescope to '"+source+"' "+offset+" "+wobble);
758 console.out(" Move telescope to '"+obs.source+"' ["+wobble+"]");
759
760 //var offset = observations[obs][2];
761 //var wobble = observations[obs][3 + parseInt(run/4)%2];
762
763 //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
764
765 dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble+1, obs.source);
766
767 // Do we have to check if the telescope is really moving?
768 // We can cross-check the SOURCE service later
769 }
770
771 if (drscal)
772 {
773 console.out(" Take DRS calibration.");
774 doDrsCalibration(); // -> VoltageOff
775 }
776
777 OpenLid();
778
779 // voltage must be switched on after the lid is open for the
780 // feedback to adapt the voltage properly to the night-sky
781 // background light level.
782 service_feedback.voltageOn();
783
784 // This is now th right time to wait for th drive to be stable
785 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
786
787 // Now we have to be prepared for data-taking:
788 // make sure voltage is on
789 service_feedback.waitForVoltageOn();
790
791 // If pointing had changed, do calibration
792 if (point)
793 {
794 console.out(" Calibration.");
795
796 // Calibration (2% of 20')
797 while (1)
798 {
799 if (!takeRun("pedestal", 1000)) // 80 Hz -> 10s
800 continue;
801 if (!takeRun("light-pulser-ext", 1000)) // 80 Hz -> 10s
802 continue;
803 break;
804 }
805 }
806
807 console.out(" Taking data: start [5min]");
808
809 var len = 300;
810 while (len>0)
811 {
812 var time = new Date();
813 if (!takeRun("data", -1, len)) // Take data (5min)
814 len -= parseInt((new Date()-time)/1000);
815 else
816 break;
817 }
818
819 //v8.sleep(360000);
820 console.out(" Taking data: done");
821
822 run++;
823}
824
825service_drs.close();
Note: See TracBrowser for help on using the repository browser.