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

Last change on this file since 1722 was 1703, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 40.8 KB
Line 
1#include "MCosy.h"
2
3#include <iomanip.h>
4#include <fstream.h>
5#include <iostream.h>
6
7#include <TROOT.h>
8#include <TEnv.h>
9#include <TSystem.h>
10#include <TApplication.h>
11#include <TTimer.h>
12
13#include "MGCosy.h"
14#include "SlaStars.h"
15
16#include "slalib/slalib.h" // FIXME: REMOVE
17
18#include "macs.h"
19#include "base/timer.h"
20#include "shaftencoder.h"
21
22//#include <sys/resource.h> // PRIO_PROCESS
23
24ClassImp(MCosy);
25
26typedef struct tm tm_t;
27
28/*
29#define GEAR_RATIO_ALT 2475.6 // [U_mot/U_tel(360deg)]
30#define GEAR_RATIO_AZ 5891.7 // [U_mot/U_tel(360deg)]
31
32#define RES_RE 500 // [re/U_mot]
33#define RES_SE 16384 // [se/U_tel(360deg)]
34*/
35/*
36 #define GEAR_RATIO_ALT (75.55*16384/1500) // 75.25 VERY IMPORTANT! unit=U_mot/U_tel
37 #define GEAR_RATIO_AZ (179.8*16384/1500) // VERY IMPORTANT! unit=U_mot/U_tel
38*/
39
40//const XY kGearRatio (GEAR_RATIO_ALT*RES_RE/RES_SE, GEAR_RATIO_AZ*RES_RE/RES_SE); //[re/se]
41//const XY kGearRatio2(GEAR_RATIO_ALT*RES_RE/360.0, GEAR_RATIO_AZ*RES_RE/360.0); //[re/deg]
42
43/* +===================================+
44 FIXME: What if fMac3 (Sync) died?
45 +===================================+
46*/
47
48double MCosy::Rad2SE(double rad) const
49{
50 return 16384.0/k2Pi*rad;
51}
52
53double MCosy::Rad2ZdRE(double rad) const
54{
55 return 16384.0/k2Pi*rad*kGearRatio.X();
56}
57
58double MCosy::Rad2AzRE(double rad) const
59{
60 return 16384.0/k2Pi*rad*kGearRatio.Y();
61}
62
63double MCosy::Deg2ZdRE(double rad) const
64{
65 return rad*kGearRatio2.X();
66}
67
68double MCosy::Deg2AzRE(double rad) const
69{
70 return rad*kGearRatio2.Y();
71}
72
73ZdAz MCosy::CorrectTarget(const ZdAz &src, const ZdAz &dst)
74{
75 // CorrectTarget [se]
76
77 // src [se]
78 // dst [rad]
79
80 // fAltMax = 70
81 // fAltMin = -105/110
82 // fAzMin = -355
83 // fAzMax = 355
84
85 ZdAz source = src * 360.0/16384.0;
86 ZdAz dest = dst * kRad2Deg;
87
88 if (dest.Zd()>-3 && dest.Zd()<3)
89 dest.Zd(dest.Zd()<0?-3:3);
90
91 if (dest.Zd()>-1e-6 && dest.Zd()<1e-6)
92 return dst*(16384.0/k2Pi);
93
94 const float fZdMin = -67;
95 const float fZdMax = 67;
96 const float fAzMin = -29;
97 const float fAzMax = 423;
98
99 //
100 // This corrects to target for the shortest distance, not for the fastest move!
101 //
102 ZdAz s = source-dest;
103
104 float min = s.Sqr();
105
106 //
107 // Is it enought to search inside one revolution?
108 //
109 ZdAz ret = dest;
110
111 for (int i=-5; i<5+1; i++)
112 {
113 const ZdAz p(i%2 ? -dest.Zd() : dest.Zd(), dest.Az() - i*180);
114
115 //
116 // Range Check
117 //
118 if (p.Zd()<fZdMin || p.Zd()>fZdMax)
119 continue;
120
121 if (p.Az()<fAzMin || p.Az()>fAzMax)
122 continue;
123
124 //
125 // Calculate distance
126 //
127 s = source-p;
128
129 const float dist = s.Sqr();
130
131 if (dist > min)
132 continue;
133
134 //
135 // New shortest distance
136 //
137 ret = p;
138 min = dist;
139 }
140 return ret*(16384.0/360.0);
141}
142
143// --------------------------------------------------------------------------
144//
145// GetSePos, reads the Shaftencoder positions from the Can-drivers
146// for the shaftencoders. The two shaft encoders at the elevation axis
147// are avaraged. The values are returned as a ZdAz object.
148//
149// The positions are alway up-to-date because the shaftencoders are
150// sending all changes immediatly.
151//
152ZdAz MCosy::GetSePos()
153{
154 //
155 // Get the values
156 //
157 const int p0 = fZd1->GetPos();
158 const int p1 = fZd2->GetPos();
159 const int p2 = fAz->GetPos();
160
161 //
162 // interpolate shaft encoder positions
163 //
164 const float p = (float)(p0-p1)/2;
165
166 //
167 // calculate 'regelabweichung'
168 //
169 return ZdAz(p, p2);
170}
171
172// --------------------------------------------------------------------------
173//
174// request the current positions from the rotary encoders.
175// use GetRePos to get the psotions. If the request fails the function
176// returns kFALSE, otherwise kTRUE
177//
178Bool_t MCosy::RequestRePos()
179{
180 //
181 // Send request
182 //
183 fMac2->RequestSDO(0x6004);
184 fMac1->RequestSDO(0x6004);
185
186 //
187 // Wait until the objects are received.
188 //
189 // FIXME, what when waiting times out (Zombie)
190 WaitForSdos();
191
192 //
193 // If waiting was not interrupted everything is ok. return.
194 //
195 if (!StopWaitingForSDO() && !HasZombie())
196 return kTRUE;
197
198 //
199 // If the waiting was interrupted due to a network error,
200 // print some logging message.
201 //
202 if (HasError())
203 lout << "Error while requesting re pos from Macs (SDO #6004)" << endl;
204
205 return kFALSE;
206}
207
208// --------------------------------------------------------------------------
209//
210// reads the Rotary encoder positions from the last request of the Macs.
211//
212// The positions are returned as a ZdAz object. Use RequestRePos to request
213// the current positions first.
214//
215ZdAz MCosy::GetRePos()
216{
217 return ZdAz(fMac2->GetPos(), fMac1->GetPos());
218}
219
220// --------------------------------------------------------------------------
221//
222// reads the Rotary encoder positions from the Macs.
223//
224// The positions are returned as a ZdAz object. The positions are the ones
225// which are send as PDOs to the computer. This is done at a given
226// frequency. Which means, that this positions are not ought to be
227// up-to-date.
228//
229ZdAz MCosy::GetRePosPdo()
230{
231 return ZdAz(fMac2->GetPdoPos(), fMac1->GetPdoPos());
232}
233
234// --------------------------------------------------------------------------
235//
236// set the velocity and accelerations for position maneuvers.
237//
238// The acceleratin is set as given (in percent of maximum).
239// The velocity is given in percent, depending on the ratio (<1 or >1)
240// one of the axis becomes a slower velocity. This is used for maneuvers
241// in which both axis are moved synchromously and should reach their
242// target position at the same time.
243//
244void MCosy::SetPosVelocity(const Float_t ratio, Float_t vel, Float_t acc)
245{
246 //
247 // Set velocities
248 //
249 const int vr = fMac1->GetVelRes();
250
251 vel *= vr;
252 acc *= vr;
253
254 if (ratio <1)
255 {
256 fMac1->SetVelocity(vel);
257 fMac1->SetAcceleration(acc);
258 fMac1->SetDeceleration(acc);
259
260 fMac2->SetVelocity(vel*ratio);
261 fMac2->SetAcceleration(acc*ratio);
262 fMac2->SetDeceleration(acc*ratio);
263 }
264 else
265 {
266 fMac1->SetVelocity(vel/ratio);
267 fMac1->SetAcceleration(acc/ratio);
268 fMac1->SetDeceleration(acc/ratio);
269
270 fMac2->SetVelocity(vel);
271 fMac2->SetAcceleration(acc);
272 fMac2->SetDeceleration(acc);
273 }
274}
275
276// --------------------------------------------------------------------------
277//
278// Does a relative positioning.
279//
280// The steps to move are given in a ZdAz object relative to the current
281// position. The coordinates are given in Roteryencoder steps.
282// Axis 1 is moved only if axe1==kTRUE, Axis 2 is moved only
283// if Axis 2==kTRUE. The function waits for the movement to be finished.
284//
285void MCosy::DoRelPos(const ZdAz &rd, const Bool_t axe1, const Bool_t axe2)
286{
287 SetStatus(MCosy::kMoving);
288
289 if (axe1) fMac2->StartRelPos(rd.Zd());
290 if (axe2) fMac1->StartRelPos(rd.Az());
291
292 cout << "Waiting for positioning..." << flush;
293
294 WaitForEndMovement();
295
296 cout << "done." << endl;
297}
298
299// --------------------------------------------------------------------------
300//
301// check for a break-signal (from the msgqueue) and errors.
302//
303int MCosy::StopWaitingForSDO() const
304{
305 return Break() || HasError();
306}
307
308// --------------------------------------------------------------------------
309//
310// Waits for a movement to become finished.
311//
312// First waits for all peding Sdos, then waits until both motors are stopped
313// or waiting for SDOs was stopped (either by an error or by Break)
314//
315void MCosy::WaitForEndMovement()
316{
317 // FIXME, what when waiting times out (Zombie)
318 WaitForSdos();
319
320 while ((fMac1->IsPositioning() || fMac2->IsPositioning()) && !StopWaitingForSDO() && !HasZombie())
321 usleep(1);
322}
323
324// --------------------------------------------------------------------------
325//
326// Check for an error...
327//
328// This is ment for usage after the Action: All Motors Stop.
329//
330void MCosy::CheckForError()
331{
332 //
333 // Check all Can-Nodes for an Error. If there is no error the motor
334 // status is set to stopped.
335 //
336 if (!HasError())
337 {
338 SetStatus(MCosy::kStopped);
339 return;
340 }
341
342 //
343 // If there is an error, the error status is set to Error.
344 //
345 SetStatus(MCosy::kError);
346
347 //
348 // Now try to handle the error.
349 //
350 fMac1->HandleError();
351 fMac2->HandleError();
352
353 //
354 // If the error couldn't get solved return
355 //
356 if (HasError())
357 return;
358
359 //
360 // Set motor status to stopped
361 //
362 SetStatus(MCosy::kStopped);
363}
364
365// --------------------------------------------------------------------------
366//
367// Move the telescope to the given position. The position must be given in
368// a ZdAz object in rad.
369//
370// The first positioning is done absolutely. If we didn't reach the
371// correct psotion we try to correct for this by 10 relative position
372// maneuvers. If this doesn't help positioning failed.
373//
374// As a reference the shaftencoder values are used.
375//
376int MCosy::SetPosition(const ZdAz &dst) // [rad]
377{
378 // FIXME: Correct by fOffset ?
379
380 /*
381 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
382 {
383 cout << "SetPosition: No connection to at least one of the MACS!" << endl;
384 return TRUE;
385 }
386 */
387
388 //
389 // Make sure that the motors are in sync mode (necessary if the
390 // MACS has been rebooted from a Zombie state.
391 //
392 InitSync();
393 if (fMac3->IsZombieNode())
394 return false;
395
396 //
397 // Calculate new target position (shortest distance to go)
398 //
399 const ZdAz src = GetSePos();
400
401 //
402 // Because we agreed on I don't search for the shortest move
403 // anymore
404 //
405 // const ZdAz dest = CorrectTarget(src, dst);
406 //
407 fZdAzSoll = fBending(dst);
408 const ZdAz dest = fZdAzSoll*16384/2/TMath::Pi();
409
410 lout << "Positioning to Target..." << endl;
411 cout << "Source Zd: " << src.Zd() << "se Az:" << src.Az() << "se" << endl;
412 cout << "Destination Zd: " << Rad2SE(dst.Zd()) << "se Az:" << Rad2SE(dst.Az()) << "se" << endl;
413 cout << "Bend'd Dest Zd: " << Rad2SE(fZdAzSoll.Zd()) << "se Az:" << Rad2SE(fZdAzSoll.Az()) << "se" << endl;
414 cout << "Shortest Dest Zd: " << dest.Zd() << "se Az:" << dest.Az() << "se" << endl;
415
416 for (int i=0; i<10 && !StopWaitingForSDO() && !HasZombie(); i++)
417 {
418 //
419 // Get Shaft Encoder Positions
420 //
421 const ZdAz p=GetSePos();
422
423 //
424 // calculate control deviation and rounded cd
425 //
426 ZdAz rd = dest-p; // [se]
427
428 ZdAz cd = rd; // [se]
429 cd.Round();
430
431 //
432 // Check if there is a control deviation on the axis
433 //
434 const Bool_t cdzd = (int)cd.Zd() ? kTRUE : kFALSE;
435 const Bool_t cdaz = (int)cd.Az() ? kTRUE : kFALSE;
436
437 //
438 // check if we reached the correct position already
439 //
440 if (!cdzd && !cdaz)
441 {
442 lout << "Positioning done in " << i << (i==1?" step.":" steps.") << endl;
443 SetStatus(MCosy::kStopped);
444 return TRUE;
445 }
446
447 //
448 // change units from se to re
449 //
450 rd *= kGearRatio; // [re]
451
452 //
453 // Initialize Velocities so that we reach both positions
454 // at the same time
455 //
456 if (i)
457 SetPosVelocity(1.0, 0.1, 0.1);
458 else
459 SetPosVelocity(fabs(rd.Ratio()), 0.9, 0.5);
460
461 rd.Round();
462
463 // FIXME? Check for Error or Zombie?
464
465 /*
466 cout << " + " << (int)cdzd << " " << (int)cdaz << endl;
467 cout << " + APOS: Zd=" << setw(6) << p.Zd() << "se Az=" << setw(6) << p.Az() << "se" << endl;
468 cout << " + dZd=" << setw(6) << cd.Zd() << "se dAz=" << setw(6) << cd.Az() << "se" << endl;
469 cout << " + dZd=" << setw(6) << rd.Zd() << "re dAz=" << setw(6) << rd.Az() << "re" << endl;
470 cout << " + Ratio: Zd=" << setw(6) << kGearRatio.X() << "se Az=" << setw(6) << kGearRatio.Y() << "se" << endl;
471 */
472
473 //
474 // repositioning (relative)
475 //
476 DoRelPos(rd, cdzd, cdaz);
477 }
478
479 StopMovement();
480 lout << "Warning: Requested position not reached." << endl;
481 return FALSE;
482}
483
484// --------------------------------------------------------------------------
485//
486// Sets the tracking velocity
487//
488// The velocities are given in a ZdAz object in re/min. Return kTRUE
489// in case of success, kFALSE in case of failure.
490//
491Bool_t MCosy::SetVelocity(const ZdAz &v)
492{
493 //
494 // Send the new velocities for both axes.
495 //
496 fMac2->SendSDO(0x3006, 1, (LWORD_t)v.Zd()); // SetRpmVelocity [re/min]
497 fMac1->SendSDO(0x3006, 1, (LWORD_t)v.Az()); // SetRpmVelocity [re/min]
498
499 //
500 // Wait for the objects to be OKed.
501 //
502 // FIXME, what when waiting times out (Zombie)
503 WaitForSdos();
504
505 //
506 // If the waiting for the objects wasn't interrupted return kTRUE
507 //
508 if (!StopWaitingForSDO() && !HasZombie())
509 return kTRUE;
510
511 //
512 // print a message if the interruption was due to a Can-node Error
513 //
514 if (HasError())
515 lout << "Error while setting velocity (SDO #3006)" << endl;
516
517 return kFALSE;
518}
519
520// --------------------------------------------------------------------------
521//
522// Initializes Tracking mode
523//
524// Initializes the accelerations of both axes with 90% of the maximum
525// acceleration. Set the status for moving and tracking and starts thr
526// revolution mode.
527//
528bool MCosy::InitTracking()
529{
530 // FIXME? Handling of Zombie OK?
531 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
532 return false;
533
534 //
535 // Start revolution mode
536 //
537 fMac2->SetAcceleration(0.90*fMac2->GetVelRes());
538 fMac2->SetDeceleration(0.90*fMac2->GetVelRes());
539 if (fMac2->IsZombieNode())
540 return false;
541
542 fMac1->SetAcceleration(0.90*fMac1->GetVelRes());
543 fMac1->SetDeceleration(0.90*fMac1->GetVelRes());
544 if (fMac1->IsZombieNode())
545 return false;
546
547 SetStatus(MCosy::kMoving | MCosy::kTracking);
548
549 fMac2->SetRpmMode(TRUE);
550 if (fMac2->IsZombieNode())
551 return false;
552
553 fMac1->SetRpmMode(TRUE);
554 if (fMac1->IsZombieNode())
555 return false;
556
557 return true;
558}
559
560// --------------------------------------------------------------------------
561//
562// Limits the speed.
563//
564// This function should work as a limiter. If a tracking error is too large
565// to be corrected fast enough we would get enormous velocities. These
566// velocities are limited to the maximum velocity.
567//
568void MCosy::LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const
569{
570 //
571 // How to limit the speed. If the wind comes and blowes
572 // we cannot forbid changing of the sign. But on the other hand
573 // we don't want fast changes!
574 //
575
576 ULong_t vrzd = fMac1->GetVelRes();
577 ULong_t vraz = fMac2->GetVelRes();
578
579#define sgn(x) (x<0?-1:1)
580
581 const Float_t limit = 0.25;
582/*
583 if (sgn(vt->Az()) != sgn(vcalc.Az()))
584 vt->Az(0);
585// else
586 {
587 if (fabs(vt->Az()) < fabs(vcalc.Az()) *0.5)
588 vt->Az(0.5*vcalc.Az());
589
590 if (fabs(vt->Az()) > fabs(vcalc.Az()) *1.5)
591 vt->Az(1.5*vcalc.Az());
592 }
593
594 if (sgn(vt->Zd()) != sgn(vcalc.Zd()))
595 vt->Zd(0);
596// else
597 {
598 if (fabs(vt->Zd()) > fabs(vcalc.Az()) *1.5)
599 vt->Zd(1.5*vcalc.Zd());
600
601 if (fabs(vt->Zd()) < fabs(vcalc.Az()) *0.5)
602 vt->Zd(0.5*vcalc.Zd());
603 }
604 */
605
606 if (sgn(vt->Az()) != sgn(vcalc.Az())
607 && fabs(vt->Az()) < limit*fabs(vcalc.Az())
608 )
609 vt->Az(0);
610 else
611 if (fabs(vt->Az()) > 0.9*vraz)
612 {
613 lout << "Warning: Azimuth speed limit exceeded. Limiting speed to 90% max." << endl;
614 vt->Az(0.9*vraz*sgn(vt->Az()));
615 }
616
617 if (sgn(vt->Zd()) != sgn(vcalc.Zd())
618 && fabs(vt->Zd()) < limit*fabs(vcalc.Zd())
619 )
620 vt->Zd(0);
621 else
622 if (fabs(vt->Zd()) > 0.9*vrzd)
623 {
624 lout << "Warning: Altitude speed limit exceeded. Limiting speed to 90% max." << endl;
625 vt->Zd(0.9*vrzd*sgn(vt->Zd()));
626 }
627}
628
629void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad]
630{
631 SlaStars sla;
632
633 //
634 // Position to actual position
635 //
636 sla.SetMjd2Now();
637 ZdAz dest = sla.CalcZdAz(dst);
638
639 if (!SetPosition(dest))
640 {
641 lout << "Error: Cannot start tracking, positioning failed." << endl;
642 return;
643 }
644
645 //
646 // calculate offset from present se position
647 //
648 const ZdAz sepos = GetSePos()*kGearRatio;
649
650 if (!RequestRePos())
651 return;
652
653 //
654 // Estimate Offset before starting to track
655 //
656 fOffset = sepos-GetRePos();
657
658 /*
659 cout << "Sepos: " << sepos.Zd() << "re, " << sepos.Az() << "re" << endl;
660 cout << "Repos: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
661 cout << "Offset: " << fOffset.Zd() << "re, " << fOffset.Az() << "re" << endl;
662 */
663
664 //
665 // Init accelerations and Rpm Mode
666 //
667 if (!InitTracking())
668 return;
669
670 XY xy(Rad2Deg(dst.Ra())*24/360, Rad2Deg(dst.Dec()));
671
672 lout << "Start tracking:";
673 lout << " Ra: " << xy.X() << "h " << "Dec: " << xy.Y() << "\xb0" << endl;
674
675 ofstream fout("coordinates.txt");
676 fout << xy;
677 fout.close();
678
679 //
680 // Initialize Tracker (slalib or starguider)
681 //
682 fRaDec = dst;
683 fTracking = kTRUE;
684
685//--- ofstream fout("log/cosy.pos");
686//--- fout << "Tracking:";
687//--- fout << " Ra: " << Rad2Deg(dst.Ra()) << "\x9c ";
688//--- fout << "Dec: " << Rad2Deg(dst.Dec()) << "\x9c" << endl << endl;
689//--- fout << " Mjd/10ms V/re/min/4" << endl;
690
691 //
692 // We want to reach the theoretical position exactly in about 0.5s
693 //
694 const float dt = 1; // 1 second
695 while (!StopWaitingForSDO() && !HasZombie())
696 {
697 //
698 // Request Target position for this moment
699 //
700 sla.Now();
701
702 //
703 // Request theoretical Position for a time in the future (To+dt) from CPU
704 //
705 sla.SetMjd(sla.CalcMjd()+dt/(60*60*24));
706 ZdAz dummy = fBending(sla.CalcZdAz(fRaDec));
707 dest = CorrectTarget(GetSePos(), dummy); // [se]
708
709 //
710 // Request absolute position of rotary encoder from Macs
711 //
712 if (!RequestRePos())
713 break;
714
715 //
716 // distance between (To+dt) and To [re]
717 // position time difference < 5usec
718 // fOffset does the synchronization between the
719 // Shaft- and the rotary encoders
720 //
721 dest *= kGearRatio; // [re]
722 dest -= GetRePos() + fOffset;
723
724 //
725 // Velocity to go [re/min] to reach the right position at time t+dt
726 // correct for the duration of RaDec2AltAz
727 //
728 const ZdAz v = dest*60.0/(dt-(fMac2->GetTime()-sla));
729
730 //
731 // calculate real velocity of future [re/min]
732 // believing the Macs manual '/4' shouldn't be necessary, but it is.
733 //
734 ZdAz vt = v/4;
735 ZdAz vcalc = sla.GetApproxVel(fRaDec) * kGearRatio2*4./60.; // [re/min]
736 LimitSpeed(&vt, vcalc);
737 vt.Round();
738
739 //
740 // check if the drive is fast enough to follow the star
741 //
742 if (vt.Zd()>.9*fMac1->GetVelRes() || vt.Az()>.9*fMac2->GetVelRes())
743 {
744 lout << "Error: Tracking speed faster than 90% of possible maximum velocity." << endl;
745 break;
746 }
747
748 //
749 // Set theoretical velocity (as early after calculation as possible)
750 // Maybe we should attenuate the changes
751 //
752 if (!SetVelocity(vt))
753 break;
754
755 //
756 // Now do 'unnecessary' things
757 //
758 fVelocity = vt/kGearRatio2*4;
759
760//--- const double mjd = fMac2->GetMjd();
761//--- fout << setprecision(15) << setw(17) << mjd*60.*60.*24. << " ";
762//--- fout << setw(4) << vt.Zd() << " ";
763//--- fout << setw(4) << vt.Az() << endl;
764 //
765 // FIXME? Calculate an accuracy for the tracking system?
766 // How good do we reach the calculated position in 'real'
767 // re valus?
768 //
769
770
771 //
772 // Update speed as often as possible.
773 // make sure, that dt is around 10 times larger than the
774 // update time
775 //
776 //
777 // The loop should not be executed faster than the ramp of
778 // a change in the velocity can be followed.
779 // (This is important on fast machines >500MHz)
780 //
781 usleep(50000); // 0.05s
782 }
783
784 fTracking = kFALSE;
785 StopMovement();
786 lout << "Tracking stopped." << endl;
787}
788
789// --------------------------------------------------------------------------
790//
791// Stops the movement of both motors.
792//
793// Sets the status to stopping. Sets the deceleration to 50% of the maximum.
794// stops. Quits the revolution mode and wait for the end of the movement.
795//
796void MCosy::StopMovement()
797{
798 //
799 // Set status to Stopping
800 //
801 SetStatus(MCosy::kStopping);
802
803 //
804 // set deceleration to 50%
805 //
806 cout << "Stopping..." << endl;
807 fMac1->SetDeceleration(0.5*fMac1->GetVelRes());
808 if (!fMac1->IsZombieNode())
809 fMac1->SetRpmMode(FALSE);
810
811 fMac2->SetDeceleration(0.5*fMac2->GetVelRes());
812 if (!fMac2->IsZombieNode())
813 fMac2->SetRpmMode(FALSE);
814
815 //
816 // Wait for the movement to really be finished.
817 //
818 cout << "Waiting for silence..." << endl;
819 WaitForEndMovement();
820
821 //
822 // Check whether everything works fine.
823 //
824 CheckForError();
825 cout << "Movement stopped." << endl;
826}
827
828bool MCosy::CheckNetwork()
829{
830 CheckConnections();
831 if (HasZombie())
832 {
833 lout << "- Found Zombies in Network..." << endl;
834 if (!RebootZombies())
835 return false;
836 }
837 return true;
838}
839
840void *MCosy::Proc(int msg, void *mp)
841{
842 switch (msg)
843 {
844 case WM_WAIT:
845 cout << "Wait for execution of Proc(WM_*, ): done." << endl;
846 return NULL;
847
848 case WM_STOP:
849 cout << "MCosy::Proc: Stop." << endl;
850 if (!CheckNetwork())
851 return (void*)0xebb0;
852 StopMovement();
853 return NULL;
854
855 case WM_PRESET:
856 cout << "WM_Preset: start." << endl;
857 if (!CheckNetwork())
858 return (void*)0xebb0;
859 fZd1->SetPreset();
860 fZd2->SetPreset();
861 fAz->SetPreset();
862 cout << "WM_Preset: done. (return 0xaffe)" << endl;
863 return (void*)0xaffe;
864
865 case WM_CALIB:
866 {
867 cout << "WM_Calib: start." << endl;
868 if (!CheckNetwork())
869 return (void*)0xebb0;
870
871 SlaStars sla;
872 sla.SetMjd2Now();
873
874 RaDec rd = *((RaDec*)mp);
875
876 //RaDec rd(37.94, 89.2644); // POLARIS
877 //RaDec rd(213.915417, 19.1825); // ACTURUS
878
879 cout << "Calibrating to: " << rd.Ra()*24/360 << "h " << rd.Dec() << "°" << endl;
880
881 ZdAz za=sla.CalcZdAz(rd*kDeg2Rad)*16384.0/k2Pi;
882
883 cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl;
884
885 ZdAz sepos = GetSePos();
886 cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl;
887
888 fZd1->SetPreset(za.Zd());
889 fZd2->SetPreset(-za.Zd());
890 fAz->SetPreset(za.Az());
891
892 cout << "WM_Calib: done. (return 0xaffe)" << endl;
893 }
894 return (void*)0xaffe;
895
896 case WM_TPOINT:
897 {
898 cout << "WM_TPoint: start." << endl;
899 SlaStars sla;
900 sla.SetMjd2Now();
901
902 RaDec rd = *((RaDec*)mp);
903 cout << "TPoint Star: " << rd.Ra()/15 << "h " << rd.Dec() << "°" << endl;
904
905 AltAz za=sla.CalcAltAz(rd*kDeg2Rad)*kRad2Deg;
906
907 cout << " Alt/Az: " << za.Alt() << "° " << za.Az() << "°" << endl;
908 *tpout << za.Az() << " " << za.Alt() << " ";
909
910 ZdAz sepos = GetSePos()*TMath::Pi()*2/16384;;
911 za.Set(TMath::Pi()/2-sepos.Zd(), sepos.Az());
912 za *= kRad2Deg;
913
914 cout << " SE-Pos: " << za.Alt() << "° " << za.Az() << "°" << endl;
915 *tpout << fmod(za.Az()+360, 360) << " " << za.Alt() << endl;
916
917 cout << "WM_TPoint: done. (return 0xaffe)" << endl;
918 }
919 return (void*)0xca1b;
920
921 case WM_POSITION:
922 cout << "WM_Position: start." << endl;
923 {
924 if (!CheckNetwork())
925 return (void*)0xebb0;
926
927 ZdAz dest = *((ZdAz*)mp);
928 SetPosition(dest*kDeg2Rad);
929 }
930 cout << "WM_Position: done. (return 0x7777)" << endl;
931 return (void*)0x7777;
932
933 case WM_TRACK:
934 cout << "WM_Track: START" << endl;
935 {
936 if (!CheckNetwork())
937 return (void*)0xebb0;
938
939 RaDec dest = *((RaDec*)mp);
940 TrackPosition(dest*kDeg2Rad);
941 }
942 cout << "WM_Track: done. (return 0x8888)" << endl;
943 return (void*)0x8888;
944
945 case WM_NEWTRACK:
946 cout << "WM_NewTrack: START" << endl;
947 fRaDec = *((RaDec*)mp);
948 cout << "WM_NewTrack: done. (return 0x9999)" << endl;
949 return (void*)0x9999;
950
951 case WM_LOADBENDING:
952 cout << "WM_LoadBending: START" << endl;
953 fBending.Load("bending.txt");
954 cout << "WM_LoadBending: done. (return 0xbe0d)" << endl;
955 return (void*)0xbe0d;
956
957 case WM_RESETBENDING:
958 cout << "WM_ResetBending: START" << endl;
959 fBending.Reset();
960 cout << "WM_ResetBending: done. (return 0xbe0e)" << endl;
961 return (void*)0xbe0e;
962
963 case WM_HOME:
964 cout << "WM_Home: START" << endl;
965 if (!CheckNetwork())
966 return (void*)0xebb0;
967 else
968 {
969 cout << "Going Home..." << endl;
970 TEnv env(".cosyrc");
971 fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100));
972 fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100));
973
974 fAz->SetPreset();
975 fZd1->SetPreset();
976 fZd2->SetPreset();
977
978 fMac1->ReqPos();
979 fMac2->ReqPos();
980 }
981 cout << "WM_Home: done. (return 0x403e)" << endl;
982 return (void*)0x403e;
983
984 case WM_CALCALTAZ:
985 {
986 cout << endl;
987
988 SlaStars sla;
989 sla.SetMjd2Now();
990
991 XY xy = *((XY*)mp);
992 RaDec rd(xy.X()*15., xy.Y());
993
994 ZdAz a0 = sla.CalcZdAz(rd*kDeg2Rad);
995 ZdAz a1 = fBending(a0);
996 ZdAz se = CorrectTarget(GetSePos(), a1);
997 a0 *= kRad2Deg;
998 a1 *= kRad2Deg;
999 ZdAz a2 = a1*16384/360;
1000 cout << "Ra/Dec source: " << xy.X() << "h " << xy.Y() << "°" << endl;
1001 cout << "Zd/Az source: " << a0.Zd() << "° " << a0.Az() << "°" << endl;
1002 cout << "Zd/Az bended: " << a1.Zd() << "° " << a1.Az() << "°" << endl;
1003 cout << "SE bended: " << a2.Zd() << " " << a2.Az() << endl;
1004 cout << "SE target: " << se.Zd() << " " << se.Az() << endl;
1005 }
1006 return (void*)0xa17a;
1007
1008 case WM_QUIT:
1009 cout << "WM_Quit: now." << endl;
1010 if (!CheckNetwork())
1011 {
1012 lout << "ERROR: Cannot shutdown CANbus network." << endl;
1013 return (void*)0xebb0;
1014 }
1015 TerminateApp();
1016 cout << "WM_Quit: done." << endl;
1017 return (void*)0xaaaa;
1018 }
1019 cout << "MCosy::Proc: Unknown message 0x" << msg << endl;
1020 return (void*)0xffffffff;
1021}
1022
1023void *MTTalk::Thread()
1024{
1025 fCosy->TalkThread();
1026 return NULL;
1027}
1028
1029void MCosy::ReadConfig()
1030{
1031 cout << "Reading configuration file..." << flush;
1032 TEnv env(".cosyrc");
1033 cout << "done." << endl;
1034
1035 cout << "Reading gear ratios..." << flush;
1036 const Double_t gaz = env.GetValue("Az_GearRatio[U_mot/U_tel]", 1000.0);
1037 const Double_t gzd = env.GetValue("Zd_GearRatio[U_mot/U_tel]", 1000.0);
1038
1039 Double_t resreaz = 0;
1040 if (!fMac1->IsZombieNode())
1041 resreaz = fMac1->GetRes();
1042 else
1043 if (fMac3 && !fMac3->IsZombieNode())
1044 resreaz = fMac3->GetRes();
1045 else
1046 resreaz = env.GetValue("Az_ResRE[re/U_mot]", 1500);
1047
1048 Double_t resrezd = 0;
1049 if (!fMac2->IsZombieNode())
1050 resrezd = fMac2->GetRes();
1051 else
1052 resrezd = env.GetValue("Zd_ResRE[re/U_mot]", 1500);
1053
1054 Double_t ressezd = 0;
1055 if (!fZd1->IsZombieNode())
1056 ressezd = fZd1->GetPhysRes();
1057 else
1058 if (!fZd2->IsZombieNode())
1059 ressezd = fZd2->GetPhysRes();
1060 else
1061 ressezd = env.GetValue("Zd_ResSE[se/U_mot]", 16384);
1062
1063 Double_t resseaz = 0;
1064 if (!fAz->IsZombieNode())
1065 resseaz = fAz->GetPhysRes();
1066 else
1067 resseaz = env.GetValue("Az_ResSE[se/U_mot]", 16384);
1068
1069 kGearRatio.Set (gzd*resrezd/ressezd, gaz*resreaz/resseaz); //[re/se]
1070 kGearRatio2.Set(gzd*resrezd/360.0, gaz*resreaz/360.0); //[re/deg]
1071 cout << "done." << endl;
1072
1073 cout << " * Setting Gear Ratios:" << endl;
1074 cout << " --------------------" << endl;
1075 cout << " * X: " << gzd << "*" << resrezd << "/" << ressezd << "=" << kGearRatio.X() << endl;
1076 cout << " * Y: " << gaz << "*" << resreaz << "/" << resseaz << "=" << kGearRatio.Y() << endl;
1077}
1078
1079void MCosy::InitSync()
1080{
1081 if (!fMac3)
1082 return;
1083
1084 const int res = fMac3->GetVelRes();
1085
1086 fMac3->SetVelocity(res);
1087 fMac3->SetAcceleration(res);
1088 fMac3->SetDeceleration(res);
1089 fMac3->StartPosSync();
1090}
1091
1092void MCosy::TalkThread()
1093{
1094 /* ========== FIXME? =============
1095 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
1096 return;
1097 */
1098 fMac1->ReqPos();
1099 fMac2->ReqPos();
1100
1101 if (fZd1->IsZombieNode() || fZd2->IsZombieNode() || fAz->IsZombieNode())
1102 return;
1103
1104
1105 //
1106 // Start the Network
1107 //
1108 //cout << "Reading configuration file..." << flush;
1109 //TEnv env(".cosyrc");
1110 //cout << "done." << endl;
1111/*
1112 const int res = fMac3->GetVelRes();
1113
1114 fMac3->SetVelocity(res);
1115 fMac3->SetAcceleration(res);
1116 fMac3->SetDeceleration(res);
1117
1118 fMac1->ReqPos();
1119 fMac2->ReqPos();
1120
1121 //const ZdAz repos=GetRePos();
1122 //cout << "APOS: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
1123
1124 //cout << Deg2AzRE(env.GetValue("MinAz[Deg]", -1.0)) << " < Az < "
1125 //</< Deg2AzRE(env.GetValue("MaxAz[Deg]", +1.0)) << "RE" << endl;
1126 //cout << env.GetValue("MinAz[Deg]", -1.0) << " < Az < "
1127 //<< env.GetValue("MaxAz[Deg]", +1.0) << kDEG << endl;
1128 //cout << Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)) << "RE < Zd < "
1129 //<< Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)) << "RE" << endl;
1130
1131 cout << "Setting up software endswitch..." << flush;
1132 fMac1->SetNegEndswitch(Deg2AzRE(env.GetValue("Az_Min[Deg]", -1.0)));
1133 fMac1->SetPosEndswitch(Deg2AzRE(env.GetValue("Az_Max[Deg]", +1.0)));
1134
1135 fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("Zd_Min[Deg]", -1.0)));
1136 fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("Zd_Max[Deg]", +1.0)));
1137 cout << "done." << endl;
1138
1139 fMac1->EnableTimeout(kTRUE, 500);
1140 fMac2->EnableTimeout(kTRUE, 500);
1141
1142 //fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)));
1143 //fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)));
1144 // fMac3->StartVelSync();
1145 */
1146 SlaStars sla;
1147 while (1)
1148 {
1149 //
1150 // wait until a tracking session is started
1151 //
1152 while (!fTracking)
1153 usleep(1);
1154
1155//--- ofstream fout("log/cosy.err");
1156//--- fout << "Tracking:";
1157//--- fout << " Ra: " << Rad2Deg(fRaDec.Ra()) << "\x9c ";
1158//--- fout << "Dec: " << Rad2Deg(fRaDec.Dec()) << "\x9c" << endl << endl;
1159//--- fout << " MjdZd/10ms ErrZd/re";
1160//--- fout << " MjdAz/10ms ErrAd/re" << endl;
1161
1162 ZdAz old;
1163 ZdAz ist;
1164
1165 ZdAz sollzd;
1166 ZdAz sollaz;
1167
1168 ZdAz istre = -fOffset; // [re]
1169 ZdAz time;
1170
1171 //
1172 // only update fTrackingError while tracking
1173 //
1174 bool phca1=false;
1175 bool phca2=false;
1176 bool phcaz=false;
1177
1178 while (fTracking)
1179 {
1180 //
1181 // Make changes (eg wind) smoother - attenuation of control function
1182 //
1183 const float weight = 1.; //0.3;
1184
1185 //
1186 // This is the time constant which defines how fast
1187 // you correct for external influences (like wind)
1188 //
1189 fZd1->ResetPosHasChanged();
1190 fZd2->ResetPosHasChanged();
1191 fAz->ResetPosHasChanged();
1192 do
1193 {
1194 phca1 = fZd1->PosHasChanged();
1195 phca2 = fZd2->PosHasChanged();
1196 phcaz = fAz->PosHasChanged();
1197 usleep(1);
1198 } while (!phca1 && !phca2 && !phcaz && fTracking);
1199
1200 //---usleep(100000); // 0.1s
1201
1202 //
1203 // get position, where we are
1204 //
1205 old = ist;
1206 ist = GetSePos(); // [se]
1207
1208 //
1209 // if the position didn't change continue
1210 //
1211 /*---
1212 if ((int)ist.Zd() == (int)old.Zd() &&
1213 (int)ist.Az() == (int)old.Az())
1214 continue;
1215 */
1216 istre = GetRePosPdo();
1217
1218 //
1219 // Get time from last shaftencoder position change (position: ist)
1220 // FIXME: I cannot take the avarage
1221 //
1222 time.Zd((fZd1->GetMjd()+fZd2->GetMjd())/2.0);
1223 time.Az(fAz->GetMjd());
1224
1225 //
1226 // if Shaftencoder changed position
1227 // calculate were we should be
1228 //
1229 if (phca1 || phca2 /*(int)ist.Zd() != (int)old.Zd()*/)
1230 {
1231 sla.SetMjd(time.Zd());
1232
1233 ZdAz dummy = fBending(sla.CalcZdAz(fRaDec));
1234 sollzd = CorrectTarget(ist, dummy); // [se]
1235
1236 fOffset.Zd(fOffset.Zd()*(1.-weight)+(ist.Zd()*kGearRatio.X()-istre.Zd())*weight);
1237 }
1238
1239 if (phcaz /*(int)ist.Az() != (int)old.Az()*/)
1240 {
1241 sla.SetMjd(time.Az());
1242
1243 ZdAz dummy = fBending(sla.CalcZdAz(fRaDec));
1244 sollaz = CorrectTarget(ist, dummy); // [se]
1245
1246 fOffset.Az(fOffset.Az()*(1.-weight)+(ist.Az()*kGearRatio.Y()-istre.Az())*weight);
1247 }
1248
1249 fZdAzSoll.Set(sollzd.Zd(), sollaz.Az());
1250 fZdAzSoll *= 2*TMath::Pi()/16384;
1251
1252 fTrackingError.Set((ist.Zd()-sollzd.Zd())*kGearRatio.X(),
1253 (ist.Az()-sollaz.Az())*kGearRatio.Y());
1254
1255//--- fout << setprecision(15) << setw(17) << time.Zd()*60.*60.*24. << " ";
1256//--- fout << setprecision(5) << setw(7) << fTrackingError.Zd() << " ";
1257//--- fout << setprecision(15) << setw(17) << time.Az()*60.*60.*24. << " ";
1258//--- fout << setprecision(5) << setw(7) << fTrackingError.Az() << endl;
1259 }
1260
1261//--- fout << endl << endl;
1262 }
1263}
1264
1265Bool_t MCosy::HandleTimer(TTimer *t)
1266{
1267 //
1268 // Update Gui, foremer MTGui.
1269 //
1270 fZd1->DisplayVal();
1271 fZd2->DisplayVal();
1272 fAz->DisplayVal();
1273
1274 ZdAz seist = GetSePos()*2*TMath::Pi()/16384; // [se]
1275 ZdAz bendist = fBending.CorrectBack(seist);
1276
1277 Byte_t avail = 0;
1278
1279 avail |= !fMac1->IsZombieNode() ? 0x01 : 0;
1280 avail |= !fMac2->IsZombieNode() ? 0x02 : 0;
1281 avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0;
1282 avail |= !fZd1->IsZombieNode() ? 0x08 : 0;
1283 avail |= !fZd2->IsZombieNode() ? 0x10 : 0;
1284 avail |= !fAz->IsZombieNode() ? 0x20 : 0;
1285
1286 fWin->Update(bendist*(360.0/2/TMath::Pi()), fTrackingError/kGearRatio2,
1287 fVelocity, fOffset, fRaDec, fZdAzSoll, fStatus, avail);
1288
1289 /*
1290 cout << (int)(fMac1->GetStatus()&Macs::kOutOfControl) << " ";
1291 cout << (int)(fMac2->GetStatus()&Macs::kOutOfControl) << " ";
1292 cout << (int)(fMac3->GetStatus()&Macs::kOutOfControl) << endl;
1293 */
1294
1295 return kTRUE;
1296}
1297
1298
1299// --------------------------------------------------------------------------
1300//
1301// Start the work of the application:
1302//
1303// Start the Can-Network.
1304// Start the MCosy::TalkThread thread.
1305// turn on the gui update
1306//
1307void MCosy::Start()
1308{
1309 // Don't call this function twice!
1310 Network::Start();
1311
1312 ReadConfig();
1313
1314 lout << "- Starting TX Thread." << endl;
1315 fTTalk = new MTTalk(this);
1316
1317 lout << "- Starting GUI update." << endl;
1318 fUpdateGui->TurnOn();
1319}
1320
1321// --------------------------------------------------------------------------
1322//
1323// Start the work of the application:
1324//
1325// Turn of the gui update
1326// stop the MCosy::TalkThread thread.
1327// Stop the network
1328//
1329void MCosy::Stop()
1330{
1331
1332 lout << "- Stopping GUI update." << endl;
1333 fUpdateGui->TurnOff();
1334 lout << "- GUI Update stopped." << endl;
1335
1336 delete fTTalk;
1337 lout << "- TX Thread stopped." << endl;
1338
1339 Network::Stop();
1340}
1341
1342// --------------------------------------------------------------------------
1343//
1344// Disable the synchronization by using a negative CAN Id for id2.
1345//
1346void MCosy::Constructor(Int_t id1, Int_t id2, Int_t id3,
1347 Int_t id4, Int_t id5, Int_t id6)
1348{
1349 //
1350 // Create Nodes
1351 //
1352 lout << "- Setting up network." << endl;
1353
1354 fMac1=new Macs(id1, "Mac/Az", lout);
1355 fMac2=new Macs(id3, "Mac/Zd", lout);
1356 if (id2>=0)
1357 fMac3=new Macs(id2, "Mac/Az-Sync", lout);
1358
1359 fZd1=new ShaftEncoder(id4, "SE/Zd1", lout);
1360 fZd2=new ShaftEncoder(id5, "SE/Zd2", lout);
1361 fAz =new ShaftEncoder(id6, "SE/Az", lout);
1362
1363 lout << "- Connecting devices to network." << endl;
1364
1365 //
1366 // Connect the devices to the network
1367 //
1368 SetNode(fMac1);
1369 SetNode(fMac2);
1370 if (id2>=0)
1371 SetNode(fMac3);
1372 SetNode(fZd1);
1373 SetNode(fZd2);
1374 SetNode(fAz);
1375
1376 //
1377 // Create Gui Event timer and Gui
1378 //
1379 lout << "- Initializing GUI Timer." << endl;
1380 fUpdateGui = new TTimer(this, 100); // 100ms
1381
1382 lout << "- Starting GUI." << endl;
1383 fWin=new MGCosy(this, gClient->GetRoot(), 1, 1);
1384}
1385
1386void MCosy::ConstructorSE(Int_t id4, Int_t id5, Int_t id6)
1387{
1388 //
1389 // Create Nodes
1390 //
1391 lout << "- Setting up network." << endl;
1392
1393 fZd1=new ShaftEncoder(id4, "SE/Zd1", lout);
1394 fZd2=new ShaftEncoder(id5, "SE/Zd2", lout);
1395 fAz =new ShaftEncoder(id6, "SE/Az", lout);
1396
1397 lout << "- Connecting devices to network." << endl;
1398
1399 //
1400 // Connect the devices to the network
1401 //
1402 SetNode(fZd1);
1403 SetNode(fZd2);
1404 SetNode(fAz);
1405
1406 //
1407 // Create Gui Event timer and Gui
1408 //
1409 lout << "- Initializing GUI Timer." << endl;
1410 fUpdateGui = new TTimer(this, 100); // 100ms
1411
1412 lout << "- Starting GUI." << endl;
1413 fWin=new MGCosy(this, gClient->GetRoot(), 1, 1);
1414}
1415
1416void MCosy::ConstructorDemo()
1417{
1418 //
1419 // Create Nodes
1420 //
1421 lout << "- Setting up network." << endl;
1422
1423 //
1424 // Create Gui Event timer and Gui
1425 //
1426 lout << "- Initializing GUI Timer." << endl;
1427 fUpdateGui = new TTimer(this, 100); // 100ms
1428
1429 lout << "- Starting GUI." << endl;
1430 fWin=new MGCosy(this, gClient->GetRoot(), 1, 1);
1431}
1432
1433MCosy::MCosy(int mode, const char *dev, const int baud, MLog &out)
1434: Network(dev, baud, out), fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), fMac3(0), fTracking(kFALSE)
1435{
1436 TEnv env(".cosyrc");
1437 const Int_t id1 = env.GetValue("Az_Id-MAC1", 1); //1
1438 const Int_t id2 = env.GetValue("Az_Id-MAC2", 2); //2
1439 const Int_t id3 = env.GetValue("Zd_Id-MAC", 3); //3
1440 const Int_t id4 = env.GetValue("Zd_Id-SE1", 4); //4
1441 const Int_t id5 = env.GetValue("Zd_Id-SE2", 5); //5
1442 const Int_t id6 = env.GetValue("Az_Id-SE", 6); //6
1443
1444 lout << "- Program in ";
1445 switch (mode)
1446 {
1447 case 0:
1448 lout << "<<Stanard mode>>" << endl;
1449 Constructor(id1, id2, id3, id4, id5, id6);
1450 break;
1451 case 1:
1452 lout << "<<SE mode>>" << endl;
1453 ConstructorSE(id4, id5, id6);
1454 break;
1455 default:
1456 lout << "<<Demo mode>>" << endl;
1457 ConstructorDemo();
1458 }
1459
1460 lout.SetOutputGui(fWin->GetLog(), kTRUE);
1461
1462 fZd1->SetDisplay(fWin->GetLabel2());
1463 fZd2->SetDisplay(fWin->GetLabel3());
1464 fAz->SetDisplay(fWin->GetLabel1());
1465
1466 int i=0;
1467 char name[100];
1468 while (1)
1469 {
1470 sprintf(name, "/home/tbretz/TPoint/tpoint%03d.txt", i++);
1471 cout << "Testing: " << name << endl;
1472 if (gSystem->AccessPathName(name, kFileExists))
1473 break;
1474 }
1475
1476 Timer time;
1477 time.Now();
1478
1479 tpout = new ofstream(name);
1480 *tpout << "Magic Model TPOINT data file" << endl;
1481 *tpout << ": ALTAZ" << endl;
1482 *tpout << "49 48 0 ";
1483 *tpout << time.Year() << " " << time.Month() << " " << time.Day() << " ";
1484 *tpout << /*"20 1013.25 300 0.5 0.55 0.0065" <<*/ endl;
1485 // temp(°C) pressure(mB) height(m) humidity(1) wavelength(microm) troplapserate(K/m)
1486}
1487
1488void MCosy::TerminateApp()
1489{
1490 cout << "MCosy::TerminateApp()" << endl;
1491/*
1492 Int_t rc;
1493 TGMessageBox msg(this, gClient->GetRoot(),
1494 "Information",
1495 "Cosy is shutting down the system - this may take wa while!",
1496 kMBIconExclamation,
1497 kMBOK, //kMBClose
1498 &rc, 0);
1499*/
1500
1501 lout.DisableOutputDevice(MLog::eGui);
1502 lout.SetOutputGui(NULL, kFALSE);
1503
1504 gApplication->Terminate(0);
1505}
1506
1507MCosy::~MCosy()
1508{
1509 *tpout << "END" << endl;
1510 delete tpout;
1511
1512 cout << "Deleting GUI timer." << endl;
1513
1514 delete fUpdateGui;
1515
1516 cout << "Deleting Nodes." << endl;
1517
1518 delete fAz;
1519 delete fZd1;
1520 delete fZd2;
1521 delete fMac1;
1522 delete fMac2;
1523 if (fMac3)
1524 delete fMac3;
1525
1526 cout << "Deleting MGCosy." << endl;
1527
1528 lout.DisableOutputDevice(MLog::eGui);
1529
1530 delete fWin;
1531
1532 cout << "MGCosy destructed." << endl;
1533}
Note: See TracBrowser for help on using the repository browser.