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

Last change on this file since 1275 was 1275, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 30.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 while requesting re pos from Macs (SDO #6004)" << 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 in " << i << (i==1?" step.":" steps.") << endl;
403 SetStatus(MCosy::kStopped);
404 return TRUE;
405 }
406
407 //
408 // change units from se to re
409 //
410 rd *= kGearRatio; // [re]
411
412 //
413 // Initialize Velocities so that we reach both positions
414 // at the same time
415 //
416 if (i)
417 SetPosVelocity(1.0, 0.1, 0.1);
418 else
419 SetPosVelocity(fabs(rd.Ratio()), 0.9, 0.5);
420
421 rd.Round();
422
423 /*
424 cout << " + " << cdzd << " " << cdaz << endl;
425 cout << " + APOS: Zd=" << setw(6) << p.Zd() << "se Az=" << setw(6) << p.Az() << "se" << endl;
426 cout << " + dZd=" << setw(6) << cd.Zd() << "se dAz=" << setw(6) << cd.Az() << "se" << endl;
427 cout << " + dZd=" << setw(6) << rd.Zd() << "re dAz=" << setw(6) << rd.Az() << "re" << endl;
428 */
429
430 //
431 // repositioning (relative)
432 //
433 DoRelPos(rd, cdzd, cdaz);
434 }
435
436 StopMovement();
437 lout << "Warning: Requested position not reached." << endl;
438 return FALSE;
439}
440
441// --------------------------------------------------------------------------
442//
443// Sets the tracking velocity
444//
445// The velocities are given in a ZdAz object in re/min. Return kTRUE
446// in case of success, kFALSE in case of failure.
447//
448Bool_t MCosy::SetVelocity(ZdAz v)
449{
450 //
451 // Send the new velocities for both axes.
452 //
453 fMac2->SendSDO(0x3006, 1, (LWORD_t)v.Zd()); // SetRpmVelocity [re/min]
454 fMac1->SendSDO(0x3006, 1, (LWORD_t)v.Az()); // SetRpmVelocity [re/min]
455
456 //
457 // Wait for the objects to be OKed.
458 //
459 WaitForSdos();
460
461 //
462 // If the waiting for the objects wasn't interrupted return kTRUE
463 //
464 if (!StopWaitingForSDO())
465 return kTRUE;
466
467 //
468 // print a message if the interruption was due to a Can-node Error
469 //
470 if (HasError())
471 lout << "Error while setting velocity (SDO #3006)" << endl;
472
473 return kFALSE;
474}
475
476// --------------------------------------------------------------------------
477//
478// Initializes Tracking mode
479//
480// Initializes the accelerations of both axes with 90% of the maximum
481// acceleration. Set the status for moving and tracking and starts thr
482// revolution mode.
483//
484void MCosy::InitTracking()
485{
486 //
487 // Start revolution mode
488 //
489 fMac2->SetAcceleration(0.90*fMac2->GetVelRes());
490 fMac2->SetDeceleration(0.90*fMac2->GetVelRes());
491
492 fMac1->SetAcceleration(0.90*fMac1->GetVelRes());
493 fMac1->SetDeceleration(0.90*fMac1->GetVelRes());
494
495 SetStatus(MCosy::kMoving | MCosy::kTracking);
496
497 fMac2->SetRpmMode(TRUE);
498 fMac1->SetRpmMode(TRUE);
499}
500
501// --------------------------------------------------------------------------
502//
503// Limits the speed.
504//
505// This function should work as a limiter. If a tracking error is too large
506// to be corrected fast enough we would get enormous velocities. These
507// velocities are limited to the maximum velocity.
508//
509void MCosy::LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const
510{
511 //
512 // How to limit the speed. If the wind comes and blowes
513 // we cannot forbid changing of the sign. But on the other hand
514 // we don't want fast changes!
515 //
516
517 ULong_t vrzd = fMac1->GetVelRes();
518 ULong_t vraz = fMac2->GetVelRes();
519
520#define sgn(x) (x<0?-1:1)
521
522 const Float_t limit = 0.25;
523/*
524 if (sgn(vt->Az()) != sgn(vcalc.Az()))
525 vt->Az(0);
526// else
527 {
528 if (fabs(vt->Az()) < fabs(vcalc.Az()) *0.5)
529 vt->Az(0.5*vcalc.Az());
530
531 if (fabs(vt->Az()) > fabs(vcalc.Az()) *1.5)
532 vt->Az(1.5*vcalc.Az());
533 }
534
535 if (sgn(vt->Zd()) != sgn(vcalc.Zd()))
536 vt->Zd(0);
537// else
538 {
539 if (fabs(vt->Zd()) > fabs(vcalc.Az()) *1.5)
540 vt->Zd(1.5*vcalc.Zd());
541
542 if (fabs(vt->Zd()) < fabs(vcalc.Az()) *0.5)
543 vt->Zd(0.5*vcalc.Zd());
544 }
545 */
546
547 if (sgn(vt->Az()) != sgn(vcalc.Az())
548 && fabs(vt->Az()) < limit*fabs(vcalc.Az())
549 )
550 vt->Az(0);
551 else
552 if (fabs(vt->Az()) > 0.9*vraz)
553 {
554 lout << "Warning: Azimuth speed limit exceeded. Limiting speed to 90% max." << endl;
555 vt->Az(0.9*vraz*sgn(vt->Az()));
556 }
557
558 if (sgn(vt->Zd()) != sgn(vcalc.Zd())
559 && fabs(vt->Zd()) < limit*fabs(vcalc.Zd())
560 )
561 vt->Zd(0);
562 else
563 if (fabs(vt->Zd()) > 0.9*vrzd)
564 {
565 lout << "Warning: Altitude speed limit exceeded. Limiting speed to 90% max." << endl;
566 vt->Zd(0.9*vrzd*sgn(vt->Zd()));
567 }
568}
569
570void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad]
571{
572 SlaStars sla;
573
574 //
575 // Position to actual position
576 //
577 sla.SetMjd2Now();
578 ZdAz dest = sla.CalcZdAz(dst);
579
580 if (!SetPosition(dest))
581 {
582 lout << "Error: Cannot start tracking, positioning failed." << endl;
583 return;
584 }
585
586 //
587 // calculate offset from present se position
588 //
589 const ZdAz sepos = GetSePos()*kGearRatio;
590
591 if (!RequestRePos())
592 return;
593
594 //
595 // Estimate Offset before starting to track
596 //
597 fOffset = sepos-GetRePos();
598
599 /*
600 cout << "Sepos: " << sepos.Zd() << "re, " << sepos.Az() << "re" << endl;
601 cout << "Repos: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
602 cout << "Offset: " << fOffset.Zd() << "re, " << fOffset.Az() << "re" << endl;
603 */
604
605 //
606 // Init accelerations and Rpm Mode
607 //
608 InitTracking();
609
610 lout << "Start tracking:";
611 lout << " Ra: " << Rad2Deg(dst.Ra()) << "\xb0 ";
612 lout << "Dec: " << Rad2Deg(dst.Dec()) << "\xb0" << endl;
613
614 //
615 // Initialize Tracker (slalib or starguider)
616 //
617 fRaDec = dst;
618 fTracking = kTRUE;
619
620 ofstream fout("log/cosy.pos");
621 fout << "Tracking:";
622 fout << " Ra: " << Rad2Deg(dst.Ra()) << "\x9c ";
623 fout << "Dec: " << Rad2Deg(dst.Dec()) << "\x9c" << endl << endl;
624 fout << " Mjd/10ms V/re/min/4" << endl;
625
626 //
627 // We want to reach the theoretical position exactly in about 0.5s
628 //
629 const float dt = 1; // 1 second
630 while (!StopWaitingForSDO())
631 {
632 //
633 // The loop should not be executed faster than the ramp of
634 // a change in the velocity can be followed.
635 // (This is important on fast machines >500MHz)
636 //
637 //usleep(100000000);
638
639 //
640 // Request Target position for this moment
641 //
642 sla.Now();
643
644 //
645 // Request theoretical Position for a time in the future (To+dt) from CPU
646 //
647 sla.SetMjd(sla.CalcMjd()+dt/(60*60*24));
648 dest = CorrectTarget(GetSePos(), sla.CalcZdAz(dst)); // [se]
649
650 ZdAz vcalc = sla.GetApproxVel(dst) * kGearRatio2*4./60.; // [re/min]
651
652 //
653 // Request absolute position of rotary encoder from Macs
654 //
655 if (!RequestRePos())
656 break;
657
658 //
659 // distance between (To+dt) and To [re]
660 // position time difference < 5usec
661 // fOffset does the synchronization between the
662 // Shaft- and the rotary encoders
663 //
664 dest *= kGearRatio; // [re]
665 dest -= GetRePos() + fOffset;
666
667 //
668 // Velocity to go [re/min] to reach the right position at time t+dt
669 // correct for the duration of RaDec2AltAz
670 //
671 const ZdAz v = dest*60.0/(dt-(fMac2->GetTime()-sla));
672
673 //
674 // calculate real velocity of future [re/min]
675 // believing the Macs manual '/4' shouldn't be necessary, but it is.
676 //
677 ZdAz vt = v/4;
678 LimitSpeed(&vt, vcalc);
679 vt.Round();
680
681 //
682 // check if the drive is fast enough to follow the star
683 //
684 if (vt.Zd()>.9*fMac1->GetVelRes() || vt.Az()>.9*fMac2->GetVelRes())
685 {
686 lout << "Error: Tracking speed faster than 90% of possible maximum velocity." << endl;
687 break;
688 }
689
690 //
691 // Set theoretical velocity (as early after calculation as possible)
692 // Maybe we should attenuate the changes
693 //
694 if (!SetVelocity(vt))
695 break;
696
697 //
698 // Now do 'unnecessary' things
699 //
700 fVelocity = vt/kGearRatio2*4;
701
702 const double mjd = fMac2->GetMjd();
703 fout << setprecision(15) << setw(17) << mjd*60.*60.*24. << " ";
704 fout << setw(4) << vt.Zd() << " ";
705 fout << setw(4) << vt.Az() << endl;
706 //
707 // FIXME? Calculate an accuracy for the tracking system?
708 // How good do we reach the calculated position in 'real'
709 // re valus?
710 //
711
712
713 //
714 // Update speed as often as possible.
715 // make sure, that dt is around 10 times larger than the
716 // update time
717 //
718 // usleep(50000); // 0.05s
719 }
720
721 fTracking = kFALSE;
722 StopMovement();
723 lout << "Tracking stopped." << endl;
724}
725
726// --------------------------------------------------------------------------
727//
728// Stops the movement of both motors.
729//
730// Sets the status to stopping. Sets the deceleration to 50% of the maximum.
731// stops. Quits the revolution mode and wait for the end of the movement.
732//
733void MCosy::StopMovement()
734{
735 //
736 // Set status to stopped
737 //
738 SetStatus(MCosy::kStopping);
739
740 //
741 // set deceleration to 50%
742 //
743 cout << "Stopping positioning..." << endl;
744 fMac1->SetDeceleration(0.5*fMac1->GetVelRes());
745 fMac2->SetDeceleration(0.5*fMac2->GetVelRes());
746
747 //
748 // Stop revolution mode (movement)
749 //
750 cout << "Stopping possibleRPM mode..." << endl;
751 fMac1->SetRpmMode(FALSE);
752 fMac2->SetRpmMode(FALSE);
753
754 //
755 // Wait for the movement to really be finished.
756 //
757 cout << "Waiting for silence..." << endl;
758 WaitForEndMovement();
759
760 //
761 // Check whether everything works fine.
762 //
763 CheckForError();
764 cout << "Movement stopped." << endl;
765}
766
767void *MCosy::Proc(int msg, void *mp)
768{
769 cout << "MCosy::Proc: 0x" << msg << endl;
770 switch (msg)
771 {
772 case WM_WAIT:
773 cout << "Wait for execution of Proc(WM_*, ): done." << endl;
774 return NULL;
775
776 case WM_STOP:
777 StopMovement();
778 return NULL;
779
780 case WM_PRESET:
781 cout << "WM_Preset: start." << endl;
782 fZd1->SetPreset();
783 fZd2->SetPreset();
784 fAz->SetPreset();
785 cout << "WM_Preset: done. (return 0xaffe)" << endl;
786 return (void*)0xaffe;
787
788 case WM_POLARIS:
789 {
790 cout << "WM_Polaris: start." << endl;
791 SlaStars sla;
792 sla.SetMjd2Now();
793
794 RaDec rd(37.94, 89.2644);
795 ZdAz za=sla.CalcZdAz(rd*kDeg2Rad)*16384.0/k2Pi;
796
797 cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl;
798
799 ZdAz sepos = GetSePos();
800 cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl;
801
802 fZd1->SetPreset(za.Zd());
803 fZd2->SetPreset(-za.Zd());
804 fAz->SetPreset(za.Az());
805
806 cout << "WM_Polaris: done. (return 0xaffe)" << endl;
807 }
808 return (void*)0xaffe;
809
810 case WM_POSITION:
811 cout << "WM_Position: start." << endl;
812 {
813 ZdAz dest = *((ZdAz*)mp);
814
815 SetPosition(dest*kDeg2Rad);
816 }
817 cout << "WM_Position: done. (return 0x7777)" << endl;
818 return (void*)0x7777;
819
820 case WM_TRACK:
821 cout << "WM_Track: START" << endl;
822 {
823 RaDec dest = *((RaDec*)mp);
824 TrackPosition(dest*kDeg2Rad);
825 }
826 cout << "WM_Track: done. (return 0x8888)" << endl;
827 return (void*)0x8888;
828
829 case WM_QUIT:
830 cout << "WM_Quit: now." << endl;
831 TerminateApp();
832 cout << "WM_Quit: done." << endl;
833 return (void*)0x9999;
834 }
835 cout << "Unknown Msg" << endl;
836 return (void*)0xffffffff;
837}
838
839void *MTTalk::Thread()
840{
841 fCosy->TalkThread();
842 return NULL;
843}
844
845void MCosy::TalkThread()
846{
847 //
848 // Start the Network
849 //
850 cout << "Reading configuration file..." << flush;
851 TEnv env(".cosyrc");
852 cout << "done." << endl;
853
854 const int res = fMac3->GetVelRes();
855
856 fMac3->SetVelocity(res);
857 fMac3->SetAcceleration(res);
858 fMac3->SetDeceleration(res);
859
860 fMac3->StartPosSync();
861
862 cout << "Going Home..." << endl;
863 fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100));
864 fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100));
865 PostMsg(WM_PRESET, 0, 0);
866 PostMsg(WM_WAIT, 0, 0);
867
868 fMac1->ReqPos();
869 fMac2->ReqPos();
870
871 //const ZdAz repos=GetRePos();
872 //cout << "APOS: " << repos.Zd() << "re, " << repos.Az() << "re" << endl;
873
874 /*
875 cout << Deg2AzRE(env.GetValue("MinAz[Deg]", -1.0)) << " < Az < "
876 << Deg2AzRE(env.GetValue("MaxAz[Deg]", +1.0)) << "RE" << endl;
877 cout << env.GetValue("MinAz[Deg]", -1.0) << " < Az < "
878 << env.GetValue("MaxAz[Deg]", +1.0) << kDEG << endl;
879 cout << Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)) << "RE < Zd < "
880 << Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)) << "RE" << endl;
881 */
882
883
884 cout << "Setting up software endswitch..." << flush;
885 fMac1->SetNegEndswitch(Deg2AzRE(env.GetValue("Az_Min[Deg]", -1.0)));
886 fMac1->SetPosEndswitch(Deg2AzRE(env.GetValue("Az_Max[Deg]", +1.0)));
887
888 fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("Zd_Min[Deg]", -1.0)));
889 fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("Zd_Max[Deg]", +1.0)));
890 cout << "done." << endl;
891
892 fMac1->EnableTimeout(kTRUE, 500);
893 fMac2->EnableTimeout(kTRUE, 500);
894
895/*
896 fMac2->SetNegEndswitch(Deg2ZdRE(env.GetValue("MinZd[Deg]", -1.0)));
897 fMac2->SetPosEndswitch(Deg2ZdRE(env.GetValue("MaxZd[Deg]", +1.0)));
898*/
899// fMac3->StartVelSync();
900/*
901 cout << "PostMsg(WM_PRESET)" << endl;
902 void *rc =
903 cout << hex << "WM_PRESET: ret=" << rc << endl;
904
905 RaDec dest = RaDec(45.0, 30.0)*D2PI/360.0;
906
907 cout << "PostMsg(WM_TRACK)" << endl;
908 cout << sizeof(RaDec) << "==" << sizeof(dest) << endl;
909 rc=PostMsg(WM_TRACK, &dest, sizeof(dest));
910 cout << "DEST killed." << endl;
911*/
912 // AltAz dest = AltAz(45.0, 30.0);
913 // double ra, dec;
914 // slaDaf2r( 71, 0, 0, &ra, &status); // 0 WARNING: RANGE
915 // slaDaf2r( 89, 0, 0, &dec, &status); // 49
916 // cout << "Start tracking: Ra: " << Rad2Deg(ra) << kDEG << " Dec: " << Rad2Deg(dec) << kDEG << endl;
917
918 // dest = AltAz(-46.0, 210);
919 // SetPosition(dest);
920
921 SlaStars sla;
922 while (1)
923 {
924 //
925 // wait until a tracking session is started
926 //
927 while (!fTracking)
928 usleep(1);
929
930 ofstream fout("log/cosy.err");
931 fout << "Tracking:";
932 fout << " Ra: " << Rad2Deg(fRaDec.Ra()) << "\x9c ";
933 fout << "Dec: " << Rad2Deg(fRaDec.Dec()) << "\x9c" << endl << endl;
934 fout << " MjdZd/10ms ErrZd/re";
935 fout << " MjdAz/10ms ErrAd/re" << endl;
936
937 ZdAz old;
938 ZdAz ist;
939
940 ZdAz sollzd;
941 ZdAz sollaz;
942
943 ZdAz istre = -fOffset; // [re]
944 ZdAz time;
945
946 //
947 // only update fTrackingError while tracking
948 //
949 bool phca1=false;
950 bool phca2=false;
951 bool phcaz=false;
952
953 while (fTracking)
954 {
955 //
956 // Make changes (eg wind) smoother - attenuation of control function
957 //
958 const float weight = 1.; //0.3;
959
960 //
961 // This is the time constant which defines how fast
962 // you correct for external influences (like wind)
963 //
964 fZd1->ResetPosHasChanged();
965 fZd2->ResetPosHasChanged();
966 fAz->ResetPosHasChanged();
967 do
968 {
969 phca1 = fZd1->PosHasChanged();
970 phca2 = fZd2->PosHasChanged();
971 phcaz = fAz->PosHasChanged();
972 usleep(1);
973 } while (!phca1 && !phca2 && !phcaz && fTracking);
974
975 //---usleep(100000); // 0.1s
976
977 //
978 // get position, where we are
979 //
980 old = ist;
981 ist = GetSePos(); // [se]
982
983 //
984 // if the position didn't change continue
985 //
986 /*---
987 if ((int)ist.Zd() == (int)old.Zd() &&
988 (int)ist.Az() == (int)old.Az())
989 continue;
990 */
991 istre = GetRePosPdo();
992
993 //
994 // Get time from last shaftencoder position change (position: ist)
995 // FIXME: I cannot take the avarage
996 //
997 time.Zd((fZd1->GetMjd()+fZd2->GetMjd())/2.0);
998 time.Az(fAz->GetMjd());
999
1000 //
1001 // if Shaftencoder changed position
1002 // calculate were we should be
1003 //
1004 if (phca1 || phca2 /*(int)ist.Zd() != (int)old.Zd()*/)
1005 {
1006 sla.SetMjd(time.Zd());
1007 sollzd = CorrectTarget(ist, sla.CalcZdAz(fRaDec)); // [se]
1008
1009 fOffset.Zd(fOffset.Zd()*(1.-weight)+(ist.Zd()*kGearRatio.X()-istre.Zd())*weight);
1010 }
1011
1012 if (phcaz /*(int)ist.Az() != (int)old.Az()*/)
1013 {
1014 sla.SetMjd(time.Az());
1015 sollaz = CorrectTarget(ist, sla.CalcZdAz(fRaDec)); // [se]
1016
1017 fOffset.Az(fOffset.Az()*(1.-weight)+(ist.Az()*kGearRatio.Y()-istre.Az())*weight);
1018 }
1019
1020 fTrackingError.Set((ist.Zd()-sollzd.Zd())*kGearRatio.X(),
1021 (ist.Az()-sollaz.Az())*kGearRatio.Y());
1022
1023 fout << setprecision(15) << setw(17) << time.Zd()*60.*60.*24. << " ";
1024 fout << setprecision(5) << setw(7) << fTrackingError.Zd() << " ";
1025 fout << setprecision(15) << setw(17) << time.Az()*60.*60.*24. << " ";
1026 fout << setprecision(5) << setw(7) << fTrackingError.Az() << endl;
1027 }
1028
1029 fout << endl << endl;
1030 }
1031}
1032
1033Bool_t MCosy::HandleTimer(TTimer *t)
1034{
1035 //
1036 // Update Gui, foremer MTGui.
1037 //
1038 fZd1->DisplayVal();
1039 fZd2->DisplayVal();
1040 fAz->DisplayVal();
1041
1042 ZdAz ist = GetSePos()*(360.0/16384.0); // [se]
1043
1044 fWin->Update(ist, fTrackingError/kGearRatio2,
1045 fVelocity, fOffset/*/kGearRatio2*/,
1046 fStatus);
1047
1048 return kTRUE;
1049}
1050
1051
1052// --------------------------------------------------------------------------
1053//
1054// Start the work of the application:
1055//
1056// Start the Can-Network.
1057// Start the MCosy::TalkThread thread.
1058// turn on the gui update
1059//
1060void MCosy::Start()
1061{
1062 // Don't call this function twice!
1063 Network::Start();
1064
1065 lout << "- Starting TX Thread." << endl;
1066 fTTalk = new MTTalk(this);
1067
1068 lout << "- Starting GUI update." << endl;
1069 fUpdateGui->TurnOn();
1070 // fTGui = new MTGui(this);
1071}
1072
1073// --------------------------------------------------------------------------
1074//
1075// Start the work of the application:
1076//
1077// Turn of the gui update
1078// stop the MCosy::TalkThread thread.
1079// Stop the network
1080//
1081void MCosy::Stop()
1082{
1083
1084 lout << "- Stopping GUI update." << endl;
1085 fUpdateGui->TurnOff();
1086 lout << "- GUI Update stopped." << endl;
1087
1088 delete fTTalk;
1089 lout << "- TX Thread stopped." << endl;
1090
1091 Network::Stop();
1092}
1093
1094MCosy::MCosy(const char *dev, const int baud, MLog &out)
1095: Network(dev, baud, out), fTracking(kFALSE)
1096{
1097 //
1098 // Create Nodes
1099 //
1100 lout << "- Setting up network." << endl;
1101
1102 fMac1=new Macs(1, "Mac.1/Az", lout);
1103 fMac2=new Macs(2, "Mac.2/Zd", lout);
1104 fMac3=new Macs(3, "Mac.3/Az-Sync", lout);
1105
1106 fZd1=new ShaftEncoder(4, "SE.4/Zd1", lout);
1107 fZd2=new ShaftEncoder(5, "SE.5/Zd2", lout);
1108 fAz =new ShaftEncoder(6, "SE.6/Az", lout);
1109
1110 //
1111 // Connect the devices to the network
1112 //
1113 SetNode(fMac1);
1114 SetNode(fMac2);
1115 SetNode(fMac3);
1116 SetNode(fZd1);
1117 SetNode(fZd2);
1118 SetNode(fAz);
1119
1120 //
1121 // Create Gui Event timer and Gui
1122 //
1123 lout << "- Initializing GUI Timer." << endl;
1124 fUpdateGui = new TTimer(this, 100); // 100ms
1125
1126 lout << "- Starting GUI." << endl;
1127 fWin=new MGCosy(this, gClient->GetRoot(), 1, 1);
1128
1129 fAz->SetDisplay(fWin->GetLabel1());
1130 fZd1->SetDisplay(fWin->GetLabel2());
1131 fZd2->SetDisplay(fWin->GetLabel3());
1132
1133 lout.SetOutputGui(fWin->GetLog(), kTRUE);
1134}
1135
1136void MCosy::TerminateApp()
1137{
1138 cout << "MCosy::TerminateApp()" << endl;
1139/*
1140 Int_t rc;
1141 TGMessageBox msg(this, gClient->GetRoot(),
1142 "Information",
1143 "Cosy is shutting down the system - this may take wa while!",
1144 kMBIconExclamation,
1145 kMBOK, //kMBClose
1146 &rc, 0);
1147*/
1148
1149 lout.DisableOutputDevice(MLog::eGui);
1150 lout.SetOutputGui(NULL, kFALSE);
1151
1152 gApplication->Terminate(0);
1153}
1154
1155MCosy::~MCosy()
1156{
1157 cout << "Deleting GUI timer." << endl;
1158
1159 delete fUpdateGui;
1160
1161 cout << "Deleting Nodes." << endl;
1162
1163 delete fAz;
1164 delete fZd2;
1165 delete fZd1;
1166 delete fMac1;
1167 delete fMac2;
1168 delete fMac3;
1169
1170 cout << "Deleting MGCosy." << endl;
1171
1172 lout.DisableOutputDevice(MLog::eGui);
1173
1174 delete fWin;
1175
1176 cout << "MGCosy destructed." << endl;
1177}
Note: See TracBrowser for help on using the repository browser.