source: trunk/MagicSoft/Cosy/main/MTracking.cc@ 9524

Last change on this file since 9524 was 9523, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 14.6 KB
Line 
1#include "MTracking.h"
2
3#include "MLogManip.h"
4
5#include "dkc.h"
6
7#include "SlaStars.h"
8
9#include "MCosy.h"
10#include "MStarguider.h"
11
12#include "MDriveCom.h"
13
14ClassImp(MTracking);
15
16using namespace std;
17
18//#define EXPERT
19#undef EXPERT
20
21MTracking::MTracking(MCosy *cosy)
22 : MSlewing(cosy), MThread("MTracking"), fSlalib(fCosy->fObservatory),
23 fTrackAcc(0, 0), fOut(0)
24{
25}
26
27// --------------------------------------------------------------------------
28//
29// Sets the tracking velocity
30//
31// The velocities are given in a ZdAz object in re/min. Return kTRUE
32// in case of success, kFALSE in case of failure.
33//
34Bool_t MTracking::SetVelocity(const ZdAz &v)
35{
36 const Double_t vrzd = fCosy->fMac2->GetVelRes();
37 const Double_t vraz = fCosy->fMac1->GetVelRes();
38
39 //
40 // Send the new velocities for both axes.
41 //
42 fCosy->fMac2->SendSDO(0x3007, (LWORD_t)(v.Zd()*vrzd)); // SetRpmVelocity [re/min]
43 fCosy->fMac1->SendSDO(0x3007, (LWORD_t)(v.Az()*vraz)); // SetRpmVelocity [re/min]
44
45 //
46 // Wait for the objects to be acknoledged.
47 //
48 fCosy->fMac2->WaitForSdo(0x3007, 0, 100);
49 fCosy->fMac1->WaitForSdo(0x3007, 0, 100);
50
51 //
52 // If the waiting for the objects wasn't interrupted return kTRUE
53 //
54 if (!Break())
55 return kTRUE;
56
57 fCosy->PrintError();
58
59 //
60 // print a message if the interruption was due to a Can-node Error
61 //
62 if (fCosy->HasError())
63 gLog << err << "ERROR - while setting tracking velocity (SDO #3006)" << endl;
64
65 return kFALSE;
66}
67
68// --------------------------------------------------------------------------
69//
70// Initializes Tracking mode
71//
72// Initializes the accelerations of both axes with 90% of the maximum
73// acceleration. Set the status for moving and tracking and starts thr
74// revolution mode.
75//
76bool MTracking::InitTracking()
77{
78 // FIXME? Handling of Zombie OK?
79 if (fCosy->fMac1->IsZombieNode() || fCosy->fMac2->IsZombieNode())
80 return false;
81
82 //
83 // Start revolution mode
84 //
85 if (!SetAcc(fCosy->fMac2, fTrackAcc.Zd()))
86 return false;
87
88 if (!SetAcc(fCosy->fMac1, fTrackAcc.Az()))
89 return false;
90
91 fCosy->fMac2->SetRpmMode(TRUE);
92 if (fCosy->fMac2->IsZombieNode())
93 return false;
94
95 fCosy->fMac1->SetRpmMode(TRUE);
96 if (fCosy->fMac1->IsZombieNode())
97 return false;
98
99 fCosy->SetStatus(MDriveCom::kMoving | MDriveCom::kTracking);
100
101 return true;
102}
103
104/*
105void MTracking::StopTracking()
106{
107 //
108 // Set status to Stopping
109 //
110 fCosy->SetStatus(MDriveCom::kStopping);
111
112 //
113 // set deceleration to 50%
114 //
115 cout << "Stopping tracking (dec=20%)..." << endl;
116 fCosy->fMac1->SetDeceleration(0.2*fMac1->GetVelRes());
117 fCosy->fMac2->SetDeceleration(0.2*fMac2->GetVelRes());
118
119 fCosy->fMac2->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min]
120 fCosy->fMac1->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min]
121 fCosy->fMac2->WaitForSdo(0x3006, 1);
122 fCosy->fMac1->WaitForSdo(0x3006, 1);
123
124 cout << "Waiting for end of movement..." << endl;
125 fCosy->WaitForEndMovement();
126
127 //
128 // Wait for the objects to be OKed.
129 //
130 fCosy->fMac1->SetRpmMode(FALSE);
131 fCosy->fMac2->SetRpmMode(FALSE);
132
133 //
134 // Wait for the movement to really be finished.
135 //
136 //cout << "Waiting for end of movement..." << endl;
137 //WaitForEndMovement();
138
139 //
140 // Check whether everything works fine.
141 //
142 fCosy->CheckForError();
143 cout << "Movement stopped." << endl;
144}
145*/
146
147// --------------------------------------------------------------------------
148//
149// Limits the speed.
150//
151// This function should work as a limiter. If a tracking error is too large
152// to be corrected fast enough we would get enormous velocities. These
153// velocities are limited to the maximum velocity.
154//
155Bool_t MTracking::LimitSpeed(const ZdAz &vt) const
156{
157 // vt [deg/min]
158
159 // We can set a maximum speed here
160 // And we can limit the change of the speed (which is done
161 // by acceleration in the drive anyway)
162
163 return kTRUE;
164/*
165 // vt[re/min]
166
167 // Calculate approximate velocity of both axis
168 ZdAz vcalc = fSlalib.GetApproxVel(fCosy->fRaDec); // [rad/rad]
169
170 //vcalc *= 1./(24*60); // [U_tel/min]
171 //vcalc *= fCosy->kGearTot; // [U_mot/min]
172 //vcalc *= fCosy->kResRE; // [re/min]
173
174 vcalc *= fCosy->kGearTot*fCosy->kResRE/(24*60); // [re/min]
175
176 // Set return code
177 Bool_t rc = kFALSE;
178
179 //
180 // How to limit the speed. If the wind comes and blowes
181 // we cannot forbid changing of the sign. But on the other hand
182 // we don't want fast changes!
183 //
184 ULong_t vrzd = fCosy->fMac1->GetVelRes();
185 ULong_t vraz = fCosy->fMac2->GetVelRes();
186
187#define sgn(x) (x<0?-1:1)
188
189 //
190 // When speed changes sign, the maximum allowed speed
191 // is 25% of the |v|
192 //
193 //const Float_t limit = 0.25;
194
195 //
196 // The maximum allowed speed while tracking is 10%
197 //
198 const Float_t maxtrack = 0.1;
199
200 if (fabs(vt->Az()) > maxtrack*vraz)
201 {
202 vt->Az(maxtrack*vraz*sgn(vcalc.Az()));
203 gLog << warn << "Warning: Azimuth speed limit (" << maxtrack*100 << "%) exceeded (" << fabs(vt->Az()) << " > " << maxtrack*vraz << ")... limited." << endl;
204 gLog << "Vcalc: " << vcalc.Zd() << " " << vcalc.Az() << "re/min" <<endl;
205 rc=kTRUE;
206 }
207 if (fabs(vt->Zd()) > maxtrack*vrzd)
208 {
209 vt->Zd(maxtrack*vrzd*sgn(vcalc.Zd()));
210 gLog << warn << "Warning: Altitude speed limit (" << maxtrack*100 << "%) exceeded (" << fabs(vt->Zd()) <<" > " << maxtrack*vrzd << ")... limited." << endl;
211 gLog << "Vcalc: " << vcalc.Zd() << " " << vcalc.Az() << "re/min" <<endl;
212 rc=kTRUE;
213 }
214 return rc;
215 */
216}
217
218void MTracking::UpdateSlalib(SlaPlanets &sla)
219{
220 if (fTrackType<0)
221 sla.Set(fTrackPos/TMath::DegToRad());
222 else
223 sla.SetPlanet((ePlanets_t)fTrackType);
224
225// if (fCosy->fStarguider)
226// fCosy->fStarguider->SetPointingPosition(sla.GetRaDec());
227}
228
229void MTracking::UpdateSlalib(Double_t dt)
230{
231 fSlalib.Now(dt);
232 UpdateSlalib(fSlalib);
233
234 fCosy->fRaDec = fSlalib.GetRaDecRad();
235 fCosy->fHourAngle = fSlalib.GetHourAngle();
236}
237
238void MTracking::UpdateSlalib(SlaPlanets &sla, Double_t mjd)
239{
240 sla.SetMjd(mjd);
241 UpdateSlalib(sla);
242}
243
244bool MTracking::Move()
245{
246 const RaDec &dst = fSlalib.GetRaDecRad();
247
248 ZdAz dest = fSlalib.GetZdAzRad();
249
250 if (fTrackType>=0)
251 gLog << all << fSlalib.GetTime() << ": Tracking Planet with Id " << fTrackType << endl;
252 gLog << all << fSlalib.GetTime() << ": Track Position " << dst.Ra()*kRad2Deg/15 << "h, " << dst.Dec()*kRad2Deg <<"deg" << endl;
253
254 // If the star is culminating behind the zenith (South) we want to
255 // align the azimuth angle between -180 and 180deg. If the star is
256 // culminating before the zenith (north) we want the star to be
257 // aligned between -180 and 180deg (which is the default of CalcZdAz)
258 if (fSlalib.GetPhi()>dst.Dec() && dest.Az()<0)
259 {
260 // align az from -180/180 to 0/360
261 gLog << inf2 << "Star culminating behind zenith: Adding 360deg to Azimuth " << dest.Az()*kRad2Deg << endl;
262 dest.Az(dest.Az() + TMath::TwoPi());
263 }
264
265 // Position the telescope to the current local position of the
266 // star. Do not reposition but start the tracking after the
267 // first positioning step
268 if (!SetPosition(dest, kTRUE))
269 {
270 gLog << err << "ERROR - Cannot start tracking, positioning failed." << endl;
271 return false;
272 }
273
274 return true;
275}
276
277void MTracking::TrackPosition(const RaDec &dst)
278{
279 fTrackPos = dst;
280 fTrackType = -1;
281
282 // Start tracking
283 Track();
284}
285
286void MTracking::TrackPlanet(ePlanets_t planet)
287{
288 fTrackPos = RaDec();
289 fTrackType = planet;
290
291 // Start tracking
292 Track();
293}
294
295void MTracking::Track() // ra, dec [rad]
296{
297 // Position to corrent nominal position
298 UpdateSlalib();
299
300 if (!Move())
301 return;
302
303 //fCosy->fRaDec = fSlalib.GetRaDec();
304
305 // Initialize Tracker (slalib or starguider)
306 RunThread();
307
308 //
309 // Init accelerations and Rpm Mode
310 //
311 if (!InitTracking())
312 {
313 fCosy->StopMovement();
314 return;
315 }
316
317 // Get current nominal local position
318 UpdateSlalib();
319
320 ZdAz pos = fSlalib.GetZdAzRad();
321
322 // Some output
323 XY xy(TMath::RadToDeg()*fCosy->fRaDec.Ra()/15, TMath::RadToDeg()*fCosy->fRaDec.Dec());
324 gLog << all << fSlalib.GetTime() << " - Start Tracking: Ra=" << xy.X() << "h Dec=";
325 gLog << xy.Y() << "\xb0 @ Zd=" << pos.Zd()*kRad2Deg <<"deg Az=" << pos.Az()*kRad2Deg <<"deg" << endl;
326
327 //
328 // We want to reach the theoretical position exactly in about 0.5s
329 //
330 // *OLD*const float dt = 1; // 1 second
331 const float dt = 5;//3; // 2 second
332 while (!Break()/* && !fCosy->HasError() && !fCosy->HasZombie()*/)
333 {
334 /*
335 // Code for position control mode
336 // Set: S-0-0001
337 // Set: S-0-0002
338 // Set: P-0-0099
339 // Set: P-0-0187 (Spline)
340 // Replace S-0-0258 by S-0-0047 in communication
341
342 sla.Now();
343 const ZdAz pointing = sla.CalcZdAz(fCosy->fRaDec); // [rad]
344 ZdAz dest = fCosy->AlignTrackingPos(pointing); // fix ambiguity
345 dest = fCosy->fBending(dest); // [rad]
346 if (!fCosy->CheckRange(dest))
347 break;
348 dest *= 1./TMath::TwoPi(); //[rev]
349 fCosy->fMac2->SendSDO(0x6004, (LWORD_t)(dest.Zd()*fCosy->fMac2->GetPosRes()+.5), false);
350 fCosy->fMac1->SendSDO(0x6004, (LWORD_t)(dest.Az()*fCosy->fMac1->GetPosRes()+.5), false);
351 usleep(10000); // 10ms
352 continue;
353 */
354
355 //
356 // Request Target position for Now+dt
357 //
358 UpdateSlalib(dt);
359
360 //
361 // Request nominal position for this time in the future (To+dt)
362 //
363 const ZdAz pointing = fSlalib.GetZdAzRad();
364 ZdAz dest = fCosy->AlignTrackingPos(pointing); // fix ambiguity
365
366 //ZdAz repos;
367 dest = fCosy->fBending(dest); // [rad]
368 if (!fCosy->CheckRange(dest))
369 break;
370
371 // Destination position at t+dt in re-units
372 dest *= TMath::RadToDeg(); // [re]
373
374 const ZdAz sepos = fCosy->GetSePos()*360; // [deg]
375
376 // Now calculate the distance to move from now
377 // to a time in t+dt.
378 dest -= sepos;
379
380 //
381 // Velocity to go [re/min] to reach the right position at time t+dt
382 // correct for the duration of RaDec2AltAz
383 //
384 const ZdAz v = dest * 60/dt; // [deg/min]
385 const ZdAz vt = v/360; // [rpm]
386
387 //Double_t kpZd = TMath::Abs(fCosy->fTrackingError.Zd()*TMath::RadToDeg()*60*4);
388 //Double_t kpAz = TMath::Abs(fCosy->fTrackingError.Az()*TMath::RadToDeg()*60*12);
389 //v.Zd(v.Zd()*(1+TMath::Min(0.3, kpZd)));
390 //v.Az(v.Az()*(1+TMath::Min(0.3, kpAz)));
391
392 if (LimitSpeed(v))
393 {
394 gLog << dbg << "vt: " << v.Zd() << " " << v.Az() << "re/min" << endl;
395 gLog << "Dest: " << dest.Zd() << " " << dest.Az() << endl;
396 }
397
398 //
399 // check if the drive is fast enough to follow the star
400 //
401 if (TMath::Abs(vt.Zd())>0.5*fCosy->fMac2->GetVelMaxRev() ||
402 TMath::Abs(vt.Az())>0.5*fCosy->fMac1->GetVelMaxRev())
403 {
404 gLog << err << "ERROR - Tracking speed faster than 50% of possible maximum velocity." << endl;
405 gLog << "Zd: " << vt.Zd() << " Az: " << vt.Az() << endl;
406 break;
407 }
408
409 //
410 // Set theoretical velocity (as early after calculation as possible)
411 // Maybe we should attenuate the changes
412 //
413 if (!SetVelocity(vt))
414 break;
415
416 //
417 // Update speed as often as possible.
418 // make sure, that dt is around 10 times larger than the
419 // update time
420 //
421 // The loop should not be executed faster than the ramp of
422 // a change in the velocity can be followed.
423 // (This is important on fast machines >500MHz)
424 //
425 usleep(1000000); // 1s
426
427 //
428 // If we would do it in the beginnign of the loop it can happen
429 // that we check before we got the feedback through the pdo
430 //
431 if (!fCosy->fMac1->IsRpmActive() || !fCosy->fMac2->IsRpmActive())
432 break;
433 }
434
435 fSlalib.Now();
436
437 CancelThread();
438
439 // If CancelPoints are used we have to make this a Cleanup!
440 fCosy->StopMovement();
441
442 gLog << all << fSlalib.GetTime() << " - Tracking stopped @ Zd=";
443 gLog << fCosy->fZdAzSoll.Zd()*TMath::RadToDeg() <<"deg Az=";
444 gLog << fCosy->fZdAzSoll.Az()*TMath::RadToDeg() <<"deg" << endl;
445}
446
447Int_t MTracking::Thread()
448{
449 if (!fCosy->fMac1 || !fCosy->fMac2)
450 return 3;
451
452 gLog << inf2 << "- Tracking Thread started (" << MTime(-1) << ")" << endl;
453
454 //SlaPlanets sla(fSlalib.GetObservatoryKey());
455 SlaPlanets sla(MObservatory::kMagic1);
456
457 UpdateSlalib(sla);
458
459 //
460 // only update fTrackingError while tracking
461 //
462 bool phca1=false;
463 bool phcaz=false;
464
465 while (1)
466 {
467 // Make changes (eg wind) smoother - attenuation of control function
468 // This is the time constant which defines how fast
469 // you correct for external influences (like wind)
470 //const float weight = 1.; //0.3;
471
472 // Check for changes of the shaftencoder values
473 fCosy->fMac1->ResetHasChangedPos2();
474 fCosy->fMac2->ResetHasChangedPos2();
475 do
476 {
477 phcaz = fCosy->fMac1->HasChangedPos2();
478 phca1 = fCosy->fMac2->HasChangedPos2();
479
480 usleep(1);
481
482 TThread::CancelPoint();
483
484 } while (!phca1 && !phcaz);
485
486 // get current position and corresponding time of shaftencoders
487 const ZdAz istse = fCosy->GetSePos()*TMath::TwoPi(); // [deg]
488
489 const Double_t mjdaz = fCosy->fMac1->GetMjdPos2();
490 const Double_t mjdzd = fCosy->fMac2->GetMjdPos2();
491
492
493 // calculate offset for both axis (only one is needed)
494 // if Shaftencoder changed position, calculate nominal position
495 if (phca1)
496 {
497 UpdateSlalib(sla, mjdzd);
498
499 ZdAz dummy = sla.GetZdAzRad();
500 dummy = fCosy->AlignTrackingPos(dummy);
501 fCosy->fZdAzSoll.Zd(dummy.Zd());
502 fCosy->fTrackingError.Zd(fCosy->fBending(dummy).Zd()-istse.Zd());
503
504 TThread::CancelPoint();
505 }
506 if (phcaz)
507 {
508 UpdateSlalib(sla, mjdaz);
509
510 ZdAz dummy = sla.GetZdAzRad();
511 dummy = fCosy->AlignTrackingPos(dummy);
512 fCosy->fZdAzSoll.Az(dummy.Az());
513 fCosy->fTrackingError.Az(fCosy->fBending(dummy).Az()-istse.Az());
514
515 TThread::CancelPoint();
516 }
517 }
518
519 gLog << inf2 << "- Tracking Thread done. (" << MTime(-1) << ")" << endl;
520 return 0;
521}
Note: See TracBrowser for help on using the repository browser.