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

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