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

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