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

Last change on this file since 1111 was 1111, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 29.1 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#define GEAR_RATIO_ALT 75.55 // 75.25 VERY IMPORTANT! unit=RE/SE
29#define GEAR_RATIO_AZ 179.8 // VERY IMPORTANT! unit=RE/SE
30
31const XY kGearRatio(GEAR_RATIO_ALT, GEAR_RATIO_AZ);
32const XY kGearRatio2(GEAR_RATIO_ALT*16384.0/360.0, GEAR_RATIO_AZ*16384.0/360.0);
33
34double Rad2SE(double rad)
35{
36 return 16384.0/k2Pi*rad;
37}
38
39double Rad2ZdRE(double rad)
40{
41 return 16384.0/k2Pi*rad*kGearRatio.X();
42}
43
44double Rad2AzRE(double rad)
45{
46 return 16384.0/k2Pi*rad*kGearRatio.Y();
47}
48
49double Deg2ZdRE(double rad)
50{
51 return rad*kGearRatio2.X();
52}
53
54double Deg2AzRE(double rad)
55{
56 return rad*kGearRatio2.Y();
57}
58
59ZdAz MCosy::CorrectTarget(const ZdAz &src, const ZdAz &dst)
60{
61 // CorrectTarget [se]
62
63 // src [se]
64 // dst [rad]
65
66 // fAltMax = 70
67 // fAltMin = -105/110
68 // fAzMin = -355
69 // fAzMax = 355
70
71 ZdAz source = src * 360.0/16384.0;
72 ZdAz dest = dst * kRad2Deg;
73
74 if (dest.Zd()>-1e-6 && dest.Zd()<1e-6)
75 return dst*(16384.0/k2Pi);
76
77 const float fZdMin = -67;
78 const float fZdMax = 67;
79 const float fAzMin = -29;
80 const float fAzMax = 423;
81
82 //
83 // This corrects to target for the shortest distance, not for the fastest move!
84 //
85 ZdAz s = source-dest;
86
87 float min = s.Sqr();
88
89 //
90 // Is it enought to search inside one revolution?
91 //
92 ZdAz ret = dest;
93
94 for (int i=-5; i<5+1; i++)
95 {
96 const ZdAz p(i%2 ? -dest.Zd() : dest.Zd(), dest.Az() - i*180);
97
98 //
99 // Range Check
100 //
101 if (p.Zd()<fZdMin || p.Zd()>fZdMax)
102 continue;
103
104 if (p.Az()<fAzMin || p.Az()>fAzMax)
105 continue;
106
107 //
108 // Calculate distance
109 //
110 s = source-p;
111
112 const float dist = s.Sqr();
113
114 if (dist > min)
115 continue;
116
117 //
118 // New shortest distance
119 //
120 ret = p;
121 min = dist;
122 }
123 return ret*(16384.0/360.0);
124}
125
126// --------------------------------------------------------------------------
127//
128// GetSePos, reads the Shaftencoder positions from the Can-drivers
129// for the shaftencoders. The two shaft encoders at the elevation axis
130// are avaraged. The values are returned as a ZdAz object.
131//
132// The positions are alway up-to-date because the shaftencoders are
133// sending all changes immediatly.
134//
135ZdAz MCosy::GetSePos()
136{
137 //
138 // Get the values
139 //
140 const int p0 = fZd1->GetPos();
141 const int p1 = fZd2->GetPos();
142 const int p2 = fAz->GetPos();
143
144 const int a0 = p0; //p0>8192?p0-16384:p0;
145 const int a1 = p1; //p1>8192?p1-16384:p1;
146 const int a2 = p2; //p2>8192?p2-16384:p2;
147
148 //
149 // interpolate shaft encoder positions
150 //
151 const float a = (float)(a0-a1)/2;
152
153 //
154 // calculate 'regelabweichung'
155 //
156 return ZdAz(a, a2);
157}
158
159// --------------------------------------------------------------------------
160//
161// request the current positions from the rotary encoders.
162// use GetRePos to get the psotions. If the request fails the function
163// returns kFALSE, otherwise kTRUE
164//
165Bool_t MCosy::RequestRePos()
166{
167 //
168 // Send request
169 //
170 fMac2->RequestSDO(0x6004);
171 fMac1->RequestSDO(0x6004);
172
173 //
174 // Wait until the objects are received.
175 //
176 WaitForSdos();
177
178 //
179 // If waitng was not interrupted everything is ok. return.
180 //
181 if (!StopWaitingForSDO())
182 return kTRUE;
183
184 //
185 // If the waiting was interrupted due to a network error,
186 // print some logging message.
187 //
188 if (HasError())
189 lout << "Error #6004 (requesting re pos from Macs) happened." << endl;
190
191 return kFALSE;
192}
193
194// --------------------------------------------------------------------------
195//
196// reads the Rotary encoder positions from the last request of the Macs.
197//
198// The positions are returned as a ZdAz object. Use RequestRePos to request
199// the current positions first.
200//
201ZdAz MCosy::GetRePos()
202{
203 return ZdAz(fMac2->GetPos(), fMac1->GetPos());
204}
205
206// --------------------------------------------------------------------------
207//
208// reads the Rotary encoder positions from the Macs.
209//
210// The positions are returned as a ZdAz object. The positions are the ones
211// which are send as PDOs to the computer. This is done at a given
212// frequency. Which means, that this positions are not ought to be
213// up-to-date.
214//
215ZdAz MCosy::GetRePosPdo()
216{
217 return ZdAz(fMac2->GetPdoPos(), fMac1->GetPdoPos());
218}
219
220// --------------------------------------------------------------------------
221//
222// set the velocity and accelerations for position maneuvers.
223//
224// The acceleratin is set as given (in percent of maximum).
225// The velocity is given in percent, depending on the ratio (<1 or >1)
226// one of the axis becomes a slower velocity. This is used for maneuvers
227// in which both axis are moved synchromously and should reach their
228// target position at the same time.
229//
230void MCosy::SetPosVelocity(const Float_t ratio, Float_t vel, Float_t acc)
231{
232 //
233 // Set velocities
234 //
235 const int vr = fMac1->GetVelRes();
236
237 vel *= vr;
238 acc *= vr;
239
240 if (ratio <1)
241 {
242 fMac1->SetVelocity(vel);
243 fMac1->SetAcceleration(acc);
244 fMac1->SetDeceleration(acc);
245
246 fMac2->SetVelocity(vel*ratio);
247 fMac2->SetAcceleration(acc*ratio);
248 fMac2->SetDeceleration(acc*ratio);
249 }
250 else
251 {
252 fMac1->SetVelocity(vel/ratio);
253 fMac1->SetAcceleration(acc/ratio);
254 fMac1->SetDeceleration(acc/ratio);
255
256 fMac2->SetVelocity(vel);
257 fMac2->SetAcceleration(acc);
258 fMac2->SetDeceleration(acc);
259 }
260}
261
262// --------------------------------------------------------------------------
263//
264// Does a relative positioning.
265//
266// The steps to move are given in a ZdAz object relative to the current
267// position. The coordinates are given in Roteryencoder steps.
268// Axis 1 is moved only if axe1==kTRUE, Axis 2 is moved only
269// if Axis 2==kTRUE. The function waits for the movement to be finished.
270//
271void MCosy::DoRelPos(const ZdAz &rd, const Bool_t axe1, const Bool_t axe2)
272{
273 SetStatus(MCosy::kMoving);
274
275 if (axe1) fMac2->StartRelPos(rd.Zd());
276 if (axe2) fMac1->StartRelPos(rd.Az());
277
278 cout << "Waiting for positioning..." << flush;
279
280 WaitForEndMovement();
281
282 cout << "done." << endl;
283}
284
285// --------------------------------------------------------------------------
286//
287// check for a break-signal (from the msgqueue) and errors.
288//
289int MCosy::StopWaitingForSDO() const
290{
291 return Break() || HasError();
292}
293
294// --------------------------------------------------------------------------
295//
296// Waits for a movement to become finished.
297//
298// First waits for all peding Sdos, then waits until both motors are stopped
299// or waiting for SDOs was stopped (either by an error or by Break)
300//
301void MCosy::WaitForEndMovement()
302{
303 WaitForSdos();
304
305 while ((fMac1->IsPositioning() || fMac2->IsPositioning()) && !StopWaitingForSDO())
306 usleep(1);
307}
308
309// --------------------------------------------------------------------------
310//
311// Check for an error...
312//
313// This is ment for usage after the Action: All Motors Stop.
314//
315void MCosy::CheckForError()
316{
317 //
318 // Check all Can-Nodes for an Error. If there is no error the motor
319 // status is set to stopped.
320 //
321 if (!HasError())
322 {
323 SetStatus(MCosy::kStopped);
324 return;
325 }
326
327 //
328 // If there is an error, the error status is set to Error.
329 //
330 SetStatus(MCosy::kError);
331
332 //
333 // No try to handle the error.
334 //
335 fMac1->HandleError();
336 fMac2->HandleError();
337
338 //
339 // If the error couldn't get solved return
340 //
341 if (HasError())
342 return;
343
344 //
345 // Set motor status to stopped
346 //
347 SetStatus(MCosy::kStopped);
348}
349
350// --------------------------------------------------------------------------
351//
352// Move the telescope to the given position. The position must be given in
353// a ZdAz object in rad.
354//
355// The first positioning is done absolutely. If we didn't reach the
356// correct psotion we try to correct for this by 10 relative position
357// maneuvers. If this doesn't help positioning failed.
358//
359// As a reference the shaftencoder values are used.
360//
361int MCosy::SetPosition(const ZdAz &dst) // [rad]
362{
363 // FIXME: Correct by fOffset ?
364
365 //
366 // Calculate new target position (shortest distance to go)
367 //
368 const ZdAz src = GetSePos();
369 const ZdAz dest = CorrectTarget(src, dst);
370
371 lout << "Positioning to Target..." << endl;
372 //cout << "Source Zd: " << src.Zd() << "se Az:" << src.Az() << "se" << endl;
373 //cout << "Destination Zd: " << Rad2SE(dst.Zd()) << "se Az:" << Rad2SE(dst.Az()) << "se" << endl;
374 //cout << "Shortest Dest Zd: " << dest.Zd() << "se Az:" << dest.Az() << "se" << endl;
375
376 for (int i=0; i<10 && !StopWaitingForSDO(); i++)
377 {
378 //
379 // Get Shaft Encoder Positions
380 //
381 const ZdAz p=GetSePos();
382
383 //
384 // calculate control deviation and rounded cd
385 //
386 ZdAz rd = dest-p; // [se]
387
388 ZdAz cd = rd; // [se]
389 cd.Round();
390
391 //
392 // Check if there is a control deviation on the axis
393 //
394 const Bool_t cdzd = (int)cd.Zd() ? kTRUE : kFALSE;
395 const Bool_t cdaz = (int)cd.Az() ? kTRUE : kFALSE;
396
397 //
398 // check if we reached the correct position already
399 //
400 if (!cdzd && !cdaz)
401 {
402 lout << "Positioning done with " << i << "manuvers." << endl;
403 return TRUE;
404 }
405
406 //
407 // change units from se to re
408 //
409 rd *= kGearRatio; // [re]
410
411 //
412 // Initialize Velocities so that we reach both positions
413 // at the same time
414 //
415 if (i)
416 SetPosVelocity(1.0, 0.1, 0.1);
417 else
418 SetPosVelocity(fabs(rd.Ratio()), 0.9, 0.5);
419
420 rd.Round();
421
422 /*
423 cout << " + " << cdzd << " " << cdaz << endl;
424 cout << " + APOS: Zd=" << setw(6) << p.Zd() << "se Az=" << setw(6) << p.Az() << "se" << endl;
425 cout << " + dZd=" << setw(6) << cd.Zd() << "se dAz=" << setw(6) << cd.Az() << "se" << endl;
426 cout << " + dZd=" << setw(6) << rd.Zd() << "re dAz=" << setw(6) << rd.Az() << "re" << endl;
427 */
428
429 //
430 // repositioning (relative)
431 //
432 DoRelPos(rd, cdzd, cdaz);
433 }
434
435 StopMovement();
436 lout << "Warning: Requested position not reached." << endl;
437 return FALSE;
438}
439
440// --------------------------------------------------------------------------
441//
442// Sets the tracking velocity
443//
444// The velocities are given in a ZdAz object in re/min. Return kTRUE
445// in case of success, kFALSE in case of failure.
446//
447Bool_t MCosy::SetVelocity(ZdAz v)
448{
449 //
450 // Send the new velocities for both axes.
451 //
452 fMac2->SendSDO(0x3006, 1, (LWORD_t)v.Zd()); // SetRpmVelocity [re/min]
453 fMac1->SendSDO(0x3006, 1, (LWORD_t)v.Az()); // SetRpmVelocity [re/min]
454
455 //
456 // Wait for the objects to be OKed.
457 //
458 WaitForSdos();
459
460 //
461 // If the waiting for the objects wasn't interrupted return kTRUE
462 //
463 if (!StopWaitingForSDO())
464 return kTRUE;
465
466 //
467 // print a message if the interruption was due to a Can-node Error
468 //
469 if (HasError())
470 lout << "Error #3006 (setting velocity of Macs) happened." << endl;
471
472 return kFALSE;
473}
474
475// --------------------------------------------------------------------------
476//
477// Initializes Tracking mode
478//
479// Initializes the accelerations of both axes with 90% of the maximum
480// acceleration. Set the status for moving and tracking and starts thr
481// revolution mode.
482//
483void MCosy::InitTracking()
484{
485 //
486 // Start revolution mode
487 //
488 fMac2->SetAcceleration(0.90*fMac2->GetVelRes());
489 fMac2->SetDeceleration(0.90*fMac2->GetVelRes());
490
491 fMac1->SetAcceleration(0.90*fMac1->GetVelRes());
492 fMac1->SetDeceleration(0.90*fMac1->GetVelRes());
493
494 SetStatus(MCosy::kMoving | MCosy::kTracking);
495
496 fMac2->SetRpmMode(TRUE);
497 fMac1->SetRpmMode(TRUE);
498}
499
500// --------------------------------------------------------------------------
501//
502// Limits the speed.
503//
504// This function should work as a limiter. If a tracking error is too large
505// to be corrected fast enough we would get enormous velocities. These
506// velocities are limited to the maximum velocity.
507//
508void MCosy::LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const
509{
510 //
511 // How to limit the speed. If the wind comes and blowes
512 // we cannot forbid changing of the sign. But on the other hand
513 // we don't want fast changes!
514 //
515
516 ULong_t vrzd = fMac1->GetVelRes();
517 ULong_t vraz = fMac2->GetVelRes();
518
519#define sgn(x) (x<0?-1:1)
520
521 const Float_t limit = 0.25;
522
523 if (sgn(vt->Az()) != sgn(vcalc.Az()) &&
524 fabs(vt->Az()) < limit*fabs(vcalc.Az()))
525 vt->Az(0);
526 else
527 if (fabs(vt->Az()) > 0.9*vraz)
528 {
529 lout << "Warning: Azimuth speed limit exceeded. Limiting speed to 90% max." << endl;
530 vt->Az(0.9*vraz*sgn(vt->Az()));
531 }
532
533 if (sgn(vt->Zd()) != sgn(vcalc.Zd()) &&
534 fabs(vt->Zd()) < limit*fabs(vcalc.Zd()))
535 vt->Zd(0);
536 else
537 if (fabs(vt->Zd()) > 0.9*vrzd)
538 {
539 lout << "Warning: Altitude speed limit exceeded. Limiting speed to 90% max." << endl;
540 vt->Zd(0.9*vrzd*sgn(vt->Zd()));
541 }
542}
543
544void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad]
545{
546 SlaStars sla;
547
548 //
549 // Position to actual position
550 //
551 sla.SetMjd2Now();
552 ZdAz dest = sla.CalcZdAz(dst);
553
554 if (!SetPosition(dest))
555 {
556 lout << "Error: Cannot start tracking, positioning failed." << endl;
557 return;
558 }
559
560 //
561 // calculate offset from present se position
562 //
563 const ZdAz sepos = GetSePos()*kGearRatio;
564
565 if (!RequestRePos())
566 return;
567
568 //
569 // Estimate Offset before starting to track
570 //
571 fOffset = sepos-GetRePos();
572
573 /*
574 cout << "Sepos: " << sepos.Zd() << "re, " << sepos.Az() << "re" << endl;
575 cout << "Repos: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
576 cout << "Offset: " << fOffset.Zd() << "re, " << fOffset.Az() << "re" << endl;
577 */
578
579 //
580 // Init accelerations and Rpm Mode
581 //
582 InitTracking();
583
584 lout << "Start tracking:";
585 lout << " Ra: " << Rad2Deg(dst.Ra()) << "\xb0 ";
586 lout << "Dec: " << Rad2Deg(dst.Dec()) << "\xb0" << endl;
587
588 //
589 // Initialize Tracker (slalib or starguider)
590 //
591 fRaDec = dst;
592 fTracking = kTRUE;
593
594 ofstream fout("log/cosy.pos");
595 fout << "Tracking:";
596 fout << " Ra: " << Rad2Deg(dst.Ra()) << "\x9c ";
597 fout << "Dec: " << Rad2Deg(dst.Dec()) << "\x9c" << endl << endl;
598 fout << " Mjd/10ms V/re/min/4" << endl;
599
600 //
601 // We want to reach the theoretical position exactly in about 0.5s
602 //
603 const float dt = 1; // 1 second
604 while (!StopWaitingForSDO())
605 {
606 //
607 // Request Target position for this moment
608 //
609 sla.Now();
610
611 //
612 // Request theoretical Position for a time in the future (To+dt) from CPU
613 //
614 sla.SetMjd(sla.CalcMjd()+dt/(60*60*24));
615 dest = CorrectTarget(GetSePos(), sla.CalcZdAz(dst)); // [se]
616
617 ZdAz vcalc = sla.GetApproxVel(dst) * kGearRatio2*4./60.; // [re/min]
618
619 //
620 // Request absolute position of rotary encoder from Macs
621 //
622 if (!RequestRePos())
623 break;
624
625 //
626 // distance between (To+dt) and To [re]
627 // position time difference < 5usec
628 // fOffset does the synchronization between the
629 // Shaft- and the rotary encoders
630 //
631 dest *= kGearRatio; // [re]
632 dest -= GetRePos() + fOffset;
633
634 //
635 // Velocity to go [re/min] to reach the right position at time t+dt
636 // correct for the duration of RaDec2AltAz
637 //
638 const ZdAz v = dest*60.0/(dt-(fMac2->GetTime()-sla));
639
640 //
641 // calculate real velocity of future [re/min]
642 // believing the Macs manual '/4' shouldn't be necessary, but it is.
643 //
644 ZdAz vt = v/4;
645 LimitSpeed(&vt, vcalc);
646 vt.Round();
647
648 //
649 // check if the drive is fast enough to follow the star
650 //
651 if (vt.Zd()>.9*fMac1->GetVelRes() || vt.Az()>.9*fMac2->GetVelRes())
652 {
653 lout << "Error: Tracking speed faster than 90% of possible maximum velocity." << endl;
654 break;
655 }
656
657 //
658 // Set theoretical velocity (as early after calculation as possible)
659 // Maybe we should attenuate the changes
660 //
661 if (!SetVelocity(vt))
662 break;
663
664 //
665 // Now do 'unnecessary' things
666 //
667 fVelocity = vt/kGearRatio2*4;
668
669 const double mjd = fMac2->GetMjd();
670 fout << setprecision(15) << setw(17) << mjd*60.*60.*24. << " ";
671 fout << setw(4) << vt.Zd() << " ";
672 fout << setw(4) << vt.Az() << endl;
673 //
674 // FIXME? Calculate an accuracy for the tracking system?
675 // How good do we reach the calculated position in 'real'
676 // re valus?
677 //
678
679
680 //
681 // Update speed as often as possible.
682 // make sure, that dt is around 10 times larger than the
683 // update time
684 //
685 // usleep(50000); // 0.05s
686 }
687
688 fTracking = kFALSE;
689 StopMovement();
690 lout << "Tracking stopped." << endl;
691}
692
693// --------------------------------------------------------------------------
694//
695// Stops the movement of both motors.
696//
697// Sets the status to stopping. Sets the deceleration to 50% of the maximum.
698// stops. Quits the revolution mode and wait for the end of the movement.
699//
700void MCosy::StopMovement()
701{
702 //
703 // Set status to stopped
704 //
705 SetStatus(MCosy::kStopping);
706
707 //
708 // set deceleration to 50%
709 //
710 cout << "Stopping positioning..." << endl;
711 fMac1->SetDeceleration(0.5*fMac1->GetVelRes());
712 fMac2->SetDeceleration(0.5*fMac2->GetVelRes());
713
714 //
715 // Stop revolution mode (movement)
716 //
717 cout << "Stoping possibleRPM mode..." << endl;
718 fMac1->SetRpmMode(FALSE);
719 fMac2->SetRpmMode(FALSE);
720
721 //
722 // Wait for the movement to really be finished.
723 //
724 cout << "Waiting for silence..." << endl;
725 WaitForEndMovement();
726
727 //
728 // Check whether everything works fine.
729 //
730 CheckForError();
731 cout << "Movement stopped." << endl;
732}
733
734void *MCosy::Proc(int msg, void *mp)
735{
736 switch (msg)
737 {
738 case WM_WAIT:
739 cout << "Wait for execution of Proc(WM_*, ): done." << endl;
740 return NULL;
741
742 case WM_STOP:
743 StopMovement();
744 return NULL;
745
746 case WM_PRESET:
747 cout << "WM_Preset: start." << endl;
748 fZd1->SetPreset();
749 fZd2->SetPreset();
750 fAz->SetPreset();
751 cout << "WM_Preset: done. (return 0xaffe)" << endl;
752 return (void*)0xaffe;
753
754 case WM_POLARIS:
755 {
756 cout << "WM_Polaris: start." << endl;
757 SlaStars sla;
758 sla.SetMjd2Now();
759
760 RaDec rd(37.94, 89.2644);
761 ZdAz za=sla.CalcZdAz(rd*kDeg2Rad)*16384.0/k2Pi;
762
763 cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl;
764
765 ZdAz sepos = GetSePos();
766 cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl;
767
768 fZd1->SetPreset(za.Zd());
769 fZd2->SetPreset(-za.Zd());
770 fAz->SetPreset(za.Az());
771
772 cout << "WM_Polaris: done. (return 0xaffe)" << endl;
773 }
774 return (void*)0xaffe;
775
776 case WM_POSITION:
777 cout << "WM_Position: start." << endl;
778 {
779 ZdAz dest = *((ZdAz*)mp);
780
781 SetPosition(dest*kDeg2Rad);
782 }
783 cout << "WM_Position: done. (return 0x7777)" << endl;
784 return (void*)0x7777;
785
786 case WM_TRACK:
787 cout << "WM_Track: START" << endl;
788 {
789 RaDec dest = *((RaDec*)mp);
790 TrackPosition(dest*kDeg2Rad);
791 }
792 cout << "WM_Track: done. (return 0x8888)" << endl;
793 return (void*)0x8888;
794
795 case WM_QUIT:
796 cout << "WM_Quit: now." << endl;
797 TerminateApp();
798 cout << "WM_Quit: done." << endl;
799 return (void*)0x9999;
800 }
801 cout << "Unknown Msg" << endl;
802 return (void*)0xffffffff;
803}
804
805void *MTTalk::Thread()
806{
807 fCosy->TalkThread();
808 return NULL;
809}
810
811void MCosy::TalkThread()
812{
813 //
814 // Start the Network
815 //
816 cout << "Reading configuration file..." << flush;
817 TEnv env(".cosyrc");
818 cout << "done." << endl;
819
820 const int res = fMac3->GetVelRes();
821
822 fMac3->SetVelocity(res);
823 fMac3->SetAcceleration(res);
824 fMac3->SetDeceleration(res);
825
826 fMac3->StartPosSync();
827
828 cout << "Going Home..." << endl;
829 fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100));
830 fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100));
831 PostMsg(WM_PRESET, 0, 0);
832 PostMsg(WM_WAIT, 0, 0);
833
834 fMac1->ReqPos();
835 fMac2->ReqPos();
836
837 //const ZdAz repos=GetRePos();
838 //cout << "APOS: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
839
840 /*
841 cout << Deg2AzRE(env.GetValue("MinAz[Deg]", -1.0)) << " < Az < "
842 << Deg2AzRE(env.GetValue("MaxAz[Deg]", +1.0)) << "RE" << endl;
843 cout << env.GetValue("MinAz[Deg]", -1.0) << " < Az < "
844 << env.GetValue("MaxAz[Deg]", +1.0) << kDEG << endl;
845 cout << Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)) << "RE < Zd < "
846 << Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)) << "RE" << endl;
847 */
848
849 cout << "Setting up software endswitch..." << flush;
850 fMac1->SetNegEndswitch(Deg2AzRE(env.GetValue("Az_Min[Deg]", -1.0)));
851 fMac1->SetPosEndswitch(Deg2AzRE(env.GetValue("Az_Max[Deg]", +1.0)));
852
853 fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("Zd_Min[Deg]", -1.0)));
854 fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("Zd_Max[Deg]", +1.0)));
855 cout << "done." << endl;
856
857 fMac1->EnableTimeout(kTRUE, 500);
858 fMac2->EnableTimeout(kTRUE, 500);
859
860/*
861 fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)));
862 fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)));
863*/
864// fMac3->StartVelSync();
865/*
866 cout << "PostMsg(WM_PRESET)" << endl;
867 void *rc =
868 cout << hex << "WM_PRESET: ret=" << rc << endl;
869
870 RaDec dest = RaDec(45.0, 30.0)*D2PI/360.0;
871
872 cout << "PostMsg(WM_TRACK)" << endl;
873 cout << sizeof(RaDec) << "==" << sizeof(dest) << endl;
874 rc=PostMsg(WM_TRACK, &dest, sizeof(dest));
875 cout << "DEST killed." << endl;
876*/
877 // AltAz dest = AltAz(45.0, 30.0);
878 // double ra, dec;
879 // slaDaf2r( 71, 0, 0, &ra, &status); // 0 WARNING: RANGE
880 // slaDaf2r( 89, 0, 0, &dec, &status); // 49
881 // cout << "Start tracking: Ra: " << Rad2Deg(ra) << kDEG << " Dec: " << Rad2Deg(dec) << kDEG << endl;
882
883 // dest = AltAz(-46.0, 210);
884 // SetPosition(dest);
885
886 SlaStars sla;
887 while (1)
888 {
889 //
890 // wait until a tracking session is started
891 //
892 while (!fTracking && !fTTalk->HasStopFlag())
893 usleep(1);
894
895 if (fTTalk->HasStopFlag())
896 break;
897
898 ofstream fout("log/cosy.err");
899 fout << "Tracking:";
900 fout << " Ra: " << Rad2Deg(fRaDec.Ra()) << "\x9c ";
901 fout << "Dec: " << Rad2Deg(fRaDec.Dec()) << "\x9c" << endl << endl;
902 fout << " MjdZd/10ms ErrZd/re";
903 fout << " MjdAz/10ms ErrAd/re" << endl;
904
905 ZdAz old;
906 ZdAz ist;
907
908 ZdAz sollzd;
909 ZdAz sollaz;
910
911 ZdAz istre = -fOffset; // [re]
912 ZdAz time;
913
914 //
915 // only update fTrackingError while tracking
916 //
917 while (fTracking && !fTTalk->HasStopFlag())
918 {
919 //
920 // Make changes (eg wind) smoother - attenuation of control function
921 //
922 const float weight = 1.; //0.3;
923
924 ZdAz offset(fOffset.Zd()*(1.-weight)+(ist.Zd()*kGearRatio.X()-istre.Zd())*weight,
925 fOffset.Az()*(1.-weight)+(ist.Az()*kGearRatio.Y()-istre.Az())*weight);
926
927 fOffset = offset;
928
929 //
930 // This is the time constant which defines how fast
931 // you correct for external influences (like wind)
932 //
933 bool phca1;
934 bool phca2;
935 bool phcaz;
936
937 do
938 {
939 phca1 = fZd1->PosHasChanged();
940 phca2 = fZd2->PosHasChanged();
941 phcaz = fAz->PosHasChanged();
942 usleep(1);
943 } while (!phca1 && !phca2 && !phcaz);
944 //---usleep(100000); // 0.1s
945
946 //
947 // get position, where we are
948 //
949 old = ist;
950 ist = GetSePos(); // [se]
951
952 //
953 // if the position didn't change continue
954 //
955 /*---
956 if ((int)ist.Zd() == (int)old.Zd() &&
957 (int)ist.Az() == (int)old.Az())
958 continue;
959 */
960 istre = GetRePosPdo();
961
962 //
963 // Get time from last shaftencoder position change (position: ist)
964 // FIXME: I cannot take the avarage
965 //
966 time.Zd((fZd1->GetMjd()+fZd2->GetMjd())/2.0);
967 time.Az(fAz->GetMjd());
968
969 //
970 // if Shaftencoder changed position
971 // calculate were we should be
972 //
973 if (phca1 || phca2 /*(int)ist.Zd() != (int)old.Zd()*/)
974 {
975 sla.SetMjd(time.Zd());
976 sollzd = CorrectTarget(ist, sla.CalcZdAz(fRaDec)); // [se]
977 }
978
979 if (phcaz /*(int)ist.Az() != (int)old.Az()*/)
980 {
981 sla.SetMjd(time.Az());
982 sollaz = CorrectTarget(ist, sla.CalcZdAz(fRaDec)); // [se]
983 }
984
985 fTrackingError.Set((ist.Zd()-sollzd.Zd())*kGearRatio.X(),
986 (ist.Az()-sollaz.Az())*kGearRatio.Y());
987
988 fout << setprecision(15) << setw(17) << time.Zd()*60.*60.*24. << " ";
989 fout << setprecision(5) << setw(7) << fTrackingError.Zd() << " ";
990 fout << setprecision(15) << setw(17) << time.Az()*60.*60.*24. << " ";
991 fout << setprecision(5) << setw(7) << fTrackingError.Az() << endl;
992 }
993
994 fout << endl << endl;
995 }
996}
997
998Bool_t MCosy::HandleTimer(TTimer *t)
999{
1000 //
1001 // Update Gui, foremer MTGui.
1002 //
1003 fZd1->DisplayVal();
1004 fZd2->DisplayVal();
1005 fAz->DisplayVal();
1006
1007 ZdAz ist = GetSePos()*(360.0/16384.0); // [se]
1008
1009 fWin->Update(ist, fTrackingError/kGearRatio2,
1010 fVelocity, fOffset/*/kGearRatio2*/,
1011 fStatus);
1012
1013 return kTRUE;
1014}
1015
1016
1017// --------------------------------------------------------------------------
1018//
1019// Start the work of the application:
1020//
1021// Start the Can-Network.
1022// Start the MCosy::TalkThread thread.
1023// turn on the gui update
1024//
1025void MCosy::Start()
1026{
1027 // Don't call this function twice!
1028 Network::Start();
1029
1030 lout << "- Starting TX Thread." << endl;
1031 fTTalk = new MTTalk(this);
1032
1033 lout << "- Starting GUI update." << endl;
1034 fUpdateGui->TurnOn();
1035 // fTGui = new MTGui(this);
1036}
1037
1038// --------------------------------------------------------------------------
1039//
1040// Start the work of the application:
1041//
1042// Turn of the gui update
1043// stop the MCosy::TalkThread thread.
1044// Stop the network
1045//
1046void MCosy::Stop()
1047{
1048
1049 lout << "- Stopping GUI update." << endl;
1050 fUpdateGui->TurnOff();
1051 lout << "- GUI Update stopped." << endl;
1052
1053 delete fTTalk;
1054 lout << "- TX Thread stopped." << endl;
1055
1056 Network::Stop();
1057}
1058
1059MCosy::MCosy(const char *dev, const int baud, MLog &out)
1060: Network(dev, baud, out), fTracking(kFALSE)
1061{
1062 //
1063 // Create Nodes
1064 //
1065 fMac1=new Macs(1, "Mac.1/Az", lout);
1066 fMac2=new Macs(2, "Mac.2/Zd", lout);
1067 fMac3=new Macs(3, "Mac.3/Az-Sync", lout);
1068
1069 fZd1=new ShaftEncoder(4, "SE.4/Zd1", lout);
1070 fZd2=new ShaftEncoder(5, "SE.5/Zd2", lout);
1071 fAz =new ShaftEncoder(6, "SE.6/Az", lout);
1072
1073 //
1074 // Connect the devices to the network
1075 //
1076 SetNode(fMac1);
1077 SetNode(fMac2);
1078 SetNode(fMac3);
1079 SetNode(fZd1);
1080 SetNode(fZd2);
1081 SetNode(fAz);
1082
1083 //
1084 // Create Gui Event timer and Gui
1085 //
1086 fUpdateGui = new TTimer(this, 100); // 100ms
1087
1088 fWin=new MGCosy(this, gClient->GetRoot(), 1, 1);
1089
1090 fAz->SetDisplay(fWin->GetLabel1());
1091 fZd1->SetDisplay(fWin->GetLabel2());
1092 fZd2->SetDisplay(fWin->GetLabel3());
1093
1094 lout.SetOutputGui(fWin->GetLog(), kTRUE);
1095}
1096
1097void MCosy::TerminateApp()
1098{
1099 cout << "MCosy::TerminateApp()" << endl;
1100/*
1101 Int_t rc;
1102 TGMessageBox msg(this, gClient->GetRoot(),
1103 "Information",
1104 "Cosy is shutting down the system - this may take wa while!",
1105 kMBIconExclamation,
1106 kMBOK, //kMBClose
1107 &rc, 0);
1108*/
1109
1110 gApplication->Terminate(0);
1111}
1112
1113MCosy::~MCosy()
1114{
1115 cout << "Deleting GUI timer." << endl;
1116
1117 delete fUpdateGui;
1118
1119 cout << "Deleting Nodes." << endl;
1120
1121 delete fAz;
1122 delete fZd2;
1123 delete fZd1;
1124 delete fMac1;
1125 delete fMac2;
1126 delete fMac3;
1127
1128 cout << "Deleting MGCosy." << endl;
1129
1130 lout.DisableOutputDevice(MLog::eGui);
1131
1132 delete fWin;
1133
1134 cout << "MGCosy destructed." << endl;
1135}
Note: See TracBrowser for help on using the repository browser.