source: trunk/MagicSoft/Cosy/main/MCosy.cc@ 1997

Last change on this file since 1997 was 1953, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 57.1 KB
Line 
1#include "MCosy.h"
2#include "MCosy.h"
3
4#include <iomanip.h>
5#include <fstream.h>
6#include <iostream.h>
7
8#include <TROOT.h>
9#include <TEnv.h>
10#include <TSystem.h>
11#include <TApplication.h>
12#include <TTimer.h>
13
14#include <TH2.h>
15#include <TH3.h>
16#include <TProfile.h>
17#include <TCanvas.h>
18
19#include "MGCosy.h"
20#include "SlaStars.h"
21
22#include "slalib/slalib.h" // FIXME: REMOVE
23
24#include "macs.h"
25#include "base/timer.h"
26#include "shaftencoder.h"
27
28//#include <sys/resource.h> // PRIO_PROCESS
29
30ClassImp(MCosy);
31
32typedef struct tm tm_t;
33
34/*
35#define GEAR_RATIO_ALT 2475.6 // [U_mot/U_tel(360deg)]
36#define GEAR_RATIO_AZ 5891.7 // [U_mot/U_tel(360deg)]
37
38#define RES_RE 500 // [re/U_mot]
39#define RES_SE 16384 // [se/U_tel(360deg)]
40*/
41/*
42 #define GEAR_RATIO_ALT (75.55*16384/1500) // 75.25 VERY IMPORTANT! unit=U_mot/U_tel
43 #define GEAR_RATIO_AZ (179.8*16384/1500) // VERY IMPORTANT! unit=U_mot/U_tel
44*/
45
46//const XY kGearRatio (GEAR_RATIO_ALT*RES_RE/RES_SE, GEAR_RATIO_AZ*RES_RE/RES_SE); //[re/se]
47//const XY kGearRatio2(GEAR_RATIO_ALT*RES_RE/360.0, GEAR_RATIO_AZ*RES_RE/360.0); //[re/deg]
48
49/* +===================================+
50 FIXME: What if fMac3 (Sync) died?
51 +===================================+
52*/
53
54double MCosy::Rad2SE(double rad) const
55{
56 return 16384.0/k2Pi*rad;
57}
58
59double MCosy::Rad2ZdRE(double rad) const
60{
61 return 16384.0/k2Pi*rad*kGearRatio.X();
62}
63
64double MCosy::Rad2AzRE(double rad) const
65{
66 return 16384.0/k2Pi*rad*kGearRatio.Y();
67}
68
69double MCosy::Deg2ZdRE(double rad) const
70{
71 return rad*kGearRatio2.X();
72}
73
74double MCosy::Deg2AzRE(double rad) const
75{
76 return rad*kGearRatio2.Y();
77}
78
79/*
80ZdAz MCosy::CorrectTarget(const ZdAz &src, const ZdAz &dst)
81{
82 // CorrectTarget [se]
83
84 // src [se]
85 // dst [rad]
86
87 // fAltMax = 70
88 // fAltMin = -105/110
89 // fAzMin = -355
90 // fAzMax = 355
91
92 ZdAz source = src * 360.0/16384.0;
93 ZdAz dest = dst * kRad2Deg;
94
95 if (dest.Zd()>-3 && dest.Zd()<3)
96 dest.Zd(dest.Zd()<0?-3:3);
97
98 if (dest.Zd()>-1e-6 && dest.Zd()<1e-6)
99 return dst*(16384.0/k2Pi);
100
101 const float fZdMin = -67;
102 const float fZdMax = 67;
103 const float fAzMin = -29;
104 const float fAzMax = 423;
105
106 //
107 // This corrects to target for the shortest distance, not for the fastest move!
108 //
109 ZdAz s = source-dest;
110
111 float min = s.Sqr();
112
113 //
114 // Is it enought to search inside one revolution?
115 //
116 ZdAz ret = dest;
117
118 for (int i=-5; i<5+1; i++)
119 {
120 const ZdAz p(i%2 ? -dest.Zd() : dest.Zd(), dest.Az() - i*180);
121
122 //
123 // Range Check
124 //
125 if (p.Zd()<fZdMin || p.Zd()>fZdMax)
126 continue;
127
128 if (p.Az()<fAzMin || p.Az()>fAzMax)
129 continue;
130
131 //
132 // Calculate distance
133 //
134 s = source-p;
135
136 const float dist = s.Sqr();
137
138 if (dist > min)
139 continue;
140
141 //
142 // New shortest distance
143 //
144 ret = p;
145 min = dist;
146 }
147 return ret*(16384.0/360.0);
148}
149*/
150
151// --------------------------------------------------------------------------
152//
153// GetSePos, reads the Shaftencoder positions from the Can-drivers
154// for the shaftencoders. The two shaft encoders at the elevation axis
155// are avaraged. The values are returned as a ZdAz object.
156//
157// If one of the two shaftencoders on the elevation axis is missing
158// the other one's position is returned.
159//
160// The positions are alway up-to-date because the shaftencoders are
161// sending all changes immediatly.
162//
163ZdAz MCosy::GetSePos()
164{
165 const int pa = fAz->GetPos();
166 if (fZd1->IsZombieNode() && fZd2->IsZombieNode())
167 return ZdAz(0, pa);
168
169 //
170 // Get the values
171 //
172 int p1 = (fZd1->GetPos()+8192)%16384;
173 int p2 = -(fZd2->GetPos()+8192)%16384;
174
175 if (fZd1->IsZombieNode())
176 return ZdAz(p2, pa);
177 if (fZd2->IsZombieNode())
178 return ZdAz(p1, pa);
179
180 //
181 // interpolate shaft encoder positions
182 //
183 float p = (float)(p1+p2)/2;
184
185 return ZdAz(p, pa);
186}
187
188// --------------------------------------------------------------------------
189//
190// request the current positions from the rotary encoders.
191// use GetRePos to get the psotions. If the request fails the function
192// returns kFALSE, otherwise kTRUE
193//
194Bool_t MCosy::RequestRePos()
195{
196 //
197 // Send request
198 //
199 fMac2->RequestSDO(0x6004);
200 fMac1->RequestSDO(0x6004);
201
202 //
203 // Wait until the objects are received.
204 //
205 fMac2->WaitForSdo(0x6004);
206 fMac1->WaitForSdo(0x6004);
207
208 // FIXME, what when waiting times out (Zombie)
209 // WaitForSdos();
210
211 //
212 // If waiting was not interrupted everything is ok. return.
213 //
214 if (!(Break() || HasError()) && !HasZombie())
215 return kTRUE;
216
217 //
218 // If the waiting was interrupted due to a network error,
219 // print some logging message.
220 //
221 if (HasError())
222 lout << "Error while requesting re pos from Macs (SDO #6004)" << endl;
223
224 return kFALSE;
225}
226
227// --------------------------------------------------------------------------
228//
229// reads the Rotary encoder positions from the last request of the Macs.
230//
231// The positions are returned as a ZdAz object. Use RequestRePos to request
232// the current positions first.
233//
234ZdAz MCosy::GetRePos()
235{
236 return ZdAz(fMac2->GetPos(), fMac1->GetPos());
237}
238
239// --------------------------------------------------------------------------
240//
241// reads the Rotary encoder positions from the Macs.
242//
243// The positions are returned as a ZdAz object. The positions are the ones
244// which are send as PDOs to the computer. This is done at a given
245// frequency. Which means, that this positions are not ought to be
246// up-to-date.
247//
248ZdAz MCosy::GetRePosPdo()
249{
250 return ZdAz(fMac2->GetPdoPos(), fMac1->GetPdoPos());
251}
252
253
254
255// --------------------------------------------------------------------------
256//
257// set the velocity and accelerations for position maneuvers.
258//
259// The acceleratin is set as given (in percent of maximum).
260// The velocity is given in percent, depending on the ratio (<1 or >1)
261// one of the axis becomes a slower velocity. This is used for maneuvers
262// in which both axis are moved synchromously and should reach their
263// target position at the same time.
264//
265void MCosy::SetPosVelocity(const Float_t ratio, Float_t vel)
266{
267 //
268 // Set velocities
269 //
270 const int vr = fMac1->GetVelRes();
271
272 vel *= vr;
273
274 if (ratio <1)
275 {
276 fMac1->SetVelocity(vel);
277 fMac2->SetVelocity(vel*ratio);
278 }
279 else
280 {
281 fMac1->SetVelocity(vel/ratio);
282 fMac2->SetVelocity(vel);
283 }
284}
285
286// --------------------------------------------------------------------------
287//
288// Does a relative positioning.
289//
290// The steps to move are given in a ZdAz object relative to the current
291// position. The coordinates are given in Roteryencoder steps.
292// Axis 1 is moved only if axe1==kTRUE, Axis 2 is moved only
293// if Axis 2==kTRUE. The function waits for the movement to be finished.
294//
295void MCosy::DoRelPos(const ZdAz &rd, const Bool_t axe1, const Bool_t axe2)
296{
297 if (HasZombie())
298 return;
299
300 SetStatus(MCosy::kMoving);
301
302 if (axe1) fMac2->StartRelPos(rd.Zd());
303 if (axe2) fMac1->StartRelPos(rd.Az());
304
305 cout << "Waiting for positioning..." << flush;
306
307 if (axe1) fMac2->WaitForSdo(0x6004, 1);
308 if (axe2) fMac1->WaitForSdo(0x6004, 1);
309
310 WaitForEndMovement();
311
312 cout << "done." << endl;
313}
314
315// --------------------------------------------------------------------------
316//
317// check for a break-signal (from the msgqueue) and errors.
318//
319int MCosy::StopWaitingForSDO() const
320{
321 return 0/*Break() || HasError()*/;
322}
323
324// --------------------------------------------------------------------------
325//
326// Waits for a movement to become finished.
327//
328// First waits for all peding Sdos, then waits until both motors are stopped
329// or waiting for SDOs was stopped (either by an error or by Break)
330//
331void MCosy::WaitForEndMovement()
332{
333 // FIXME, what when waiting times out (Zombie)
334
335 while ((fMac1->IsPositioning() || fMac2->IsPositioning()) &&
336 !(Break() || HasError() || HasZombie()))
337 usleep(1);
338
339 if (Break() || HasError() || HasZombie())
340 {
341 lout << "WaitForEndMovement aborted... ";
342 if (Break())
343 lout << "Break signal." << endl;
344 if (HasError())
345 lout << "Network has error." << endl;
346 if (HasZombie())
347 lout << "Network has zombie." << endl;
348 }
349}
350
351// --------------------------------------------------------------------------
352//
353// Check for an error...
354//
355// This is ment for usage after the Action: All Motors Stop.
356//
357void MCosy::CheckForError()
358{
359 //
360 // Check all Can-Nodes for an Error. If there is no error the motor
361 // status is set to stopped.
362 //
363 if (!HasError())
364 {
365 SetStatus(MCosy::kStopped);
366 return;
367 }
368
369 //
370 // If there is an error, the error status is set to Error.
371 //
372 SetStatus(MCosy::kError);
373
374 /*
375 FIXME: HANDLINGE ERROR
376
377 //
378 // Now try to handle the error.
379 //
380 fMac1->HandleError();
381 fMac2->HandleError();
382
383 //
384 // If the error couldn't get solved return
385 //
386 if (HasError())
387 return;
388
389 //
390 // Set motor status to stopped
391 //
392 SetStatus(MCosy::kStopped);
393 */
394}
395
396Bool_t MCosy::CheckRange(const ZdAz &d) const
397{
398 // d [deg]
399
400 if (d.Zd()<fMin.Zd() || d.Zd()>fMax.Zd())
401 {
402 lout << "ERROR: Requested Zenith Angle (" << d.Zd() << "deg) not ";
403 lout << "inside allowed range." << endl;
404 return kFALSE;
405 }
406
407 if (d.Az()<fMin.Az() || d.Az()>fMax.Az())
408 {
409 lout << "ERROR: Requested Azimuth Angle (" << d.Az() << "deg) not ";
410 lout << "inside allowed range." << endl;
411 return kFALSE;
412 }
413
414 return kTRUE;
415}
416
417// --------------------------------------------------------------------------
418//
419// Move the telescope to the given position. The position must be given in
420// a ZdAz object in rad.
421//
422// The first positioning is done absolutely. If we didn't reach the
423// correct psotion we try to correct for this by 10 relative position
424// maneuvers. If this doesn't help positioning failed.
425//
426// As a reference the shaftencoder values are used.
427//
428int MCosy::SetPosition(const ZdAz &dst, Bool_t track) // [rad]
429{
430 // FIXME: Correct by fOffset ?
431
432 const ZdAz d = dst*kRad2Deg;
433
434 lout << "Target Position: " << d.Zd() << "deg, " << d.Az() << "deg (Zd/Az)" << endl;
435
436 if (!CheckRange(d))
437 return kFALSE;
438
439 //
440 // Calculate new target position (shortest distance to go)
441 //
442 const ZdAz src = GetSePos(); // [se]
443
444 /*
445 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
446 {
447 cout << "SetPosition: No connection to at least one of the MACS!" << endl;
448 return TRUE;
449 }
450 */
451
452 //
453 // Make sure that the motors are in sync mode (necessary if the
454 // MACS has been rebooted from a Zombie state.
455 //
456 //InitSync();
457 //if (fMac3->IsZombieNode())
458 // return false;
459
460 // ====================================
461 RequestRePos();
462 ZdAz before = GetRePos();
463 // ====================================
464
465 //
466 // Because we agreed on I don't search for the shortest move
467 // anymore
468 //
469 // const ZdAz dest = CorrectTarget(src, dst);
470 //
471 const ZdAz dest = fBending(dst)*16384/2/TMath::Pi(); // [se]
472 fZdAzSoll = dst;
473
474 cout << "Source Zd: " << src.Zd() << "se Az:" << src.Az() << "se" << endl;
475 cout << "Destination Zd: " << Rad2SE(dst.Zd()) << "se Az:" << Rad2SE(dst.Az()) << "se" << endl;
476 cout << "Bend'd Dest Zd: " << Rad2SE(fZdAzSoll.Zd()) << "se Az:" << Rad2SE(fZdAzSoll.Az()) << "se" << endl;
477 cout << "Shortest Dest Zd: " << dest.Zd() << "se Az:" << dest.Az() << "se" << endl;
478
479 /*
480 * re(se) = -28.1*cos(x*360/16384/se - 14.4) + 443.2*re/se
481 *
482 * int(re) = -1278.86*sin(0.021972656 *x/se - 14.4 )re + 443.2re x/se
483 * int(re) = -73273.4*sin(0.000383495197*x/se - .2513274)re + 443.2re x/se
484 *
485 * int (-75deg..95deg) = 3.28343e7 re
486 *
487 */
488
489 //
490 // Set velocities
491 //
492 const int vr = fMac1->GetVelRes();
493
494 int i;
495 for (i=0; i<10 && !(Break() || HasError()) && !HasZombie(); i++)
496 {
497
498 lout << "Step #" << i << endl;
499 //
500 // Get Shaft Encoder Positions
501 //
502 const ZdAz p=GetSePos();
503
504 //
505 // calculate control deviation and rounded cd
506 //
507 ZdAz rd = dest-p; // [se]
508/*
509 if (rd.Az()>0 && rd.Az()<0.5)
510 rd.Az(1);
511 if (rd.Az()<0 && rd.Az()>-0.5)
512 rd.Az(-1);
513*/
514 cout << "Deviation: " << rd.Zd() << "se Az:" << rd.Az() << "se" << endl;
515
516
517 // ===========================================
518 Float_t k1 = dest.Zd()*360/16384 - 14.3979; //[deg]
519 Float_t k0 = p.Zd()*360/16384 - 14.3979; //[deg]
520
521 //
522 // -28re/se*cos((x/deg-14.4)*pi/180) + 443.2re/se x
523 // 28re/se*2*pi/360*sin((x/deg-14.4)*pi/180)*deg + 443.2re/se*x/deg
524 //
525
526 Float_t dk = 443.152*(dest.Zd()-p.Zd());
527 Float_t dx = 28.0148/2/TMath::Pi()*(sin(k1/kRad2Deg)-sin(k0/kRad2Deg));
528
529 cout << "Using: " << rd.Zd()*kGearRatio.X() << endl; // [re]
530 cout << "Estimated1: " << 16384*dx + dk << endl;
531 cout << "Estimated2: " << (16384*dx + dk)/1.085949688 << endl;
532 cout << "Estimated3: " << rd.Zd()*432 << endl;
533 // ===========================================
534
535
536 ZdAz cd = rd; // [se]
537 cd.Round();
538/*
539 if (rd.Az()>0 && rd.Az()<0.5)
540 rd.Az(0.5);
541 if (rd.Az()<0 && rd.Az()>-0.5)
542 rd.Az(-0.5);
543*/
544 //
545 // Check if there is a control deviation on the axis
546 //
547 const Bool_t cdzd = (int)cd.Zd() ? kTRUE : kFALSE;
548 const Bool_t cdaz = (int)cd.Az() ? kTRUE : kFALSE;
549
550 //
551 // check if we reached the correct position already
552 //
553 if (!cdzd && !cdaz)
554 {
555 lout << "Positioning done in " << i << (i==1?" step.":" steps.") << endl;
556 SetStatus(MCosy::kStopped);
557
558 // ====================================
559 RequestRePos();
560 ZdAz after = GetRePos();
561 // ====================================
562
563 after -= before;
564
565 cout << "Drove: " << after.Zd() << " " << after.Az() << endl;
566 return TRUE;
567 }
568
569 //
570 // change units from se to re
571 //
572 rd *= kGearRatio; // [re]
573
574 //
575 // Initialize Velocities so that we reach both positions
576 // at the same time
577 //
578 if (i)
579 {
580 fMac1->SetAcceleration(0.1*vr);
581 fMac2->SetAcceleration(0.1*vr);
582
583 fMac1->SetDeceleration(0.1*vr);
584 fMac2->SetDeceleration(0.1*vr);
585
586 SetPosVelocity(1.0, 0.05);
587 }
588 else
589 {
590 if (rd.Az()>-15*kGearRatio.Y() && rd.Az()<15*kGearRatio.Y())
591 {
592 cout << " -------------- LO ---------------- " << endl;
593 fMac1->SetAcceleration(0.05*vr);
594 fMac1->SetDeceleration(0.05*vr);
595 }
596 else
597 {
598 cout << " -------------- HI ---------------- " << endl;
599 fMac1->SetAcceleration(0.2*vr);
600 fMac1->SetDeceleration(0.1*vr);
601 }
602
603 fMac2->SetAcceleration(0.2*vr);
604 fMac2->SetDeceleration(0.1*vr);
605
606 // vel(0.6) acc(0.5)
607 SetPosVelocity(fabs(rd.Ratio()), 0.175);
608 // SetPosVelocity(fabs(rd.Ratio()), 0.1, 0.3);
609 }
610
611 rd.Round();
612
613 // FIXME? Check for Error or Zombie?
614
615 /*
616 cout << " + " << (int)cdzd << " " << (int)cdaz << endl;
617 cout << " + APOS: Zd=" << setw(6) << p.Zd() << "se Az=" << setw(6) << p.Az() << "se" << endl;
618 cout << " + dZd=" << setw(6) << cd.Zd() << "se dAz=" << setw(6) << cd.Az() << "se" << endl;
619 cout << " + dZd=" << setw(6) << rd.Zd() << "re dAz=" << setw(6) << rd.Az() << "re" << endl;
620 cout << " + Ratio: Zd=" << setw(6) << kGearRatio.X() << "se Az=" << setw(6) << kGearRatio.Y() << "se" << endl;
621 */
622
623 //
624 // repositioning (relative)
625 //
626 lout << "Do Relative Positioning Done" << endl;
627 DoRelPos(rd, cdzd, cdaz);
628
629 lout << "Relative Positioning Done" << endl;
630 }
631
632 if (i<10)
633 StopMovement();
634
635 lout << "Warning: Requested position not reached (i=" << i << ")" << endl;
636 return FALSE;
637}
638
639// --------------------------------------------------------------------------
640//
641// Sets the tracking velocity
642//
643// The velocities are given in a ZdAz object in re/min. Return kTRUE
644// in case of success, kFALSE in case of failure.
645//
646Bool_t MCosy::SetVelocity(const ZdAz &v)
647{
648 //
649 // Send the new velocities for both axes.
650 //
651 fMac2->SendSDO(0x3006, 1, (LWORD_t)v.Zd()); // SetRpmVelocity [re/min]
652 fMac1->SendSDO(0x3006, 1, (LWORD_t)v.Az()); // SetRpmVelocity [re/min]
653
654 //
655 // Wait for the objects to be OKed.
656 //
657
658 fMac2->WaitForSdo(0x3006, 1);
659 fMac1->WaitForSdo(0x3006, 1);
660
661 // FIXME, what when waiting times out (Zombie)
662 // WaitForSdos();
663
664 //
665 // If the waiting for the objects wasn't interrupted return kTRUE
666 //
667 if (!(Break() || HasError()) && !HasZombie())
668 return kTRUE;
669
670 //
671 // print a message if the interruption was due to a Can-node Error
672 //
673 if (HasError())
674 lout << "Error while setting velocity (SDO #3006)" << endl;
675
676 return kFALSE;
677}
678
679// --------------------------------------------------------------------------
680//
681// Initializes Tracking mode
682//
683// Initializes the accelerations of both axes with 90% of the maximum
684// acceleration. Set the status for moving and tracking and starts thr
685// revolution mode.
686//
687bool MCosy::InitTracking()
688{
689 // FIXME? Handling of Zombie OK?
690 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
691 return false;
692
693 //
694 // Start revolution mode
695 //
696 fMac2->SetAcceleration(0.2*fMac2->GetVelRes());
697 fMac2->SetDeceleration(0.2*fMac2->GetVelRes());
698 if (fMac2->IsZombieNode())
699 return false;
700
701 fMac1->SetAcceleration(0.2*fMac1->GetVelRes());
702 fMac1->SetDeceleration(0.2*fMac1->GetVelRes());
703 if (fMac1->IsZombieNode())
704 return false;
705
706 SetStatus(MCosy::kMoving | MCosy::kTracking);
707
708 fMac2->SetRpmMode(TRUE);
709 if (fMac2->IsZombieNode())
710 return false;
711
712 fMac1->SetRpmMode(TRUE);
713 if (fMac1->IsZombieNode())
714 return false;
715
716 return true;
717}
718
719// --------------------------------------------------------------------------
720//
721// Limits the speed.
722//
723// This function should work as a limiter. If a tracking error is too large
724// to be corrected fast enough we would get enormous velocities. These
725// velocities are limited to the maximum velocity.
726//
727void MCosy::LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const
728{
729 //
730 // How to limit the speed. If the wind comes and blowes
731 // we cannot forbid changing of the sign. But on the other hand
732 // we don't want fast changes!
733 //
734
735 ULong_t vrzd = fMac1->GetVelRes();
736 ULong_t vraz = fMac2->GetVelRes();
737
738#define sgn(x) (x<0?-1:1)
739
740 const Float_t limit = 0.25;
741/*
742 if (sgn(vt->Az()) != sgn(vcalc.Az()))
743 vt->Az(0);
744// else
745 {
746 if (fabs(vt->Az()) < fabs(vcalc.Az()) *0.5)
747 vt->Az(0.5*vcalc.Az());
748
749 if (fabs(vt->Az()) > fabs(vcalc.Az()) *1.5)
750 vt->Az(1.5*vcalc.Az());
751 }
752
753 if (sgn(vt->Zd()) != sgn(vcalc.Zd()))
754 vt->Zd(0);
755// else
756 {
757 if (fabs(vt->Zd()) > fabs(vcalc.Az()) *1.5)
758 vt->Zd(1.5*vcalc.Zd());
759
760 if (fabs(vt->Zd()) < fabs(vcalc.Az()) *0.5)
761 vt->Zd(0.5*vcalc.Zd());
762 }
763 */
764
765 if (sgn(vt->Az()) != sgn(vcalc.Az())
766 && fabs(vt->Az()) < limit*fabs(vcalc.Az())
767 )
768 vt->Az(0);
769 else
770 if (fabs(vt->Az()) > 0.9*vraz)
771 {
772 lout << "Warning: Azimuth speed limit exceeded. Limiting speed to 90% max." << endl;
773 vt->Az(0.9*vraz*sgn(vt->Az()));
774 }
775
776 if (sgn(vt->Zd()) != sgn(vcalc.Zd())
777 && fabs(vt->Zd()) < limit*fabs(vcalc.Zd())
778 )
779 vt->Zd(0);
780 else
781 if (fabs(vt->Zd()) > 0.9*vrzd)
782 {
783 lout << "Warning: Altitude speed limit exceeded. Limiting speed to 90% max." << endl;
784 vt->Zd(0.9*vrzd*sgn(vt->Zd()));
785 }
786}
787
788Bool_t MCosy::AlignTrackingPos(ZdAz pointing, ZdAz &za)
789{
790 // pointing [deg]
791
792 if (pointing.Zd()<0)
793 {
794 pointing.Zd(-pointing.Zd());
795 pointing.Az(pointing.Az()+180);
796 }
797
798 const ZdAz se = GetSePos()*360/16384; // [deg]
799 const ZdAz unbendedse = fBending.CorrectBack(se); // ist pointing
800
801 do
802 {
803 const Double_t d = unbendedse.Az() - pointing.Az();
804 if (d>-180 && d<=180)
805 break;
806
807 pointing.Az(pointing.Az()+TMath::Sign(360., -d));
808 } while (1);
809 /*
810 while (pointing.Az()<fMin.Az())
811 pointing.Az(pointing.Az() + 360);
812
813 while (pointing.Az()>fMax.Az())
814 pointing.Az(pointing.Az() - 360);
815 */
816 const Bool_t rc = CheckRange(pointing);
817 za = fBending(pointing/kRad2Deg); // [rad]
818
819 if (!rc)
820 lout << "Error: Aligned position out of Range." << endl;
821
822 return rc;
823}
824
825void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad]
826{
827 lout << "Track Position: " << dst.Ra()*kRad2Deg/15 << "h, " << dst.Dec()*kRad2Deg << "deg (Ra/Dec)" << endl;
828
829 SlaStars sla(fObservatory);
830
831 //
832 // Position to actual position
833 //
834 sla.Now();
835 ZdAz dest = sla.CalcZdAz(dst);
836
837 // FIXME: Determin tracking start point by star culmination
838 if (dest.Az()<-TMath::Pi()/2)
839 {
840 lout << "Adding 360deg to Azimuth " << dest.Az()*kRad2Deg << endl;
841 dest.Az(dest.Az() + TMath::Pi()*2);
842 }
843
844 if (dest.Az()>3*TMath::Pi()/2)
845 {
846 lout << "Substracting 360deg to Azimuth " << dest.Az()*kRad2Deg << endl;
847 dest.Az(dest.Az() -TMath::Pi()*2);
848 }
849
850 if (!SetPosition(dest, kTRUE))
851 {
852 lout << "Error: Cannot start tracking, positioning failed." << endl;
853 return;
854 }
855
856 //
857 // calculate offset from present se position
858 //
859 const ZdAz sepos = GetSePos()*kGearRatio;
860
861 if (!RequestRePos())
862 return;
863
864 //
865 // Estimate Offset before starting to track
866 //
867 fOffset = sepos-GetRePos();
868
869 /*
870 cout << "Sepos: " << sepos.Zd() << "re, " << sepos.Az() << "re" << endl;
871 cout << "Repos: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
872 cout << "Offset: " << fOffset.Zd() << "re, " << fOffset.Az() << "re" << endl;
873 */
874
875 //
876 // Init accelerations and Rpm Mode
877 //
878 if (!InitTracking())
879 return;
880
881 XY xy(Rad2Deg(dst.Ra())*24/360, Rad2Deg(dst.Dec()));
882
883 lout << "Start tracking:";
884 lout << " Ra: " << xy.X() << "h " << "Dec: " << xy.Y() << "\xb0" << endl;
885
886 ofstream fout("coordinates.txt");
887 fout << xy;
888 fout.close();
889
890 //
891 // Initialize Tracker (slalib or starguider)
892 //
893 fRaDec = dst;
894 fBackground = kBgdTracking;
895
896//--- ofstream fout("log/cosy.pos");
897//--- fout << "Tracking:";
898//--- fout << " Ra: " << Rad2Deg(dst.Ra()) << "\x9c ";
899//--- fout << "Dec: " << Rad2Deg(dst.Dec()) << "\x9c" << endl << endl;
900//--- fout << " Mjd/10ms V/re/min/4" << endl;
901
902 //
903 // We want to reach the theoretical position exactly in about 0.5s
904 //
905 // *OLD*const float dt = 1; // 1 second
906 const float dt = 5;//3; // 2 second
907 while (!(Break() || HasError() || HasZombie()))
908 {
909 //
910 // Request Target position for this moment
911 //
912 sla.Now();
913
914 //
915 // Request theoretical Position for a time in the future (To+dt) from CPU
916 //
917 const Double_t mjd = sla.GetMjd()+dt/(60*60*24);
918 const ZdAz pointing = sla.CalcZdAz(fRaDec, mjd)*kRad2Deg; // soll pointing [deg]
919
920 ZdAz dest;
921 if (!AlignTrackingPos(pointing, dest))
922 break;
923
924 dest *= 16384/TMath::Pi()/2; // [se]
925
926 /*
927 ZdAz dummy1 = sla.CalcZdAz(fRaDec);
928
929 if (dummy1.Az()<-TMath::Pi()/2)
930 dummy1.Az(dummy1.Az() + TMath::Pi()*2);
931 if (dummy1.Az()>3*TMath::Pi()/2)
932 dummy1.Az(dummy1.Az() -TMath::Pi()*2);
933
934 if (!CheckRange(dummy1*kRad2Deg))
935 {
936 lout << "Error: Tracking position out of Range." << endl;
937 break;
938 }
939
940 ZdAz dummy = fBending(dummy1);
941 dest = CorrectTarget(GetSePos(), dummy); // [se]
942 */
943
944//*LP* const ZdAz d = dest*360./16384; // [deg]
945 dest *= kGearRatio; // [re]
946
947//*LP* ZdAz min = fBending(fMin/kRad2Deg)*kRad2Deg;
948//*LP* ZdAz max = fBending(fMax/kRad2Deg)*kRad2Deg;
949
950 ZdAz vcalc = sla.GetApproxVel(fRaDec) * kGearRatio2*4./60.; // [re/min]
951
952 //
953 // Request absolute position of rotary encoder from Macs
954 //
955 if (!RequestRePos())
956 break;
957
958 //
959 // distance between (To+dt) and To [re]
960 // position time difference < 5usec
961 // fOffset does the synchronization between the
962 // Shaft- and the rotary encoders
963 //
964 dest -= GetRePos() + fOffset;
965
966 //
967 // Velocity to go [re/min] to reach the right position at time t+dt
968 // correct for the duration of RaDec2AltAz
969 //
970 const ZdAz v = dest*60.0/(dt/*-(fMac2->GetTime()-sla)*/);
971
972 //
973 // calculate real velocity of future [re/min]
974 // believing the Macs manual '/4' shouldn't be necessary, but it is.
975 //
976 ZdAz vt = v/4;
977 LimitSpeed(&vt, vcalc);
978 vt.Round();
979
980 //
981 // check if the drive is fast enough to follow the star
982 //
983 if (vt.Zd()>.9*fMac1->GetVelRes() || vt.Az()>.9*fMac2->GetVelRes())
984 {
985 lout << "Error: Tracking speed faster than 90% of possible maximum velocity." << endl;
986 break;
987 }
988
989 //
990 // Set theoretical velocity (as early after calculation as possible)
991 // Maybe we should attenuate the changes
992 //
993 if (!SetVelocity(vt))
994 break;
995
996 //
997 // Now do 'unnecessary' things
998 //
999 fVelocity = vt/kGearRatio2*4;
1000
1001//--- const double mjd = fMac2->GetMjd();
1002//--- fout << setprecision(15) << setw(17) << mjd*60.*60.*24. << " ";
1003//--- fout << setw(4) << vt.Zd() << " ";
1004//--- fout << setw(4) << vt.Az() << endl;
1005 //
1006 // FIXME? Calculate an accuracy for the tracking system?
1007 // How good do we reach the calculated position in 'real'
1008 // re valus?
1009 //
1010
1011
1012 //
1013 // Update speed as often as possible.
1014 // make sure, that dt is around 10 times larger than the
1015 // update time
1016 //
1017 //
1018 // The loop should not be executed faster than the ramp of
1019 // a change in the velocity can be followed.
1020 // (This is important on fast machines >500MHz)
1021 //
1022 usleep(1000000); // 1s
1023 //usleep(50000); // 0.05s
1024 }
1025
1026 fBackground = kBgdNone;
1027 StopMovement();
1028 lout << "Tracking stopped." << endl;
1029}
1030
1031// --------------------------------------------------------------------------
1032//
1033// Stops the movement of both motors.
1034//
1035// Sets the status to stopping. Sets the deceleration to 50% of the maximum.
1036// stops. Quits the revolution mode and wait for the end of the movement.
1037//
1038void MCosy::StopMovement()
1039{
1040 //
1041 // Set status to Stopping
1042 //
1043 SetStatus(MCosy::kStopping);
1044
1045 //
1046 // set deceleration to 50%
1047 //
1048 cout << "Stopping movement (dec=30%)..." << endl;
1049
1050 fMac1->SetDeceleration(0.3*fMac1->GetVelRes());
1051 fMac2->SetDeceleration(0.3*fMac2->GetVelRes());
1052 fMac1->SetRpmMode(FALSE);
1053 fMac2->SetRpmMode(FALSE);
1054
1055/*
1056 fMac1->SetDeceleration(0.3*fMac1->GetVelRes());
1057 fMac2->SetDeceleration(0.3*fMac2->GetVelRes());
1058
1059 fMac2->SendSDO(0x3000, Macs::string('s','t','o','p'));
1060 fMac1->SendSDO(0x3000, Macs::string('s','t','o','p'));
1061 fMac2->WaitForSdo(0x3000, 0);
1062 fMac1->WaitForSdo(0x3000, 0);
1063 fMac1->SetRpmMode(FALSE);
1064 fMac2->SetRpmMode(FALSE);
1065 */
1066
1067 //
1068 // Wait for the movement to really be finished.
1069 //
1070 cout << "Waiting for end of movement..." << endl;
1071 WaitForEndMovement();
1072
1073 //
1074 // Check whether everything works fine.
1075 //
1076 CheckForError();
1077 cout << "Movement stopped." << endl;
1078}
1079
1080void MCosy::StopTracking()
1081{
1082 //
1083 // Set status to Stopping
1084 //
1085 SetStatus(MCosy::kStopping);
1086
1087 //
1088 // set deceleration to 50%
1089 //
1090 cout << "Stopping tracking (dec=20%)..." << endl;
1091 fMac1->SetDeceleration(0.2*fMac1->GetVelRes());
1092 fMac2->SetDeceleration(0.2*fMac2->GetVelRes());
1093
1094 fMac2->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min]
1095 fMac1->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min]
1096 fMac2->WaitForSdo(0x3006, 1);
1097 fMac1->WaitForSdo(0x3006, 1);
1098
1099 cout << "Waiting for end of movement..." << endl;
1100 WaitForEndMovement();
1101
1102 //
1103 // Wait for the objects to be OKed.
1104 //
1105 fMac1->SetRpmMode(FALSE);
1106 fMac2->SetRpmMode(FALSE);
1107
1108 //
1109 // Wait for the movement to really be finished.
1110 //
1111 //cout << "Waiting for end of movement..." << endl;
1112 //WaitForEndMovement();
1113
1114 //
1115 // Check whether everything works fine.
1116 //
1117 CheckForError();
1118 cout << "Movement stopped." << endl;
1119}
1120
1121bool MCosy::CheckNetwork()
1122{
1123 //return kTRUE;
1124 //CheckConnections();
1125
1126 if (HasZombie())
1127 {
1128 lout << "- Found Zombies in Network..." << endl;
1129 if (!RebootZombies())
1130 return false;
1131 }
1132
1133 /*
1134 FIXME HANDLING ERROR
1135 */
1136 if (HasError())
1137 {
1138 fMac1->HandleError();
1139 fMac2->HandleError();
1140 fMac3->HandleError();
1141 if (HasError() || HasZombie())
1142 return false;
1143 }
1144
1145 return true;
1146}
1147
1148void *MCosy::Proc(int msg, void *mp)
1149{
1150 switch (msg)
1151 {
1152 case WM_WAIT:
1153 cout << "Wait for execution of Proc(WM_*, ): done." << endl;
1154 return NULL;
1155
1156 case WM_STOP:
1157 cout << "MCosy::Proc: Stop." << endl;
1158 if (!CheckNetwork())
1159 return (void*)0xebb0;
1160 StopMovement();
1161 return NULL;
1162/*
1163 case WM_PRESET:
1164 cout << "WM_Preset: start." << endl;
1165 if (!CheckNetwork())
1166 return (void*)0xebb0;
1167 fZd1->SetPreset();
1168 fZd2->SetPreset();
1169 fAz->SetPreset();
1170 cout << "WM_Preset: done. (return 0xaffe)" << endl;
1171 return (void*)0xaffe;
1172*/
1173 /*
1174 case WM_CALIB:
1175 {
1176 cout << "WM_Calib: start." << endl;
1177 if (!CheckNetwork())
1178 return (void*)0xebb0;
1179
1180 SlaStars sla(fObservatory);
1181 sla.Now();
1182
1183 RaDec rd = *((RaDec*)mp);
1184
1185 //RaDec rd(37.94, 89.2644); // POLARIS
1186 //RaDec rd(213.915417, 19.1825); // ARCTURUS
1187
1188 cout << "Calibrating to: " << rd.Ra()*24/360 << "h " << rd.Dec() << "°" << endl;
1189
1190 ZdAz za=sla.CalcZdAz(rd*kDeg2Rad)*16384.0/k2Pi;
1191
1192 cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl;
1193
1194 ZdAz sepos = GetSePos();
1195 cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl;
1196
1197 fZd1->SetPreset(za.Zd());
1198 fZd2->SetPreset(-za.Zd());
1199 fAz->SetPreset(za.Az());
1200
1201 cout << "WM_Calib: done. (return 0xaffe)" << endl;
1202 }
1203 return (void*)0xaffe;
1204 */
1205
1206 case WM_TPOINT:
1207 {
1208 cout << "WM_TPoint: start." << endl;
1209 SlaStars sla(fObservatory);
1210 sla.Now();
1211
1212 RaDec rd = *((RaDec*)mp);
1213 cout << "TPoint Star: " << rd.Ra()/15 << "h " << rd.Dec() << "°" << endl;
1214
1215 AltAz za=sla.CalcAltAz(rd*kDeg2Rad)*kRad2Deg;
1216
1217 cout << " Alt/Az: " << za.Alt() << "° " << za.Az() << "°" << endl;
1218 *tpout << setprecision(7) << za.Az() << " " << za.Alt() << " ";
1219
1220 ZdAz sepos = GetSePos()*TMath::Pi()*2/16384;;
1221 za.Set(TMath::Pi()/2-sepos.Zd(), sepos.Az());
1222 za *= kRad2Deg;
1223
1224 cout << " SE-Pos: " << za.Alt() << "° " << za.Az() << "°" << endl;
1225 *tpout << fmod(za.Az()+360, 360) << " " << za.Alt() << " ";
1226 *tpout << rd.Ra()/15 << " " << rd.Dec() << " " << setprecision(11) << sla.GetMjd() << endl;
1227
1228 cout << "WM_TPoint: done. (return 0xaffe)" << endl;
1229 }
1230 return (void*)0xca1b;
1231
1232 case WM_TRACKPOS:
1233 cout << "WM_TrackPosition: start." << endl;
1234 {
1235 if (!CheckNetwork())
1236 return (void*)0xebb0;
1237
1238 ZdAz dest = *((ZdAz*)mp) * kDeg2Rad;
1239 //if (!SetPosition(dest))
1240 // return (void*)0x1234;
1241
1242 SlaStars sla(fObservatory);
1243 sla.Now();
1244
1245 RaDec rd = sla.CalcRaDec(dest);
1246 cout << dest.Zd()*180/3.1415 << " " << dest.Az()*180/3.1415 << endl;
1247 cout << rd.Ra()*12/3.1415 << " " << rd.Dec()*180/3.1415 << endl;
1248 TrackPosition(rd);
1249 }
1250 cout << "WM_TrackPosition: done. (return 0xabcd)" << endl;
1251 return (void*)0xabcd;
1252
1253 case WM_POSITION:
1254 cout << "WM_Position: start." << endl;
1255 {
1256 if (!CheckNetwork())
1257 return (void*)0xebb0;
1258
1259 ZdAz dest = *((ZdAz*)mp);
1260 SetPosition(dest*kDeg2Rad);
1261 }
1262 cout << "WM_Position: done. (return 0x7777)" << endl;
1263 return (void*)0x7777;
1264
1265 case WM_TESTSE:
1266 cout << "WM_TestSe: start." << endl;
1267 fBackground = mp ? kBgdSeTest : kBgdNone;
1268 cout << "WM_TestSe: done. (return 0x1e51)" << endl;
1269 return (void*)0x1e51;
1270
1271 case WM_GEAR:
1272 cout << "WM_Gear: start." << endl;
1273 fBackground = mp ? kBgdGear : kBgdNone;
1274 cout << "WM_Gear: done. (return 0xfeaf)" << endl;
1275 return (void*)0xfeaf;
1276
1277 case WM_DISPLAY:
1278 cout << "WM_Display: start." << endl;
1279 fTriggerDisplay = kTRUE;
1280 cout << "WM_Disply: done. (return 0xd1e1)" << endl;
1281 return (void*)0xd1e1;
1282
1283 case WM_TRACK:
1284 cout << "WM_Track: START" << endl;
1285 {
1286 if (!CheckNetwork())
1287 return (void*)0xebb0;
1288
1289 RaDec dest = *((RaDec*)mp);
1290 TrackPosition(dest*kDeg2Rad);
1291 }
1292 cout << "WM_Track: done. (return 0x8888)" << endl;
1293 return (void*)0x8888;
1294
1295 case WM_NEWTRACK:
1296 cout << "WM_NewTrack: START" << endl;
1297 fRaDec = *((RaDec*)mp);
1298 cout << "WM_NewTrack: done. (return 0x9999)" << endl;
1299 return (void*)0x9999;
1300
1301 case WM_LOADBENDING:
1302 cout << "WM_LoadBending: START" << endl;
1303 fBending.Load("bending.txt");
1304 cout << "WM_LoadBending: done. (return 0xbe0d)" << endl;
1305 return (void*)0xbe0d;
1306
1307 case WM_RESETBENDING:
1308 cout << "WM_ResetBending: START" << endl;
1309 fBending.Reset();
1310 cout << "WM_ResetBending: done. (return 0xbe0e)" << endl;
1311 return (void*)0xbe0e;
1312
1313 case WM_HOME:
1314 cout << "WM_Home: START" << endl;
1315 if (!CheckNetwork())
1316 return (void*)0xebb0;
1317 else
1318 {
1319 cout << "HOME NOT ALLOWED... for Magic." << endl;
1320 /*
1321 cout << "Going Home..." << endl;
1322 TEnv env(".cosyrc");
1323
1324 SetStatus(MCosy::kMoving);
1325
1326 fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100));
1327 fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100));
1328
1329 lout << "SETHOME DONE" << endl;
1330
1331 SetStatus(HasError() ? MCosy::kError : MCosy::kStopped);
1332
1333 fAz->SetPreset();
1334 fZd1->SetPreset();
1335 fZd2->SetPreset();
1336
1337 fMac1->ReqPos();
1338 fMac2->ReqPos();
1339 fMac3->StopMotor();
1340 */
1341 }
1342 cout << "WM_Home: done. (return 0x403e)" << endl;
1343 return (void*)0x403e;
1344
1345 case WM_CALCALTAZ:
1346 {
1347 cout << endl;
1348
1349 SlaStars sla(fObservatory);
1350 sla.Now();
1351
1352 XY xy = *((XY*)mp);
1353 RaDec rd(xy.X()*15., xy.Y()); // [deg]
1354
1355 const ZdAz a0 = sla.CalcZdAz(rd*kDeg2Rad);
1356
1357 ZdAz a1;
1358 AlignTrackingPos(a0, a1);
1359 a1 *= 180/TMath::Pi();
1360
1361 const ZdAz a2 = a1*16384/360;
1362 const ZdAz se = a0*16384/360;
1363
1364 cout << "Ra/Dec source: " << xy.X() << "h " << xy.Y() << "°" << endl;
1365 cout << "Zd/Az target: " << a0.Zd() << "° " << a0.Az() << "°" << endl;
1366 cout << "Zd/Az bended: " << a1.Zd() << "° " << a1.Az() << "°" << endl;
1367 cout << "SE target: " << se.Zd() << " " << se.Az() << endl;
1368 cout << "SE bended: " << a2.Zd() << " " << a2.Az() << endl;
1369 }
1370 return (void*)0xa17a;
1371
1372 case WM_QUIT:
1373 cout << "WM_Quit: now." << endl;
1374 if (!CheckNetwork())
1375 {
1376 lout << "ERROR: Cannot shutdown CANbus network." << endl;
1377 return (void*)0xebb0;
1378 }
1379 TerminateApp();
1380 cout << "WM_Quit: done." << endl;
1381 return (void*)0xaaaa;
1382 }
1383 cout << "MCosy::Proc: Unknown message 0x" << msg << endl;
1384 return (void*)0xffffffff;
1385}
1386
1387void *MTTalk::Thread()
1388{
1389 fCosy->TalkThread();
1390 return NULL;
1391}
1392
1393void MCosy::ReadConfig()
1394{
1395 cout << "Reading configuration file..." << flush;
1396 TEnv env(".cosyrc");
1397 cout << "done." << endl;
1398
1399 cout << "Reading telescope range..." << flush;
1400 const Double_t amin = env.GetValue("Az_Min[deg]", -90.0);
1401 const Double_t zmin = env.GetValue("Zd_Min[deg]", -74.5);
1402 fMin.Set(zmin, amin);
1403
1404 cout << " Min: " << zmin << "deg " << amin << "deg" << endl;
1405
1406 const Double_t amax = env.GetValue("Az_Max[deg]", 318.0);
1407 const Double_t zmax = env.GetValue("Zd_Max[deg]", 100.5);
1408 fMax.Set(zmax, amax);
1409
1410 cout << " Max: " << zmax << "deg " << amax << "deg" << endl;
1411
1412 cout << "Reading gear ratios..." << flush;
1413 const Double_t gaz = env.GetValue("Az_GearRatio[U_mot/U_tel]", 1000.0);
1414 const Double_t gzd = env.GetValue("Zd_GearRatio[U_mot/U_tel]", 1000.0);
1415
1416 Double_t resreaz = 0;
1417 if (fMac1 && !fMac1->IsZombieNode())
1418 resreaz = fMac1->GetRes();
1419 else
1420 if (fMac3 && !fMac3->IsZombieNode())
1421 resreaz = fMac3->GetRes();
1422 else
1423 resreaz = env.GetValue("Az_ResRE[re/U_mot]", 1500);
1424
1425 Double_t resrezd = 0;
1426 if (fMac2 && !fMac2->IsZombieNode())
1427 resrezd = fMac2->GetRes();
1428 else
1429 resrezd = env.GetValue("Zd_ResRE[re/U_mot]", 1500);
1430
1431 Double_t ressezd = 0;
1432 if (fZd1 && !fZd1->IsZombieNode())
1433 ressezd = fZd1->GetPhysRes();
1434 else
1435 if (fZd2 && !fZd2->IsZombieNode())
1436 ressezd = fZd2->GetPhysRes();
1437 else
1438 ressezd = env.GetValue("Zd_ResSE[se/U_mot]", 16384);
1439
1440 Double_t resseaz = 0;
1441 if (fAz && !fAz->IsZombieNode())
1442 resseaz = fAz->GetPhysRes();
1443 else
1444 resseaz = env.GetValue("Az_ResSE[se/U_mot]", 16384);
1445
1446 kGearRatio.Set (gzd*resrezd*4/ressezd, gaz*resreaz*4/resseaz); //[re/se]
1447 kGearRatio2.Set(gzd*resrezd*4/360.0, gaz*resreaz*4/360.0); //[re/deg]
1448 cout << "done." << endl;
1449
1450 cout << " * Setting Gear Ratios:" << endl;
1451 cout << " --------------------" << endl;
1452 cout << " * X: " << gzd << "*" << resrezd << "/" << ressezd << "=" << kGearRatio.X() << endl;
1453 cout << " * Y: " << gaz << "*" << resreaz << "/" << resseaz << "=" << kGearRatio.Y() << endl;
1454}
1455
1456void MCosy::InitSync()
1457{
1458 if (!fMac3)
1459 {
1460 lout << "Unable to Init Sync! Mac3 not available." << endl;
1461 return;
1462 }
1463
1464 const int res = fMac3->GetVelRes();
1465
1466 fMac3->SetVelocity(0.3*res);
1467 fMac3->SetAcceleration(0.2*res);
1468 fMac3->SetDeceleration(0.2*res);
1469 fMac3->StartPosSync();
1470}
1471
1472void MCosy::TalkThreadTracking()
1473{
1474 if (fZd1->IsZombieNode() && fZd2->IsZombieNode())
1475 return;
1476
1477 if (fAz->IsZombieNode())
1478 return;
1479
1480 if (!fMac1 || !fMac2)
1481 return;
1482
1483 lout << "Tracking Thread started..." << endl;
1484
1485 SlaStars sla(fObservatory);
1486 sla.Now();
1487
1488 ZdAz old;
1489 ZdAz ist = GetSePos(); // [se]
1490
1491// ZdAz istre = -fOffset; // [re]
1492 ZdAz time;
1493
1494 ZdAz sollzd = sla.CalcZdAz(fRaDec); // [rad]
1495 ZdAz sollaz = sollzd; // [rad]
1496
1497 //
1498 // only update fTrackingError while tracking
1499 //
1500 bool phca1=false;
1501 bool phca2=false;
1502 bool phcaz=false;
1503
1504 while (fBackground==kBgdTracking)
1505 {
1506 //
1507 // Make changes (eg wind) smoother - attenuation of control function
1508 //
1509 const float weight = 1.; //0.3;
1510
1511 //
1512 // This is the time constant which defines how fast
1513 // you correct for external influences (like wind)
1514 //
1515 fZd1->ResetPosHasChanged();
1516 fZd2->ResetPosHasChanged();
1517 fAz->ResetPosHasChanged();
1518 do
1519 {
1520 phca1 = fZd1->PosHasChanged();
1521 phca2 = fZd2->PosHasChanged();
1522 phcaz = fAz->PosHasChanged();
1523 usleep(1);
1524 } while (!phca1 && !phca2 && !phcaz && fBackground==kBgdTracking);
1525
1526 //---usleep(100000); // 0.1s
1527
1528 //
1529 // get position, where we are
1530 //
1531 old = ist;
1532 ist = GetSePos(); // [se]
1533
1534 //
1535 // if the position didn't change continue
1536 //
1537 /*---
1538 if ((int)ist.Zd() == (int)old.Zd() &&
1539 (int)ist.Az() == (int)old.Az())
1540 continue;
1541 */
1542 ZdAz istre = GetRePosPdo();
1543
1544 //
1545 // Get time from last shaftencoder position change (position: ist)
1546 // FIXME: I cannot take the avarage
1547 //
1548 // FIXME
1549 //time.Zd(fZd1->GetMjd());
1550 /* OLD* */
1551 if (fZd1->GetMjd()>fZd2->GetMjd())
1552 time.Zd(fZd1->GetMjd());
1553 else
1554 time.Zd(fZd2->GetMjd());
1555
1556 //time.Zd((fZd1->GetMjd()+fZd2->GetMjd())/2.0);
1557 time.Az(fAz->GetMjd());
1558
1559 //
1560 // if Shaftencoder changed position
1561 // calculate were we should be
1562 //
1563 if (phca1 || phca2 /*(int)ist.Zd() != (int)old.Zd()*/)
1564 {
1565 sollzd = sla.CalcZdAz(fRaDec, time.Zd()); // [rad]
1566 /*
1567 ZdAz dummy = fBending(sla.CalcZdAz(fRaDec));
1568 sollzd = CorrectTarget(ist, dummy); // [se]
1569 */
1570 fOffset.Zd(fOffset.Zd()*(1.-weight)+(ist.Zd()*kGearRatio.X()-istre.Zd())*weight);
1571 }
1572
1573 if (phcaz /*(int)ist.Az() != (int)old.Az()*/)
1574 {
1575 sollaz = sla.CalcZdAz(fRaDec, time.Az()); // [rad]
1576 /*
1577 ZdAz dummy = fBending(sla.CalcZdAz(fRaDec));
1578 sollaz = CorrectTarget(ist, dummy); // [se]
1579 */
1580 fOffset.Az(fOffset.Az()*(1.-weight)+(ist.Az()*kGearRatio.Y()-istre.Az())*weight);
1581 }
1582
1583 ZdAz soll(sollzd.Zd(), sollaz.Az()); // [rad]
1584
1585 AlignTrackingPos(soll*360/16384, fZdAzSoll);
1586 /*
1587 fZdAzSoll = fBending.CorrectBack(soll*2*TMath::Pi()/16384);
1588
1589 // FIXME?
1590 if (fZdAzSoll.Az()<-TMath::Pi()/2)
1591 fZdAzSoll.Az(fZdAzSoll.Az() + TMath::Pi()*2);
1592 if (fZdAzSoll.Az()>3*TMath::Pi()/2)
1593 fZdAzSoll.Az(fZdAzSoll.Az() -TMath::Pi()*2);
1594
1595 // FIXME?
1596 while (ist.Az()>3*16384/4/2)
1597 ist.Az(ist.Az() - 16384);
1598 while (soll.Az()>3*16384/4/2)
1599 soll.Az(soll.Az() - 16384);
1600 while (ist.Az()<-16384/4)
1601 ist.Az(ist.Az() + 16384);
1602 while (soll.Az()<-16384/4)
1603 soll.Az(soll.Az() + 16384);
1604 */
1605 ist *= TMath::Pi()*2/16384;
1606 fTrackingError.Set(ist.Zd()-fZdAzSoll.Zd(), ist.Az()-fZdAzSoll.Az());
1607
1608 //--- fout << setprecision(15) << setw(17) << time.Zd()*60.*60.*24. << " ";
1609 //--- fout << setprecision(5) << setw(7) << fTrackingError.Zd() << " ";
1610 //--- fout << setprecision(15) << setw(17) << time.Az()*60.*60.*24. << " ";
1611 //--- fout << setprecision(5) << setw(7) << fTrackingError.Az() << endl;
1612 }
1613
1614 lout << "Tracking Thread done." << endl;
1615
1616 //--- fout << endl << endl;
1617}
1618
1619void MCosy::TalkThreadSeTest()
1620{
1621// if (fZd1->IsZombieNode() || fZd2->IsZombieNode())
1622 // return;
1623
1624 if (fHist)
1625 {
1626 lout << "You are much too fast... try again." << endl;
1627 return;
1628 }
1629
1630 fHist = new TH2F("Diff", "Difference of SE values",
1631 201, fMin.Zd(), fMax.Zd(), 41, -10.5, 10.5);
1632 fHist->SetXTitle("ZA [\\circ]");
1633 fHist->SetYTitle("\\Delta SE");
1634
1635 Double_t offset = 0;
1636
1637 int cnt = 0;
1638
1639 lout << "Starting Shaftencoder Test..." << endl;
1640
1641 while (fBackground==kBgdSeTest)
1642 {
1643 fZd1->ResetPosHasChanged();
1644 fZd2->ResetPosHasChanged();
1645
1646 while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() &&
1647 fBackground==kBgdSeTest)
1648 usleep(1);
1649
1650 const Double_t pos[3] = {
1651 (fZd1->GetPos()+8192)%16384,
1652 (fZd2->GetPos()+8192)%16384,
1653 fAz->GetPos() };
1654
1655 //
1656 // Estimate Offset from the first ten positions
1657 //
1658 if (cnt++<10)
1659 {
1660 offset += pos[0]+pos[1];
1661 continue;
1662 }
1663 if (cnt==11)
1664 {
1665 offset /= 10;
1666 cnt++;
1667 }
1668
1669 Double_t apos = (pos[0]-pos[1])/2 * TMath::Pi()*2 / 16384;
1670
1671 ZdAz bend = fBending.CorrectBack(ZdAz(apos, pos[2]))*kRad2Deg;
1672 fHist->Fill(bend.Zd(), pos[0]+pos[1]-offset);
1673 }
1674
1675 lout << "Shaftencoder Test Stopped... displaying Histogram." << endl;
1676
1677 fBackground=kBgdSeTestDispl;
1678}
1679
1680void MCosy::TalkThreadGear()
1681{
1682// if (fZd1->IsZombieNode() || fZd2->IsZombieNode())
1683 // return;
1684
1685 if (fHist)
1686 {
1687 lout << "You are much too fast... try again." << endl;
1688 return;
1689 }
1690
1691 fHist = new TH3F("Gear", "Gear Ratio Re/Se",
1692 (int)((fMax.Zd()-fMin.Zd())/2.5+1), fMin.Zd(), fMax.Zd(),
1693 (int)((fMax.Az()-fMin.Az())/2.5+1), fMin.Az(), fMax.Az(),
1694 61, 349.5, 500.5);
1695
1696 fHist->SetXTitle("Zd [\\circ]");
1697 fHist->SetYTitle("Az [\\circ]");
1698 fHist->SetZTitle("Re/Se");
1699
1700 lout << "Starting Gear determination..." << endl;
1701
1702 ZdAz se0 = GetSePos();
1703 ZdAz re0 = GetRePosPdo();
1704
1705 while (fBackground==kBgdGear)
1706 {
1707 fZd1->ResetPosHasChanged();
1708 fZd2->ResetPosHasChanged();
1709 fAz->ResetPosHasChanged();
1710
1711 while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() &&
1712 !fAz->PosHasChanged() && fBackground==kBgdGear)
1713 usleep(1);
1714
1715 ZdAz se = GetSePos();
1716 ZdAz re = GetRePosPdo();
1717
1718 ZdAz dse = se-se0;
1719 ZdAz dre = re-re0;
1720
1721 if (fabs(dse.Zd())*144>16384) // Each 2.5deg (144)
1722 {
1723 se0.Zd(se.Zd());
1724 re0.Zd(re.Zd());
1725
1726 ZdAz bend = fBending.CorrectBack(se*2*TMath::Pi()/16384)*kRad2Deg;
1727 ((TH3*)fHist)->Fill(bend.Zd(), bend.Az(), dre.Zd()/dse.Zd());
1728 }
1729
1730 if (fabs(dse.Az())*144>16384) // Each 2.5deg (144)
1731 {
1732 se0.Az(se.Az());
1733 re0.Az(re.Az());
1734
1735 ZdAz bend = fBending.CorrectBack(se*2*TMath::Pi()/16384)*kRad2Deg;
1736 ((TH3*)fHist)->Fill(bend.Az(), bend.Az(), dre.Az()/dse.Az());
1737 }
1738 }
1739 lout << "Gear Test Stopped... displaying Histogram." << endl;
1740
1741 fBackground=kBgdGearDispl;
1742}
1743
1744void MCosy::TalkThread()
1745{
1746 /* ========== FIXME? =============
1747 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
1748 return;
1749 */
1750
1751 if (fMac1 && fMac2)
1752 {
1753 fMac1->ReqPos();
1754 fMac2->ReqPos();
1755 }
1756
1757 InitSync();
1758
1759 /*** FOR DEMO MODE ***/
1760 if (!fZd1 || !fZd2 || !fAz)
1761 return;
1762 /*** FOR DEMO MODE ***/
1763
1764 //
1765 // Start the Network
1766 //
1767 while (1)
1768 {
1769 //
1770 // wait until a tracking session is started
1771 //
1772 while (fBackground==kBgdNone)
1773 usleep(1);
1774
1775 switch (fBackground)
1776 {
1777 case kBgdNone:
1778 continue;
1779
1780 case kBgdTracking:
1781 TalkThreadTracking();
1782 continue;
1783
1784 case kBgdSeTest:
1785 TalkThreadSeTest();
1786 continue;
1787
1788 case kBgdGear:
1789 TalkThreadGear();
1790 continue;
1791
1792 default:
1793 continue;
1794 }
1795 }
1796}
1797
1798Bool_t MCosy::HandleTimer(TTimer *t)
1799{
1800 //
1801 // Update Gui, foremer MTGui.
1802 //
1803 if (fZd1)
1804 fZd1->DisplayVal();
1805 if (fZd2)
1806 fZd2->DisplayVal();
1807 if (fAz)
1808 fAz->DisplayVal();
1809
1810 ZdAz seist = GetSePos()*2*TMath::Pi()/16384; // [se]
1811 ZdAz bendist = fBending.CorrectBack(seist);
1812
1813 Byte_t avail = 0;
1814
1815 avail |= (fMac1 && !fMac1->IsZombieNode()) ? 0x01 : 0;
1816 avail |= (fMac2 && !fMac2->IsZombieNode()) ? 0x02 : 0;
1817 avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0;
1818 avail |= (fZd1 && !fZd1->IsZombieNode()) ? 0x08 : 0;
1819 avail |= (fZd2 && !fZd2->IsZombieNode()) ? 0x10 : 0;
1820 avail |= (fAz && !fAz->IsZombieNode()) ? 0x20 : 0;
1821
1822 if (HasError())
1823 SetStatus(MCosy::kError);
1824
1825 lout.UpdateGui();
1826
1827 fWin->Update(bendist*(360.0/2/TMath::Pi()), fTrackingError,
1828 fVelocity, fOffset, fRaDec, fZdAzSoll, fStatus, avail);
1829
1830 const Bool_t trigger = fTriggerDisplay;
1831 fTriggerDisplay = kFALSE;
1832
1833 if (fBackground==kBgdSeTestDispl || (trigger&&fBackground==kBgdSeTest))
1834 DisplayHistTestSe(!trigger);
1835
1836 if (fBackground==kBgdGearDispl || (trigger&&fBackground==kBgdGear))
1837 DisplayHistGear(!trigger);
1838
1839 return kTRUE;
1840}
1841
1842void MCosy::DisplayHistTestSe(Bool_t del)
1843{
1844 lout << "Displaying histogram..." << endl;
1845
1846 TH2F &hist = *(TH2F*)fHist;
1847
1848 if (del)
1849 {
1850 fHist = NULL;
1851 fBackground = kBgdNone;
1852 }
1853
1854 TCanvas *c=new TCanvas("c1", "", 1000, 1000);
1855 c->Divide(1,2);
1856
1857 c->cd(1);
1858 TH2 *h=(TH2*)hist.DrawCopy();
1859
1860 TProfile *p = h->ProfileX("_pfx", -1, 9999, "s");
1861 p->SetLineColor(kBlue);
1862 p->Draw("same");
1863 p->SetBit(kCanDelete);
1864
1865 c->cd(2);
1866
1867 TH1F p2("spread", "Spread of the differences", hist.GetNbinsX(), hist.GetBinLowEdge(1),
1868 hist.GetBinLowEdge(hist.GetNbinsX()+1));
1869 p2.SetXTitle("Zd [\\circ]");
1870 for (int i=0; i<hist.GetNbinsX(); i++)
1871 p2.SetBinError(i, p->GetBinError(i));
1872 p2.SetLineColor(kRed);
1873 p2.SetStats(0);
1874 p2.DrawCopy();
1875
1876 if (del)
1877 delete &hist;
1878}
1879
1880void MCosy::DisplayHistGear(Bool_t del)
1881{
1882 lout << "Displaying histogram..." << endl;
1883
1884 TH3F &hist = *(TH3F*)fHist;
1885
1886 if (del)
1887 {
1888 fHist = NULL;
1889 fBackground = kBgdNone;
1890 }
1891
1892 TCanvas *c=new TCanvas("c1", "", 1000, 1000);
1893 c->Divide(2,2);
1894
1895 // ----------
1896
1897 c->cd(1);
1898 TH2D &h1=*(TH2D*)hist.Project3D("zx"); // Zd
1899 h1.SetTitle(" Gear Ratio Zenith Distance [re/se] ");
1900 h1.SetXTitle("Zd [\\circ]");
1901 h1.Draw();
1902 h1.SetBit(kCanDelete);
1903
1904 TProfile *p1 = h1.ProfileX("_pfx", -1, 9999, "s");
1905 p1->SetLineColor(kBlue);
1906 p1->Draw("same");
1907 p1->SetBit(kCanDelete);
1908
1909 // ----------
1910
1911 c->cd(2);
1912 TH2D &h2=*(TH2D*)hist.Project3D("zy"); // Az
1913 h2.SetTitle(" Gear Ratio Azimuth [re/se] ");
1914 h2.SetXTitle("Zd [\\circ]");
1915 h2.Draw();
1916 h2.SetBit(kCanDelete);
1917
1918 TProfile *p2 = h2.ProfileX("_pfx", -1, 9999, "s");
1919 p2->SetLineColor(kBlue);
1920 p2->Draw("same");
1921 p2->SetBit(kCanDelete);
1922
1923 // ----------
1924
1925 c->cd(3);
1926
1927 TAxis &axe1 = *h1.GetXaxis();
1928
1929 TH1F f1("spreadzd", " Spread Zenith Distance ",
1930 axe1.GetNbins(), axe1.GetXmin(), axe1.GetXmax());
1931 f1.SetXTitle("Zd [\\circ]");
1932 for (int i=0; i<axe1.GetNbins(); i++)
1933 f1.SetBinError(i, p1->GetBinError(i));
1934 f1.SetLineColor(kRed);
1935 f1.SetStats(0);
1936 f1.DrawCopy();
1937
1938 c->cd(4);
1939
1940 // ----------
1941
1942 TAxis &axe2 = *h2.GetXaxis();
1943
1944 TH1F f2("spreadaz", " Spread Azimuth ",
1945 axe2.GetNbins(), axe2.GetXmin(), axe2.GetXmax());
1946 f2.SetXTitle("Az [\\circ]");
1947 for (int i=0; i<axe2.GetNbins(); i++)
1948 f2.SetBinError(i, p2->GetBinError(i));
1949 f2.SetLineColor(kRed);
1950 f2.SetStats(0);
1951 f2.DrawCopy();
1952
1953 // ----------
1954
1955 if (del)
1956 delete &hist;
1957}
1958
1959// --------------------------------------------------------------------------
1960//
1961// Start the work of the application:
1962//
1963// Start the Can-Network.
1964// Start the MCosy::TalkThread thread.
1965// turn on the gui update
1966//
1967void MCosy::Start()
1968{
1969 // Don't call this function twice!
1970 Network::Start();
1971
1972 ReadConfig();
1973
1974 lout << "- Starting TX Thread." << endl;
1975 fTTalk = new MTTalk(this);
1976
1977 lout << "- Starting GUI update." << endl;
1978 fUpdateGui->TurnOn();
1979}
1980
1981// --------------------------------------------------------------------------
1982//
1983// Start the work of the application:
1984//
1985// Turn of the gui update
1986// stop the MCosy::TalkThread thread.
1987// Stop the network
1988//
1989void MCosy::Stop()
1990{
1991 lout << "- Stopping GUI update." << endl;
1992 fUpdateGui->TurnOff();
1993 lout << "- GUI Update stopped." << endl;
1994
1995 delete fTTalk;
1996 lout << "- TX Thread stopped." << endl;
1997
1998 Network::Stop();
1999}
2000
2001// --------------------------------------------------------------------------
2002//
2003// Disable the synchronization by using a negative CAN Id for id2.
2004//
2005void MCosy::Constructor(Int_t id1, Int_t id2, Int_t id3,
2006 Int_t id4, Int_t id5, Int_t id6)
2007{
2008 //
2009 // Create Nodes
2010 //
2011 lout << "- Setting up network." << endl;
2012
2013 fMac1=new Macs(id1, "Mac/Az", lout);
2014 fMac2=new Macs(id3, "Mac/Zd", lout);
2015 if (id2>=0)
2016 fMac3=new Macs(id2, "Mac/Az-Sync", lout);
2017
2018 fZd1=new ShaftEncoder(id4, "SE/Zd1", lout);
2019 fZd2=new ShaftEncoder(id5, "SE/Zd2", lout);
2020 fAz =new ShaftEncoder(id6, "SE/Az", lout);
2021
2022 lout << "- Connecting devices to network." << endl;
2023
2024 //
2025 // Connect the devices to the network
2026 //
2027 SetNode(fMac1);
2028 SetNode(fMac2);
2029 if (id2>=0)
2030 SetNode(fMac3);
2031 SetNode(fZd1);
2032 SetNode(fZd2);
2033 SetNode(fAz);
2034
2035 //
2036 // Create Gui Event timer and Gui
2037 //
2038 lout << "- Initializing GUI Timer." << endl;
2039 fUpdateGui = new TTimer(this, 100); // 100ms
2040
2041 lout << "- Starting GUI." << endl;
2042 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
2043}
2044
2045void MCosy::ConstructorSE(Int_t id4, Int_t id5, Int_t id6)
2046{
2047 //
2048 // Create Nodes
2049 //
2050 lout << "- Setting up network." << endl;
2051
2052 fZd1=new ShaftEncoder(id4, "SE/Zd1", lout);
2053 fZd2=new ShaftEncoder(id5, "SE/Zd2", lout);
2054 fAz =new ShaftEncoder(id6, "SE/Az", lout);
2055
2056 lout << "- Connecting devices to network." << endl;
2057
2058 //
2059 // Connect the devices to the network
2060 //
2061 SetNode(fZd1);
2062 SetNode(fZd2);
2063 SetNode(fAz);
2064
2065 //
2066 // Create Gui Event timer and Gui
2067 //
2068 lout << "- Initializing GUI Timer." << endl;
2069 fUpdateGui = new TTimer(this, 100); // 100ms
2070
2071 lout << "- Starting GUI." << endl;
2072 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
2073}
2074
2075void MCosy::ConstructorDemo()
2076{
2077 //
2078 // Create Nodes
2079 //
2080 lout << "- Setting up network." << endl;
2081
2082 //
2083 // Create Gui Event timer and Gui
2084 //
2085 lout << "- Initializing GUI Timer." << endl;
2086 fUpdateGui = new TTimer(this, 100); // 100ms
2087
2088 lout << "- Starting GUI." << endl;
2089 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
2090}
2091
2092MCosy::MCosy(int mode, const char *dev, const int baud, MLog &out)
2093: Network(dev, baud, out), fObservatory(MObservatory::kMagic1), fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), fMac3(0), fBackground(kBgdNone)
2094{
2095 TEnv env(".cosyrc");
2096 const Int_t id1 = env.GetValue("Az_Id-MAC1", 1); //1
2097 const Int_t id2 = env.GetValue("Az_Id-MAC2", 2); //2
2098 const Int_t id3 = env.GetValue("Zd_Id-MAC", 3); //3
2099 const Int_t id4 = env.GetValue("Zd_Id-SE1", 4); //4
2100 const Int_t id5 = env.GetValue("Zd_Id-SE2", 5); //5
2101 const Int_t id6 = env.GetValue("Az_Id-SE", 6); //6
2102
2103 lout << "- Program in ";
2104 switch (mode)
2105 {
2106 case 0:
2107 lout << "<<Stanard mode>>" << endl;
2108 fBending.Load("bending.txt");
2109 Constructor(id1, id2, id3, id4, id5, id6);
2110 break;
2111 case 1:
2112 lout << "<<SE mode>>" << endl;
2113 fBending.Load("bending.txt");
2114 ConstructorSE(id4, id5, id6);
2115 break;
2116 default:
2117 lout << "<<Demo mode>>" << endl;
2118 ConstructorDemo();
2119 }
2120
2121 lout.SetOutputGui(fWin->GetLog(), kTRUE);
2122
2123 fZd1->SetDisplay(fWin->GetLabel2());
2124 fZd2->SetDisplay(fWin->GetLabel3());
2125 fAz->SetDisplay(fWin->GetLabel1());
2126
2127 int i=0;
2128 char name[100];
2129 while (1)
2130 {
2131 sprintf(name, "tpoint/tpoint%03d.txt", i++);
2132 if (gSystem->AccessPathName(name, kFileExists))
2133 break;
2134 }
2135
2136 Timer time;
2137 time.Now();
2138
2139 cout << "TPoint File ********* " << name << " ********** " << endl;
2140
2141 tpout = new ofstream(name);
2142 *tpout << "Magic Model TPOINT data file" << endl;
2143 *tpout << ": ALTAZ" << endl;
2144 *tpout << "49 48 0 ";
2145 *tpout << time.Year() << " " << time.Month() << " " << time.Day() << " ";
2146 *tpout << /*"20 1013.25 300 0.5 0.55 0.0065" <<*/ endl;
2147 // temp(°C) pressure(mB) height(m) humidity(1) wavelength(microm) troplapserate(K/m)
2148}
2149
2150void MCosy::TerminateApp()
2151{
2152 cout << "MCosy::TerminateApp()" << endl;
2153/*
2154 Int_t rc;
2155 TGMessageBox msg(this, gClient->GetRoot(),
2156 "Information",
2157 "Cosy is shutting down the system - this may take wa while!",
2158 kMBIconExclamation,
2159 kMBOK, //kMBClose
2160 &rc, 0);
2161*/
2162
2163 lout.DisableOutputDevice(MLog::eGui);
2164 // FIXME: WHY DOES THIS CRASH THE APPLICATIOn WHILE TRAKING?
2165 // lout.SetOutputGui(NULL, kFALSE);
2166
2167 gApplication->Terminate(0);
2168}
2169
2170MCosy::~MCosy()
2171{
2172 *tpout << "END" << endl;
2173 delete tpout;
2174
2175 cout << "Deleting GUI timer." << endl;
2176
2177 delete fUpdateGui;
2178
2179 cout << "Deleting Nodes." << endl;
2180
2181 delete fAz;
2182 delete fZd1;
2183 delete fZd2;
2184 delete fMac1;
2185 delete fMac2;
2186 if (fMac3)
2187 delete fMac3;
2188
2189 cout << "Deleting MGCosy." << endl;
2190
2191 lout.DisableOutputDevice(MLog::eGui);
2192
2193 delete fWin;
2194
2195 cout << "MGCosy destructed." << endl;
2196}
Note: See TracBrowser for help on using the repository browser.