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

Last change on this file since 8847 was 8839, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 43.6 KB
Line 
1#include "MCosy.h"
2
3#include <iomanip>
4#include <fstream>
5
6#include <TEnv.h>
7#include <TTimer.h>
8#include <TApplication.h>
9
10#include <TH2.h>
11#include <TH3.h>
12#include <TProfile.h>
13#include <TCanvas.h>
14
15//#include "MLog.h"
16#include "MLogManip.h"
17
18#include "MTime.h"
19#include "MPointing.h"
20
21#include "MGCosy.h"
22#include "MDriveCom.h"
23#include "MStarguider.h"
24#include "SlaStars.h"
25#include "MTracking.h"
26
27#include "macs.h"
28#include "shaftencoder.h"
29
30ClassImp(MCosy);
31
32using namespace std;
33
34typedef struct tm tm_t;
35
36/* +===================================+
37 FIXME: What if fMac3 (Sync) died?
38 +===================================+
39*/
40
41//#define EXPERT
42#undef EXPERT
43
44/*
45ZdAz MCosy::CorrectTarget(const ZdAz &src, const ZdAz &dst)
46{
47 // CorrectTarget [se]
48
49 // src [se]
50 // dst [rad]
51
52 // fAltMax = 70
53 // fAltMin = -105/110
54 // fAzMin = -355
55 // fAzMax = 355
56
57 ZdAz source = src * 360.0/16384.0;
58 ZdAz dest = dst * TMath::RadToDeg();
59
60 if (dest.Zd()>-3 && dest.Zd()<3)
61 dest.Zd(dest.Zd()<0?-3:3);
62
63 if (dest.Zd()>-1e-6 && dest.Zd()<1e-6)
64 return dst*(16384.0/k2Pi);
65
66 const float fZdMin = -67;
67 const float fZdMax = 67;
68 const float fAzMin = -29;
69 const float fAzMax = 423;
70
71 //
72 // This corrects to target for the shortest distance, not for the fastest move!
73 //
74 ZdAz s = source-dest;
75
76 float min = s.Sqr();
77
78 //
79 // Is it enought to search inside one revolution?
80 //
81 ZdAz ret = dest;
82
83 for (int i=-5; i<5+1; i++)
84 {
85 const ZdAz p(i%2 ? -dest.Zd() : dest.Zd(), dest.Az() - i*180);
86
87 //
88 // Range Check
89 //
90 if (p.Zd()<fZdMin || p.Zd()>fZdMax)
91 continue;
92
93 if (p.Az()<fAzMin || p.Az()>fAzMax)
94 continue;
95
96 //
97 // Calculate distance
98 //
99 s = source-p;
100
101 const float dist = s.Sqr();
102
103 if (dist > min)
104 continue;
105
106 //
107 // New shortest distance
108 //
109 ret = p;
110 min = dist;
111 }
112 return ret*(16384.0/360.0);
113}
114*/
115
116MTTalk::~MTTalk()
117{
118 gLog << inf2 << "~MTTalk::CancelThread" << std::endl;
119 CancelThread();
120 gLog << inf2 << "~MTTalk::MTTalk" << std::endl;
121}
122
123// --------------------------------------------------------------------------
124//
125// GetSePos, reads the Shaftencoder positions from the Can-drivers
126// for the shaftencoders. The two shaft encoders at the elevation axis
127// are avaraged. The values are returned as a ZdAz object.
128//
129// If one of the two shaftencoders on the elevation axis is missing
130// the other one's position is returned.
131//
132// The positions are alway up-to-date because the shaftencoders are
133// sending all changes immediatly.
134//
135ZdAz MCosy::GetSePos() const
136{
137 const int pa = fAz->GetPos();
138 if (fZd1->IsZombieNode() && fZd2->IsZombieNode())
139 return ZdAz(0, pa);
140
141 //
142 // Get the values
143 //
144 int p1 = (fZd1->GetPos()+8192)%16384;
145 int p2 = -(fZd2->GetPos()+8192)%16384;
146
147 if (fZd1->IsZombieNode())
148 return ZdAz(p2, pa);
149 if (fZd2->IsZombieNode())
150 return ZdAz(p1, pa);
151
152 //
153 // interpolate shaft encoder positions
154 //
155 float p = (float)(p1+p2)/2;
156
157 return ZdAz(p, pa);
158}
159
160// --------------------------------------------------------------------------
161//
162// reads the Rotary encoder positions from the last request of the Macs.
163//
164// The positions are returned as a ZdAz object. Use RequestRePos to request
165// the current positions first.
166//
167ZdAz MCosy::GetRePos()
168{
169 return ZdAz(fMac2->GetPos(), fMac1->GetPos());
170}
171
172// --------------------------------------------------------------------------
173//
174// reads the Rotary encoder positions from the Macs.
175//
176// The positions are returned as a ZdAz object. The positions are the ones
177// which are send as PDOs to the computer. This is done at a given
178// frequency. Which means, that this positions are not ought to be
179// up-to-date.
180//
181ZdAz MCosy::GetRePosPdo()
182{
183 return ZdAz(fMac2->GetPdoPos(), fMac1->GetPdoPos());
184}
185
186// --------------------------------------------------------------------------
187//
188// check for a break-signal (from the msgqueue) and errors.
189//
190int MCosy::StopWaitingForSDO() const
191{
192 return 0/*Break() || HasError()*/;
193}
194
195// --------------------------------------------------------------------------
196//
197// Waits for a movement to become finished.
198//
199// First waits for all peding Sdos, then waits until both motors are stopped
200// or waiting for SDOs was stopped (either by an error or by Break)
201//
202void MCosy::WaitForEndMovement()
203{
204 // FIXME, what when waiting times out (Zombie)
205 if (!fMac1 || !fMac2)
206 return;
207
208 while ((fMac1->IsPositioning() || fMac2->IsPositioning()) &&
209 !(Break() || HasError() || HasZombie()))
210 usleep(1);
211
212 if (!Break() && !HasError() && !HasZombie())
213 return;
214
215 MTime t(-1);
216 gLog << t << " - MCosy::WaitForEndMovement aborted...";
217 if (Break())
218 gLog << " Break signal...";
219 if (HasError())
220 gLog << " Network has error...";
221 if (HasZombie())
222 gLog << " Network has zombie...";
223 gLog << endl;
224}
225
226// --------------------------------------------------------------------------
227//
228// Check for an error...
229//
230// This is ment for usage after the Action: All Motors Stop.
231//
232void MCosy::CheckForError()
233{
234 //
235 // Check all Can-Nodes for an Error. If there is no error the motor
236 // status is set to stopped.
237 //
238 if (HasError() || HasZombie())
239 {
240 SetStatus(MDriveCom::kError);
241 return;
242 }
243
244 if (fMac1->IsPositioning() || fMac2->IsPositioning())
245 SetStatus(MDriveCom::kMoving);
246 else
247 SetStatus(MDriveCom::kStopped);
248
249 //
250 // If there is an error, the error status is set to Error.
251 //
252
253 /*
254 FIXME: HANDLINGE ERROR
255
256 //
257 // Now try to handle the error.
258 //
259 fMac1->HandleError();
260 fMac2->HandleError();
261
262 //
263 // If the error couldn't get solved return
264 //
265 if (HasError())
266 return;
267
268 //
269 // Set motor status to stopped
270 //
271 SetStatus(MDriveCom::kStopped);
272 */
273}
274
275Bool_t MCosy::CheckRange(const ZdAz &d) const
276{
277 // d [rad]
278
279 if (d.Zd()<fMin.Zd())
280 {
281 gLog << "ERROR: Requested Zenith Angle below negative endswitch." << endl;
282 return kFALSE;
283 }
284
285 if (d.Zd()>fMax.Zd())
286 {
287 gLog << "ERROR: Requested Zenith Angle behind positive endswitch." << endl;
288 return kFALSE;
289 }
290
291 if (d.Az()<fMin.Az())
292 {
293 gLog << "ERROR: Requested Azimuth Angle below negative endswitch." << endl;
294 return kFALSE;
295 }
296
297 if (d.Az()>fMax.Az())
298 {
299 gLog << "ERROR: Requested Azimuth Angle behind positive endswitch." << endl;
300 return kFALSE;
301 }
302
303
304 return kTRUE;
305}
306
307ZdAz MCosy::AlignTrackingPos(ZdAz pointing) const
308{
309 // pointing [rad]
310 // AlignTrackingPos [deg]
311
312 pointing *= TMath::RadToDeg();
313
314 if (pointing.Zd()<0)
315 {
316 pointing.Zd(-pointing.Zd());
317 pointing.Az(pointing.Az()+180);
318 //gLog << "ZD=-ZD Az+=180" << endl;
319 }
320
321 const ZdAz se = GetSePos()*TMath::TwoPi()/kResSE; // [rad]
322 const ZdAz unbendedse = fBending.CorrectBack(se)*TMath::RadToDeg(); // ist pointing
323
324 //gLog << "Unbended: " << unbendedse.Zd() << " " << unbendedse.Az() << endl;
325
326 do
327 {
328 const Double_t d = unbendedse.Az() - pointing.Az();
329 if (d>-180 && d<=180)
330 break;
331
332 //gLog << "AZ += " << TMath::Sign(360., d) << endl;
333
334 pointing.Az(pointing.Az()+TMath::Sign(360., d));
335 } while (1);
336
337 return pointing/TMath::RadToDeg();
338/*
339 const Bool_t rc = CheckRange(pointing);
340 za = pointing/TMath::RadToDeg(); // [rad]
341
342 if (!rc)
343 gLog << "Error: Aligned position out of Range." << endl;
344
345 return rc;*/
346}
347
348Double_t MCosy::Starguider(Double_t mjd, ZdAz &dest) const
349{
350 ifstream fin("pointingpos.txt");
351 if (!fin)
352 return -1;
353
354 Double_t mjd0, zd, az;
355 fin >> mjd0 >> zd >> az;
356
357 mjd0 += 52000;
358
359 if (mjd0+1./24/60 <mjd)
360 return -1;
361
362 ZdAz point=AlignTrackingPos(ZdAz(zd, az)/TMath::RadToDeg());
363 /*
364 if (!AlignTrackingPos(ZdAz(zd, az), point))
365 {
366 cout << "Starguider position couldn't be aligned..." << endl;
367 return -1;
368 }*/
369
370 // FIXME: Check Range missing!
371
372 const ZdAz diff = (dest-point)*TMath::RadToDeg();
373
374 if (diff.Zd()>5 || diff.Az()>5)
375 {
376 cout << "Starguider deviation too large... dZd=" << diff.Zd() <<" dAz="<<diff.Az() << endl;
377 return -1;
378 }
379
380 dest -= point;
381 dest *= -kGearTot/TMath::TwoPi(); // [re]
382
383 cout << "Using Starguider... dZd=" << dest.Zd() << " dAz=" << dest.Az() << endl;
384
385 return (mjd-mjd0) * (24*60*60); // [s]
386}
387
388// --------------------------------------------------------------------------
389//
390// Move the telescope to the given position. The position must be given in
391// a ZdAz object in rad.
392//
393// The first positioning is done absolutely. If we didn't reach the
394// correct psotion we try to correct for this by 10 relative position
395// maneuvers. If this doesn't help positioning failed.
396//
397// As a reference the shaftencoder values are used.
398//
399int MCosy::SetPosition(const ZdAz &dst, Bool_t track) // [rad]
400{
401 MSlewing point(this);
402
403//#ifdef EXPERT
404// point.SetAccDec(0.4, 0.4);
405// point.SetVelocity(0.2); // fast: 0.6, slow: 0.2
406//#else
407
408// original settings
409//
410 point.SetPointAccDec(0.2, 0.1);
411
412 point.SetPointVelocity(0.1);
413
414
415//#endif
416
417// point.SetPointAccDec(0.4, 0.4);
418// point.SetPointVelocity(0.4);
419
420
421// original
422 return point.SetPosition(dst, track);
423
424// test
425// return point.SetPosition(dst, kTRUE);
426
427
428
429}
430
431void MCosy::SetTrackingPosRE(ZdAz za)
432{
433 za /= kGearTot; // [U_tel]
434 za *= TMath::TwoPi(); // [rad]
435 //cout << "RE1: " << za.Zd()*180/3.1415 << " " << za.Az()*180/3.1415 << endl;
436 fTrackingPosRaw = za*TMath::RadToDeg();
437 fTrackingPos = fBending.CorrectBack(za)*TMath::RadToDeg();
438 //cout << "RE2: " << fTrackingPos.Zd() << " " << fTrackingPos.Az() << endl;
439}
440
441void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad]
442{
443 MTracking track(this);
444 track.SetOut(fOutRep);
445//#ifdef EXPERT
446// track.SetPointAccDec(0.4, 0.4);
447// track.SetPointVelocity(0.2); // fast: 0.6, slow: 0.2
448//#else
449
450
451
452 track.SetPointAccDec(0.2, 0.1);
453 track.SetPointVelocity(0.1);
454
455 // track.SetPointAccDec(0.4, 0.4);
456 // track.SetPointVelocity(0.4);
457
458
459
460//#endif
461 track.SetTrackAccDec(0.1, 0.1);
462
463 track.TrackPosition(dst);
464}
465
466void MCosy::TrackPositionGRB(const RaDec &dst) // ra, dec [rad]
467{
468 MTracking track(this);
469 track.SetOut(fOutRep);
470//#ifdef EXPERT
471// track.SetPointAccDec(0.4, 0.4);
472// track.SetPointVelocity(0.2); // fast: 0.6, slow: 0.2
473//#else
474 track.SetPointAccDec(0.4, 0.4);
475 track.SetPointVelocity(0.3);
476//#endif
477 track.SetTrackAccDec(0.1, 0.1);
478
479 track.TrackPosition(dst);
480}
481
482// --------------------------------------------------------------------------
483//
484// Stops the movement of both motors.
485//
486// Sets the status to stopping. Sets the deceleration to 50% of the maximum.
487// stops. Quits the revolution mode and wait for the end of the movement.
488//
489void MCosy::StopMovement()
490{
491 //
492 // Set status to Stopping
493 //
494 SetStatus(MDriveCom::kStopping);
495
496 //
497 // set deceleration to 50%
498 //
499 cout << "Stopping movement (dec=30%)..." << endl;
500 if (fMac1 && fMac2)
501 {
502#ifdef EXPERT
503 fMac1->SetDeceleration(TMath::Nint(0.5*fMac1->GetVelRes()));
504 fMac2->SetDeceleration(TMath::Nint(0.5*fMac2->GetVelRes()));
505#else
506 fMac1->SetDeceleration(TMath::Nint(0.3*fMac1->GetVelRes()));
507 fMac2->SetDeceleration(TMath::Nint(0.3*fMac2->GetVelRes()));
508#endif
509 fMac1->SetRpmMode(FALSE);
510 fMac2->SetRpmMode(FALSE);
511 }
512
513/*
514 fMac1->SetDeceleration(0.3*fMac1->GetVelRes());
515 fMac2->SetDeceleration(0.3*fMac2->GetVelRes());
516
517 fMac2->SendSDO(0x3000, Macs::string('s','t','o','p'));
518 fMac1->SendSDO(0x3000, Macs::string('s','t','o','p'));
519 fMac2->WaitForSdo(0x3000, 0);
520 fMac1->WaitForSdo(0x3000, 0);
521 fMac1->SetRpmMode(FALSE);
522 fMac2->SetRpmMode(FALSE);
523 */
524
525 //
526 // Wait for the movement to really be finished.
527 //
528#ifdef EXPERT
529 cout << "Waiting for end of movement..." << endl;
530#endif
531 WaitForEndMovement();
532
533 //
534 // Check whether everything works fine.
535 //
536 CheckForError();
537#ifdef EXPERT
538 cout << "Movement stopped." << endl;
539#endif
540}
541
542bool MCosy::CheckNetwork()
543{
544 //return kTRUE;
545 //CheckConnections();
546
547 CheckForError();
548
549 if (HasZombie())
550 {
551 lout << "- Found Zombies in Network..." << endl;
552 if (!RebootZombies())
553 return false;
554 }
555
556 /*
557 FIXME HANDLING ERROR
558 */
559 if (HasError())
560 {
561 fMac1->HandleError();
562 fMac2->HandleError();
563 fMac3->HandleError();
564 if (HasError() || HasZombie())
565 return false;
566 }
567
568 CheckForError();
569 return true;
570}
571
572Int_t MCosy::Proc(int msg, void *mp)
573{
574 switch (msg)
575 {
576 case WM_WAIT:
577 cout << "Wait for execution of Proc(WM_*, ): done." << endl;
578 return 0;
579
580 case WM_STOP:
581 //cout << "MCosy::Proc: Stop." << endl;
582 if (!CheckNetwork())
583 return 0xebb0;
584 StopMovement();
585 return 0;
586/*
587 case WM_PRESET:
588 cout << "WM_Preset: start." << endl;
589 if (!CheckNetwork())
590 return (void*)0xebb0;
591 fZd1->SetPreset();
592 fZd2->SetPreset();
593 fAz->SetPreset();
594 cout << "WM_Preset: done. (return 0xaffe)" << endl;
595 return (void*)0xaffe;
596*/
597 /*
598 case WM_CALIB:
599 {
600 cout << "WM_Calib: start." << endl;
601 if (!CheckNetwork())
602 return (void*)0xebb0;
603
604 SlaStars sla(fObservatory);
605 sla.Now();
606
607 RaDec rd = *((RaDec*)mp);
608
609 //RaDec rd(37.94, 89.2644); // POLARIS
610 //RaDec rd(213.915417, 19.1825); // ARCTURUS
611
612 cout << "Calibrating to: " << rd.Ra()*24/360 << "h " << rd.Dec() << "°" << endl;
613
614 ZdAz za=sla.CalcZdAz(rd*TMath::DegToRad())*16384.0/k2Pi;
615
616 cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl;
617
618 ZdAz sepos = GetSePos();
619 cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl;
620
621 fZd1->SetPreset(za.Zd());
622 fZd2->SetPreset(-za.Zd());
623 fAz->SetPreset(za.Az());
624
625 cout << "WM_Calib: done. (return 0xaffe)" << endl;
626 }
627 return (void*)0xaffe;
628 */
629 case WM_TPOINT:
630 {
631 //cout << "WM_TPoint: start." << endl;
632 SlaStars sla(fObservatory);
633 sla.Now();
634
635 RaDec rd = *((RaDec*)mp);
636 cout << "TPoint Star: " << rd.Ra()/15 << "h " << rd.Dec() << "°" << endl;
637
638 AltAz za=sla.CalcAltAz(rd*TMath::DegToRad())*TMath::RadToDeg();
639
640 if (!fOutTp)
641 {
642 //
643 // open tpoint file
644 //
645 const TString name = GetFileName("tpoint", "old-tpoint", "txt");
646 cout << "TPoint-Cosy File ********* " << name << " ********** " << endl;
647
648 fOutTp = new ofstream(name);
649 *fOutTp << "Magic Model TPOINT data file" << endl;
650 *fOutTp << ": ALTAZ" << endl;
651 *fOutTp << "49 48 0 ";
652 *fOutTp << sla.GetTime().Year() << " " << sla.GetTime().Month() << " " << sla.GetTime().Day() << " ";
653 *fOutTp << /*"20 1013.25 300 0.5 0.55 0.0065" <<*/ endl;
654 // temp(°C) pressure(mB) height(m) humidity(1) wavelength(microm) troplapserate(K/m)
655 }
656
657 cout << " Alt/Az: " << za.Alt() << "° " << za.Az() << "°" << endl;
658 *fOutTp << setprecision(7) << za.Az() << " " << za.Alt() << " ";
659
660 ZdAz sepos = GetSePos()*TMath::TwoPi()/kResSE;
661 za.Set(TMath::Pi()/2-sepos.Zd(), sepos.Az());
662 za *= TMath::RadToDeg();
663
664 cout << " SE-Pos: " << za.Alt() << "° " << za.Az() << "°" << endl;
665 *fOutTp << fmod(za.Az()+360, 360) << " " << za.Alt() << " ";
666
667 if (fStarguider)
668 {
669 XY tp = fStarguider->GetCoordinates();
670 *fOutTp << 90-tp.X() << " " << tp.Y() << " ";
671 }
672
673 *fOutTp << rd.Ra()/15 << " " << rd.Dec() << " " << setprecision(11) << sla.GetMjd() << endl;
674
675 //cout << "WM_TPoint: done. (return 0xaffe)" << endl;
676 }
677 return 0xca1b;
678
679 case WM_TRACKPOS:
680 //cout << "WM_TrackPosition: start." << endl;
681 {
682 if (!CheckNetwork())
683 return 0xebb0;
684
685 ZdAz dest = *((ZdAz*)mp) * TMath::DegToRad();
686 if (!SetPosition(dest, kTRUE))
687 return 0x1234;
688
689 SlaStars sla(fObservatory);
690 sla.Now();
691
692 RaDec rd = sla.CalcRaDec(dest);
693 TrackPosition(rd);
694 }
695 //cout << "WM_TrackPosition: done. (return 0xabcd)" << endl;
696 return 0xabcd;
697/*
698 case WM_ARM:
699 //cout << "WM_Position: start." << endl;
700 {
701 if (!CheckNetwork())
702 return (void*)0xebb0;
703
704 const bool arm = *((bool*)mp);
705 if (arm)
706 {
707 fMac1->Arm();
708 fMac2->Arm();
709 cout << "ARMED" << endl;
710 }
711 else
712 {
713 fMac1->Disarm();
714 fMac2->Disarm();
715 cout << "DISARMED" << endl;
716 }
717 }
718 //cout << "WM_Position: done. (return 0x7777)" << endl;
719 return (void*)0x9999;
720 */
721 case WM_POSITION:
722 //cout << "WM_Position: start." << endl;
723 {
724 if (!CheckNetwork())
725 return 0xebb0;
726
727 ZdAz dest = *((ZdAz*)mp);
728 SetPosition(dest*TMath::DegToRad());
729 }
730 //cout << "WM_Position: done. (return 0x7777)" << endl;
731 return 0x7777;
732
733 case WM_POSITION1:
734 //cout << "WM_Position1: start." << endl;
735 {
736 if (!CheckNetwork())
737 return 0xebb0;
738
739 ZdAz dest = *((ZdAz*)mp);
740 SetPosition(dest*TMath::DegToRad(), kTRUE);
741 }
742 //cout << "WM_Position: done. (return 0x7777)" << endl;
743 return 0x7777;
744
745 case WM_PREPS:
746 //cout << "WM_Track: START" << endl;
747 {
748 if (!CheckNetwork())
749 return 0xebb0;
750
751 const char *preps = (const char*)mp;
752 cout << "Preposition command to " << preps << " received." << endl;
753
754 ifstream fin("prepos.txt");
755 if (!fin)
756 {
757 cout << "ERROR: cannot open prepos.txt." << endl;
758 return 0xebb1;
759 }
760
761 while (1)
762 {
763 Double_t zd, az;
764 fin >> zd >> az;
765
766 TString str;
767 str.ReadLine(fin);
768 if (!fin)
769 break;
770
771 str.ToLower();
772
773 if (str.Strip(TString::kBoth)==preps)
774 {
775 ZdAz dest(zd, az);
776 SetPosition(dest*TMath::DegToRad());
777 return 0x7979;
778 }
779 cout << "ERROR - Requested preposition not found in file..." << endl;
780 }
781 }
782 //cout << "WM_Track: done. (return 0x8888)" << endl;
783 return 0x7878;
784
785 case WM_TESTSE:
786 //cout << "WM_TestSe: start." << endl;
787 fBackground = mp ? kBgdSeTest : kBgdNone;
788 //cout << "WM_TestSe: done. (return 0x1e51)" << endl;
789 return 0x1e51;
790
791 case WM_GEAR:
792 //cout << "WM_Gear: start." << endl;
793 fBackground = mp ? kBgdGear : kBgdNone;
794 //cout << "WM_Gear: done. (return 0xfeaf)" << endl;
795 return 0xfeaf;
796
797 case WM_DISPLAY:
798 //cout << "WM_Display: start." << endl;
799 fTriggerDisplay = kTRUE;
800 //cout << "WM_Disply: done. (return 0xd1e1)" << endl;
801 return 0xd1e1;
802
803 case WM_TRACK:
804 case WM_GRB:
805 //cout << "WM_Track/GRB: START" << endl;
806 {
807 RaDec dest = ((RaDec*)mp)[0];
808 if (fStarguider)
809 fStarguider->SetPointingPosition(((RaDec*)mp)[1]);
810 if (!CheckNetwork())
811 return 0xebb0;
812
813 if (msg==WM_TRACK)
814 TrackPosition(dest*TMath::DegToRad());
815 else
816 TrackPositionGRB(dest*TMath::DegToRad());
817 }
818 //cout << "WM_Track/GRB: done. (return 0x8888)" << endl;
819 return 0x8888;
820
821 case WM_NEWTRACK:
822 //cout << "WM_NewTrack: START" << endl;
823 fRaDec = *((RaDec*)mp);
824 //cout << "WM_NewTrack: done. (return 0x9999)" << endl;
825 return 0x9999;
826
827 case WM_LOADBENDING:
828 //cout << "WM_LoadBending: START" << endl;
829 fBending.Load("bending.txt");
830 //cout << "WM_LoadBending: done. (return 0xbe0d)" << endl;
831 return 0xbe0d;
832
833 case WM_RESETBENDING:
834 //cout << "WM_ResetBending: START" << endl;
835 fBending.Reset();
836 //cout << "WM_ResetBending: done. (return 0xbe0e)" << endl;
837 return 0xbe0e;
838
839 case WM_HOME:
840 //cout << "WM_Home: START" << endl;
841 if (!CheckNetwork())
842 return 0xebb0;
843 else
844 {
845 cout << "HOME NOT ALLOWED... for Magic." << endl;
846 /*
847 cout << "Going Home..." << endl;
848 TEnv env(".cosyrc");
849
850 SetStatus(MDriveCom::kMoving);
851
852 fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100));
853 fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100));
854
855 gLog << "SETHOME DONE" << endl;
856
857 SetStatus(HasError() ? MDriveCom::kError : MDriveCom::kStopped);
858
859 fAz->SetPreset();
860 fZd1->SetPreset();
861 fZd2->SetPreset();
862
863 fMac1->ReqPos();
864 fMac2->ReqPos();
865 fMac3->StopMotor();
866 */
867 }
868 //cout << "WM_Home: done. (return 0x403e)" << endl;
869 return 0x403e;
870
871 case WM_CALCALTAZ:
872 {
873 cout << endl;
874
875 SlaStars sla(fObservatory);
876 sla.Now();
877
878 XY xy = *((XY*)mp);
879 RaDec rd(xy.X()*15., xy.Y()); // [deg]
880
881 ZdAz a1 = sla.CalcZdAz(rd*TMath::DegToRad()); // [rad]
882
883 cout << "Ra/Dec source: " << xy.X() << "h " << xy.Y() << "°" << endl;
884 cout << "Zd/Az target: " << a1.Zd()*TMath::RadToDeg() << "° " << a1.Az()*TMath::RadToDeg() << "°" << endl;
885
886 if (fZd1 && fZd2 && fAz)
887 a1 = AlignTrackingPos(a1);
888
889 a1 = fBending(a1);
890 CheckRange(a1);
891 a1 *= TMath::RadToDeg();
892
893 const ZdAz a2 = a1*kResSE/360;
894
895 cout << "Zd/Az bended: " << a1.Zd() << "° " << a1.Az() << "°" << endl;
896 cout << "SE bended: " << a2.Zd() << " " << a2.Az() << endl;
897 }
898 return 0xa17a;
899
900 case WM_ENDSWITCH:
901 {
902 ZdAz pos = GetSePos()*TMath::TwoPi()/kResSE;
903 pos = fBending.SubtractOffsets(pos)*TMath::RadToDeg();
904
905 cout << "Endswitch Position: Zd=" << pos.Zd() << "° Az=";
906 cout << pos.Az() << "°" << endl;
907 }
908
909 return 0x1010;
910
911 case WM_QUIT:
912 cout << "WM_Quit: now." << endl;
913 if (!CheckNetwork())
914 {
915 gLog << "ERROR: Cannot shutdown CANbus network." << endl;
916 return 0xebb0;
917 }
918 TerminateApp();
919 cout << "WM_Quit: done." << endl;
920 return 0xaaaa;
921 }
922 cout << "MCosy::Proc: Unknown message 0x" << msg << endl;
923 return 0xffffffff;
924}
925
926Int_t MTTalk::Thread()
927{
928 fCosy->TalkThread();
929 return 0;
930}
931
932void MCosy::ReadConfig()
933{
934 cout << "Reading configuration file..." << flush;
935 TEnv env(".cosyrc");
936 cout << "done." << endl;
937
938 cout << "Reading telescope range..." << flush;
939 const Double_t amin = env.GetValue("Az_Min[deg]", -95.0);
940 const Double_t zmin = env.GetValue("Zd_Min[deg]", -75.0);
941 fMin.Set(zmin, amin);
942
943 const Double_t amax = env.GetValue("Az_Max[deg]", 305.0);
944 const Double_t zmax = env.GetValue("Zd_Max[deg]", 98.25);
945 fMax.Set(zmax, amax);
946 cout << "done." << endl;
947
948 cout << " * Min: " << zmin << "deg " << amin << "deg" << endl;
949 cout << " * Max: " << zmax << "deg " << amax << "deg" << endl;
950
951 fMin = fBending.AddOffsets(fMin/TMath::RadToDeg());
952 fMax = fBending.AddOffsets(fMax/TMath::RadToDeg());
953
954 cout << " * Min': " << fMin.Zd()*TMath::RadToDeg() << "deg " << fMin.Az()*TMath::RadToDeg() << "deg" << endl;
955 cout << " * Max': " << fMax.Zd()*TMath::RadToDeg() << "deg " << fMax.Az()*TMath::RadToDeg() << "deg" << endl;
956
957 cout << "Reading gear ratios..." << flush;
958// kGear.X(env.GetValue("Zd_GearRatio[U_mot/U_tel]", 1000.0));
959// kGear.Y(env.GetValue("Az_GearRatio[U_mot/U_tel]", 1000.0));
960 kGear.Set(env.GetValue("Zd_GearRatio[U_mot/U_tel]", 1000.0),
961 env.GetValue("Az_GearRatio[U_mot/U_tel]", 1000.0));
962
963 Bool_t mac1 = fMac1 && !fMac1->IsZombieNode();
964 Bool_t mac2 = fMac2 && !fMac2->IsZombieNode();
965 Bool_t mac3 = fMac3 && !fMac3->IsZombieNode();
966
967 Bool_t zd1 = fZd1 && !fZd1->IsZombieNode();
968 Bool_t zd2 = fZd2 && !fZd2->IsZombieNode();
969 Bool_t az = fAz && !fAz->IsZombieNode();
970
971 Double_t x = 0;
972 Double_t y = 0;
973 y = mac1 ? fMac1->GetRes() : (mac3 ? fMac3->GetRes() : env.GetValue("Az_ResRE[re/U_mot]", 1500));
974 x = mac2 ? fMac2->GetRes() : env.GetValue("Zd_ResRE[re/U_mot]", 1500);
975 kResRE.Set(x,y);
976
977 x = zd1 ? fZd1->GetPhysRes() : (zd2 ? fZd2->GetPhysRes() : env.GetValue("Zd_ResSE[se/U_mot]", 16384));
978 y = az ? fAz->GetPhysRes() : env.GetValue("Az_ResSE[se/U_mot]", 16384);
979 kResSE.Set(x,y);
980
981 /*
982 kResRE.Y(0);
983 if (fMac1 && !fMac1->IsZombieNode())
984 kResRE.Y(fMac1->GetRes());
985 else
986 y = fMac3 && !fMac3->IsZombieNode() ? fMac3->GetRes() : env.GetValue("Az_ResRE[re/U_mot]", 1500);
987 if (fMac3 && !fMac3->IsZombieNode())
988 kResRE.Y(fMac3->GetRes());
989 else
990 kResRE.Y(env.GetValue("Az_ResRE[re/U_mot]", 1500));
991
992 kResRE.X(0);
993 if (fMac2 && !fMac2->IsZombieNode())
994 kResRE.X(fMac2->GetRes());
995 else
996 kResRE.X(env.GetValue("Zd_ResRE[re/U_mot]", 1500));
997
998 kResSE.X(0);
999 if (fZd1 && !fZd1->IsZombieNode())
1000 kResSE.X(fZd1->GetPhysRes());
1001 else
1002 if (fZd2 && !fZd2->IsZombieNode())
1003 kResSE.X(fZd2->GetPhysRes());
1004 else
1005 kResSE.X(env.GetValue("Zd_ResSE[se/U_mot]", 16384));
1006
1007 kResSE.Y(0);
1008 if (fAz && !fAz->IsZombieNode())
1009 kResSE.Y(fAz->GetPhysRes());
1010 else
1011 kResSE.Y(env.GetValue("Az_ResSE[se/U_mot]", 16384));
1012 */
1013
1014 // believing the Macs manual '*4' shouldn't be necessary, but it is.
1015 // Because the a RE is 4 quad counts.
1016 // Calculating speeds we have to convert back to qc
1017 kResRE *= 4;
1018 kGearTot = Mul(kResRE, kGear);
1019// kGearTot = kResRE*kGear;
1020
1021 cout << "done." << endl;
1022
1023 cout << " * Setting Gear Ratios:" << endl;
1024 cout << " --------------------" << endl;
1025 cout << " * X: " << kGear.X() << "*" << kResRE.X()/4 << "/" << kResSE.X() << "=4*" << kGearTot.X() << "/" << kResSE.X() << endl;
1026 cout << " * Y: " << kGear.Y() << "*" << kResRE.Y()/4 << "/" << kResSE.Y() << "=4*" << kGearTot.Y() << "/" << kResSE.Y() << endl;
1027}
1028/*
1029void MCosy::InitSync()
1030{
1031 if (!fMac3)
1032 {
1033 gLog << "Unable to Init Sync! Mac3 not available." << endl;
1034 return;
1035 }
1036
1037 const int res = fMac3->GetVelRes();
1038
1039 fMac3->SetVelocity(0.3*res);
1040 fMac3->SetAcceleration(0.2*res);
1041 fMac3->SetDeceleration(0.2*res);
1042 fMac3->StartPosSync();
1043}
1044*/
1045void MCosy::TalkThreadSeTest()
1046{
1047// if (fZd1->IsZombieNode() || fZd2->IsZombieNode())
1048 // return;
1049
1050 if (fHist)
1051 {
1052 gLog << "You are much too fast... try again." << endl;
1053 return;
1054 }
1055
1056 fHist = new TH2F("Diff", "Difference of SE values",
1057 201, fMin.Zd(), fMax.Zd(), 41, -10.5, 10.5);
1058 fHist->SetXTitle("ZA [\\circ]");
1059 fHist->SetYTitle("\\Delta SE");
1060
1061 Double_t offset = 0;
1062
1063 int cnt = 0;
1064
1065 gLog << "Starting Shaftencoder Test..." << endl;
1066
1067 while (fBackground==kBgdSeTest)
1068 {
1069 fZd1->ResetPosHasChanged();
1070 fZd2->ResetPosHasChanged();
1071
1072 while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() &&
1073 fBackground==kBgdSeTest)
1074 {
1075 usleep(1);
1076 TThread::CancelPoint();
1077 }
1078
1079 const Double_t pos[3] = {
1080 (fZd1->GetPos()+8192)%16384,
1081 (fZd2->GetPos()+8192)%16384,
1082 fAz->GetPos() };
1083
1084 //
1085 // Estimate Offset from the first ten positions
1086 //
1087 if (cnt++<10)
1088 {
1089 offset += pos[0]+pos[1];
1090 continue;
1091 }
1092 if (cnt==11)
1093 {
1094 offset /= 10;
1095 cnt++;
1096 }
1097
1098 Double_t apos = (pos[0]-pos[1])/2 * TMath::TwoPi() / kResSE.X();
1099
1100 ZdAz bend = fBending.CorrectBack(ZdAz(apos, pos[2]))*TMath::RadToDeg();
1101 fHist->Fill(bend.Zd(), pos[0]+pos[1]-offset);
1102 }
1103
1104 gLog << "Shaftencoder Test Stopped... displaying Histogram." << endl;
1105
1106 fBackground=kBgdSeTestDispl;
1107}
1108
1109void MCosy::TalkThreadGear()
1110{
1111// if (fZd1->IsZombieNode() || fZd2->IsZombieNode())
1112 // return;
1113
1114 if (fHist)
1115 {
1116 gLog << "You are much too fast... try again." << endl;
1117 return;
1118 }
1119
1120 fHist = new TH3F("Gear", "Gear Ratio Re/Se",
1121 (int)((fMax.Zd()-fMin.Zd())/2.5+1), fMin.Zd(), fMax.Zd(),
1122 (int)((fMax.Az()-fMin.Az())/2.5+1), fMin.Az(), fMax.Az(),
1123 61, 349.5, 500.5);
1124
1125 fHist->SetXTitle("Zd [\\circ]");
1126 fHist->SetYTitle("Az [\\circ]");
1127 fHist->SetZTitle("Re/Se");
1128
1129 gLog << "Starting Gear determination..." << endl;
1130
1131 ZdAz se0 = GetSePos();
1132 ZdAz re0 = GetRePosPdo();
1133
1134 while (fBackground==kBgdGear)
1135 {
1136 fZd1->ResetPosHasChanged();
1137 fZd2->ResetPosHasChanged();
1138 fAz->ResetPosHasChanged();
1139
1140 while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() &&
1141 !fAz->PosHasChanged() && fBackground==kBgdGear)
1142 {
1143 usleep(1);
1144 TThread::CancelPoint();
1145 }
1146
1147 ZdAz se = GetSePos();
1148 ZdAz re = GetRePosPdo();
1149
1150 ZdAz dse = se-se0;
1151 ZdAz dre = re-re0;
1152
1153 if (fabs(dse.Zd())*144>kResSE.X()) // Each 2.5deg (144)
1154 {
1155 se0.Zd(se.Zd());
1156 re0.Zd(re.Zd());
1157
1158 se -= dse/2;
1159
1160 ZdAz bend = fBending.CorrectBack(se*TMath::TwoPi()/kResSE)*TMath::RadToDeg();
1161 ((TH3*)fHist)->Fill(bend.Zd(), bend.Az(), dre.Zd()/dse.Zd());
1162 }
1163
1164 if (fabs(dse.Az())*144>kResSE.Y()) // Each 2.5deg (144)
1165 {
1166 se0.Az(se.Az());
1167 re0.Az(re.Az());
1168
1169 se -= dse/2;
1170
1171 ZdAz bend = fBending.CorrectBack(se*TMath::TwoPi()/kResSE)*TMath::RadToDeg();
1172 ((TH3*)fHist)->Fill(bend.Az(), bend.Az(), dre.Az()/dse.Az());
1173 }
1174 }
1175 gLog << "Gear Test Stopped... displaying Histogram." << endl;
1176
1177 fBackground=kBgdGearDispl;
1178}
1179
1180void MCosy::TalkThread()
1181{
1182 /* ========== FIXME? =============
1183 if (fMac1->IsZombieNode() || fMac2->IsZombieNode())
1184 return;
1185 */
1186
1187 if (fMac1 && fMac2)
1188 {
1189 fMac1->ReqPos();
1190 fMac2->ReqPos();
1191 }
1192
1193 //InitSync();
1194
1195 /*** FOR DEMO MODE ***/
1196 if (!fZd1 || !fZd2 || !fAz)
1197 return;
1198 /*** FOR DEMO MODE ***/
1199
1200 //
1201 // Start the Network
1202 //
1203 while (1)
1204 {
1205 //
1206 // wait until a tracking session is started
1207 //
1208 while (fBackground==kBgdNone)
1209 {
1210 usleep(1);
1211 TThread::CancelPoint();
1212 }
1213
1214 switch (fBackground)
1215 {
1216 case kBgdNone:
1217 continue;
1218/*#ifndef NEWALGO
1219 case kBgdTracking:
1220 TalkThreadTracking();
1221 continue;
1222#endif*/
1223 case kBgdSeTest:
1224 TalkThreadSeTest();
1225 continue;
1226
1227 case kBgdGear:
1228 TalkThreadGear();
1229 continue;
1230
1231 default:
1232 continue;
1233 }
1234 }
1235}
1236
1237ZdAz MCosy::GetPointingPos() const
1238{
1239 if (fZd1->IsZombieNode() || fZd2->IsZombieNode() || fAz->IsZombieNode())
1240 return ZdAz(0, 0);
1241
1242 // GetPointingPos [deg]
1243 const ZdAz seist = GetSePos()*TMath::TwoPi()/kResSE; // [rad]
1244 return fBending.CorrectBack(seist)*TMath::RadToDeg();
1245}
1246
1247Bool_t MCosy::HandleTimer(TTimer *t)
1248{
1249 const Int_t rc = fMutexGui.TryLock();
1250 if (rc==13)
1251 cout << "MCosy::HandleTimer - mutex is already locked by this thread" << endl;
1252
1253 if (rc)
1254 {
1255 gLog << "* GUI update skipped due to locked mutex." << endl;
1256 return kTRUE;
1257 }
1258
1259 //
1260 // Update Gui, foremer MTGui.
1261 //
1262 if (fZd1)
1263 fZd1->DisplayVal();
1264 if (fZd2)
1265 fZd2->DisplayVal();
1266 if (fAz)
1267 fAz->DisplayVal();
1268
1269 Byte_t avail = 0;
1270
1271 avail |= (fMac1 && !fMac1->IsZombieNode()) ? 0x01 : 0;
1272 avail |= (fMac2 && !fMac2->IsZombieNode()) ? 0x02 : 0;
1273 avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0;
1274 avail |= (fZd1 && !fZd1->IsZombieNode()) ? 0x08 : 0;
1275 avail |= (fZd2 && !fZd2->IsZombieNode()) ? 0x10 : 0;
1276 avail |= (fAz && !fAz->IsZombieNode()) ? 0x20 : 0;
1277// avail |= (!(fStatus&MDriveCom::kError) && 1 ? 0x40 : 0;
1278
1279 if (HasError())
1280 SetStatus(MDriveCom::kError);
1281
1282
1283 ZdAz bendist = fStatus&MDriveCom::kTracking ? fTrackingPos : GetPointingPos();
1284
1285 //cout << (fStatus&MDriveCom::kTracking?"TRA: ":"POS: ") << bendist.Zd() << " " << bendist.Az() << endl;
1286
1287 fCom->SendReport(fStatus, fRaDec, fZdAzSoll, bendist, fTrackingError);
1288
1289 fWin->UpdateWeather(*fCom);
1290 fWin->Update(bendist, fTrackingError, fVelocity, /*fOffset,*/
1291 fRaDec, fZdAzSoll, fStatus, avail);
1292
1293 gLog.UpdateGui();
1294
1295 const Bool_t trigger = fTriggerDisplay;
1296 fTriggerDisplay = kFALSE;
1297
1298 if (fBackground==kBgdSeTestDispl || (trigger&&fBackground==kBgdSeTest))
1299 DisplayHistTestSe(!trigger);
1300
1301 if (fBackground==kBgdGearDispl || (trigger&&fBackground==kBgdGear))
1302 DisplayHistGear(!trigger);
1303
1304 if (fMutexGui.UnLock()==13)
1305 cout << "MCosy::HandleTimer - tried to unlock mutex locked by other thread." << endl;
1306
1307 return kTRUE;
1308}
1309
1310void MCosy::DisplayHistTestSe(Bool_t del)
1311{
1312 gLog << "Displaying histogram..." << endl;
1313
1314 TH2F &hist = *(TH2F*)fHist;
1315
1316 if (del)
1317 {
1318 fHist = NULL;
1319 fBackground = kBgdNone;
1320 }
1321
1322 TCanvas *c=new TCanvas("c1", "", 1000, 1000);
1323 c->Divide(1,2);
1324
1325 c->cd(1);
1326 TH2 *h=(TH2*)hist.DrawCopy();
1327
1328 TProfile *p = h->ProfileX("_pfx", -1, 9999, "s");
1329 p->SetLineColor(kBlue);
1330 p->Draw("same");
1331 p->SetBit(kCanDelete);
1332
1333 c->cd(2);
1334
1335 TH1F p2("spread", "Spread of the differences", hist.GetNbinsX(), hist.GetBinLowEdge(1),
1336 hist.GetBinLowEdge(hist.GetNbinsX()+1));
1337 p2.SetXTitle("Zd [\\circ]");
1338 for (int i=0; i<hist.GetNbinsX(); i++)
1339 p2.SetBinError(i, p->GetBinError(i));
1340 p2.SetLineColor(kRed);
1341 p2.SetStats(0);
1342 p2.DrawCopy();
1343
1344 if (del)
1345 delete &hist;
1346}
1347
1348void MCosy::DisplayHistGear(Bool_t del)
1349{
1350 gLog << "Displaying histogram..." << endl;
1351
1352 TH3F &hist = *(TH3F*)fHist;
1353
1354 if (del)
1355 {
1356 fHist = NULL;
1357 fBackground = kBgdNone;
1358 }
1359
1360 TCanvas *c=new TCanvas("c1", "", 1000, 1000);
1361 c->Divide(2,2);
1362
1363 // ----------
1364
1365 c->cd(1);
1366 TH2D &h1=*(TH2D*)hist.Project3D("zx"); // Zd
1367 h1.SetTitle(" Gear Ratio Zenith Distance [re/se] ");
1368 h1.SetXTitle("Zd [\\circ]");
1369 h1.Draw();
1370 h1.SetBit(kCanDelete);
1371
1372 TProfile *p1 = h1.ProfileX("_pfx", -1, 9999, "s");
1373 p1->SetLineColor(kBlue);
1374 p1->Draw("same");
1375 p1->SetBit(kCanDelete);
1376
1377 // ----------
1378
1379 c->cd(2);
1380 TH2D &h2=*(TH2D*)hist.Project3D("zy"); // Az
1381 h2.SetTitle(" Gear Ratio Azimuth [re/se] ");
1382 h2.SetXTitle("Zd [\\circ]");
1383 h2.Draw();
1384 h2.SetBit(kCanDelete);
1385
1386 TProfile *p2 = h2.ProfileX("_pfx", -1, 9999, "s");
1387 p2->SetLineColor(kBlue);
1388 p2->Draw("same");
1389 p2->SetBit(kCanDelete);
1390
1391 // ----------
1392
1393 c->cd(3);
1394
1395 TAxis &axe1 = *h1.GetXaxis();
1396
1397 TH1F f1("spreadzd", " Spread Zenith Distance ",
1398 axe1.GetNbins(), axe1.GetXmin(), axe1.GetXmax());
1399 f1.SetXTitle("Zd [\\circ]");
1400 for (int i=0; i<axe1.GetNbins(); i++)
1401 f1.SetBinError(i, p1->GetBinError(i));
1402 f1.SetLineColor(kRed);
1403 f1.SetStats(0);
1404 f1.DrawCopy();
1405
1406 c->cd(4);
1407
1408 // ----------
1409
1410 TAxis &axe2 = *h2.GetXaxis();
1411
1412 TH1F f2("spreadaz", " Spread Azimuth ",
1413 axe2.GetNbins(), axe2.GetXmin(), axe2.GetXmax());
1414 f2.SetXTitle("Az [\\circ]");
1415 for (int i=0; i<axe2.GetNbins(); i++)
1416 f2.SetBinError(i, p2->GetBinError(i));
1417 f2.SetLineColor(kRed);
1418 f2.SetStats(0);
1419 f2.DrawCopy();
1420
1421 // ----------
1422
1423 if (del)
1424 delete &hist;
1425}
1426
1427// --------------------------------------------------------------------------
1428//
1429// Start the work of the application:
1430//
1431// Start the Can-Network.
1432// Start the MCosy::TalkThread thread.
1433// turn on the gui update
1434//
1435void MCosy::Start()
1436{
1437 // Don't call this function twice!
1438 Network::Start();
1439
1440 CheckForError();
1441
1442 ReadConfig();
1443
1444 gLog << "- Starting TX Thread." << endl;
1445 fTTalk = new MTTalk(this);
1446
1447 gLog << "- Starting GUI update." << endl;
1448 fUpdateGui->TurnOn();
1449}
1450
1451// --------------------------------------------------------------------------
1452//
1453// Start the work of the application:
1454//
1455// Turn of the gui update
1456// stop the MCosy::TalkThread thread.
1457// Stop the network
1458//
1459void MCosy::Stop()
1460{
1461 gLog << inf << "- Stopping GUI update." << endl;
1462 fUpdateGui->TurnOff();
1463 gLog << inf << "- GUI Update stopped." << endl;
1464
1465 gLog << inf << "- Stopping TX Thread." << endl;
1466 delete fTTalk;
1467 gLog << inf << "- TX Thread stopped." << endl;
1468
1469 gLog << inf << "- Stopping CAN network." << endl;
1470 Network::Stop();
1471 gLog << inf << "- CAN network stopped." << endl;
1472
1473 gLog << inf << "- Stopping message queue." << endl;
1474 CancelThread();
1475 gLog << inf << "- Message queue stopped." << endl;
1476}
1477
1478// --------------------------------------------------------------------------
1479//
1480// Disable the synchronization by using a negative CAN Id for id2.
1481//
1482void MCosy::Constructor(Int_t id1, Int_t id2, Int_t id3,
1483 Int_t id4, Int_t id5, Int_t id6)
1484{
1485 //
1486 // Create Nodes
1487 //
1488 gLog << "- Setting up network." << endl;
1489
1490 fMac1=new Macs(id1, "Mac/Az");
1491 fMac2=new Macs(id3, "Mac/Zd");
1492 if (id2>=0)
1493 fMac3=new Macs(id2, "Mac/Az-Sync");
1494
1495 fZd1=new ShaftEncoder(id4, "SE/Zd1");
1496 fZd2=new ShaftEncoder(id5, "SE/Zd2");
1497 fAz =new ShaftEncoder(id6, "SE/Az");
1498
1499 fZd1->SetReport(fOutRep);
1500 fZd2->SetReport(fOutRep);
1501 fAz->SetReport(fOutRep);
1502
1503 fAz->SetMotor(fMac1);
1504 fZd1->SetMotor(fMac2);
1505 fZd2->SetMotor(fMac2);
1506
1507 gLog << "- Connecting devices to network." << endl;
1508
1509 //
1510 // Connect the devices to the network
1511 //
1512 SetNode(fMac1);
1513 SetNode(fMac2);
1514 if (id2>=0)
1515 SetNode(fMac3);
1516 SetNode(fZd1);
1517 SetNode(fZd2);
1518 SetNode(fAz);
1519
1520 //
1521 // Create Gui Event timer and Gui
1522 //
1523 gLog << "- Initializing GUI Timer." << endl;
1524 fUpdateGui = new TTimer(this, 100); // 100ms
1525
1526 gLog << "- Starting GUI." << endl;
1527 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
1528}
1529/*
1530void MCosy::ConstructorSE(Int_t id4, Int_t id5, Int_t id6)
1531{
1532 //
1533 // Create Nodes
1534 //
1535 gLog << "- Setting up network." << endl;
1536
1537 fZd1=new ShaftEncoder(id4, "SE/Zd1", gLog);
1538 fZd2=new ShaftEncoder(id5, "SE/Zd2", gLog);
1539 fAz =new ShaftEncoder(id6, "SE/Az", gLog);
1540
1541 gLog << "- Connecting devices to network." << endl;
1542
1543 //
1544 // Connect the devices to the network
1545 //
1546 SetNode(fZd1);
1547 SetNode(fZd2);
1548 SetNode(fAz);
1549
1550 //
1551 // Create Gui Event timer and Gui
1552 //
1553 gLog << "- Initializing GUI Timer." << endl;
1554 fUpdateGui = new TTimer(this, 100); // 100ms
1555
1556 gLog << "- Starting GUI." << endl;
1557 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
1558}
1559
1560void MCosy::ConstructorDemo()
1561{
1562 //
1563 // Create Nodes
1564 //
1565 gLog << "- Setting up network." << endl;
1566
1567 //
1568 // Create Gui Event timer and Gui
1569 //
1570 gLog << "- Initializing GUI Timer." << endl;
1571 fUpdateGui = new TTimer(this, 100); // 100ms
1572
1573 gLog << "- Starting GUI." << endl;
1574 fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1);
1575}
1576*/
1577
1578TString MCosy::GetFileName(const char *path, const char *name, const char *ext)
1579{
1580 // FIXME: Timeout missing
1581
1582 while (1)
1583 {
1584 MTime time(-1);
1585
1586 // This is the full qualified date which is part of the name
1587 const TString clock = time.GetStringFmt("%Y%m%d_%H%M%S");
1588
1589 // This gives the night in which the date belongs to
1590 time.SetMjd(TMath::Nint(time.GetMjd()));
1591
1592 const TString night = time.GetStringFmt("%Y_%m_%d");
1593
1594 const TString dir = Form("%s/%s", path, night.Data());
1595 const TString fname = Form("%s_%s.%s", name, clock.Data(), ext);
1596
1597 const TString full = Form("%s/%s", dir.Data(), fname.Data());
1598
1599 gSystem->mkdir(dir, kTRUE);
1600
1601 if (gSystem->AccessPathName(full, kFileExists))
1602 return full;
1603
1604 break;// !!!!!!!!!!!!!!!!!!!!!!!
1605
1606 usleep(1000);
1607 }
1608 return "";
1609}
1610
1611MCosy::MCosy()
1612: Network(), fObservatory(MObservatory::kMagic1), fStarguider(NULL),
1613fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), fMac3(0),
1614fBackground(kBgdNone), fTriggerDisplay(kFALSE), fStatus(MDriveCom::kStopped),
1615fOutTp(0), fOutRep(0)
1616{
1617 TEnv env(".cosyrc");
1618 const Int_t id1 = env.GetValue("Az_Id-MAC1", 1); //1
1619 const Int_t id2 = env.GetValue("Az_Id-MAC2", 2); //2
1620 const Int_t id3 = env.GetValue("Zd_Id-MAC", 3); //3
1621 const Int_t id4 = env.GetValue("Zd_Id-SE1", 4); //4
1622 const Int_t id5 = env.GetValue("Zd_Id-SE2", 5); //5
1623 const Int_t id6 = env.GetValue("Az_Id-SE", 6); //6
1624
1625 TString name = GetFileName("rep", "cosy", "rep");
1626 cout << "Open Repfile: " << name << endl;
1627 fOutRep = new MLog(name, kTRUE);
1628 *fOutRep << "[Drive Report File]" << endl;
1629 *fOutRep << "Version <cvs>" << endl;
1630 *fOutRep << "Date " << MTime(-1) << endl;
1631 *fOutRep << "[Reports]" << endl;
1632
1633/*
1634 gLog << "- Program in ";
1635 switch (mode)
1636 {
1637 case 0:
1638 gLog << "<<Standard mode>>" << endl;*/
1639 fBending.Load("bending.txt");
1640 Constructor(id1, id2, id3, id4, id5, id6);/*
1641 break;
1642 case 1:
1643 gLog << "<<SE mode>>" << endl;
1644 fBending.Load("bending.txt");
1645 ConstructorSE(id4, id5, id6);
1646 break;
1647 default:
1648 gLog << "<<Demo mode>>" << endl;
1649 ConstructorDemo();
1650 }
1651*/
1652 gLog.SetOutputGui(fWin->GetLog(), kTRUE);
1653
1654 fZd1->SetDisplay(fWin->GetLabel2());
1655 fZd2->SetDisplay(fWin->GetLabel3());
1656 fAz->SetDisplay(fWin->GetLabel1());
1657
1658 fCom = new MDriveCom(this, fOutRep);
1659// fCom->Start();
1660}
1661
1662void MCosy::TerminateApp()
1663{
1664 cout << "MCosy::TerminateApp()" << endl;
1665/*
1666 Int_t rc;
1667 TGMessageBox msg(this, gClient->GetRoot(),
1668 "Information",
1669 "Cosy is shutting down the system - this may take wa while!",
1670 kMBIconExclamation,
1671 kMBOK, //kMBClose
1672 &rc, 0);
1673*/
1674
1675 gLog.DisableOutputDevice(MLog::eGui);
1676 // FIXME: WHY DOES THIS CRASH THE APPLICATIOn WHILE TRAKING?
1677 // gLog.SetOutputGui(NULL, kFALSE);
1678
1679 gApplication->Terminate(0);
1680}
1681
1682MCosy::~MCosy()
1683{
1684 cout << "Deleting GUI timer." << endl;
1685 // FIXME: Wait until last Update was finished!!!
1686 delete fUpdateGui;
1687
1688 //fMutexGui.Lock();
1689
1690 // Now the files can safely be closed
1691 cout << "Closing output files." << endl;
1692 if (fOutTp)
1693 {
1694 *fOutTp << "END" << endl;
1695 delete fOutTp;
1696 }
1697 delete fOutRep;
1698
1699 cout << "Deleting CC communication." << endl;
1700 delete fCom;
1701
1702 cout << "Deleting Nodes." << endl;
1703 fZd1->SetReport(0);
1704 fZd2->SetReport(0);
1705 fAz->SetReport(0);
1706
1707 delete fAz;
1708 delete fZd1;
1709 delete fZd2;
1710 delete fMac1;
1711 delete fMac2;
1712 if (fMac3)
1713 delete fMac3;
1714
1715 cout << "Deleting MGCosy." << endl;
1716
1717 gLog.DisableOutputDevice(MLog::eGui);
1718
1719 delete fWin;
1720
1721 cout << "MGCosy destructed." << endl;
1722}
Note: See TracBrowser for help on using the repository browser.