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

Last change on this file since 9338 was 9132, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 13.0 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(0x3006, 1, (LWORD_t)(v.Zd()*vrzd)); // SetRpmVelocity [re/min]
36 fCosy->fMac1->SendSDO(0x3006, 1, (LWORD_t)(v.Az()*vraz)); // SetRpmVelocity [re/min]
37
38 //
39 // Wait for the objects to be acknoledged.
40 //
41 fCosy->fMac2->WaitForSdo(0x3006, 1, 100);
42 fCosy->fMac1->WaitForSdo(0x3006, 1, 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 sla.Now(1);
275 const ZdAz pointing = sla.CalcZdAz(fCosy->fRaDec); // [rad]
276 ZdAz dest = fCosy->AlignTrackingPos(pointing); // fix ambiguity
277 dest = fCosy->fBending(dest); // [rad]
278 if (!fCosy->CheckRange(dest))
279 break;
280 dest *= 1./TMath::TwoPi(); //[rev]
281 fCosy->fMac2->SendSDO(0x6004, 0, (LWORD_t)(dest.Zd()*fCosy->fMac2->GetPosRes()+.5), false);
282 fCosy->fMac1->SendSDO(0x6004, 0, (LWORD_t)(dest.Az()*fCosy->fMac1->GetPosRes()+.5), false);
283 usleep(100000); // 1s
284 continue;
285 */
286
287 //
288 // Request Target position for Now+dt
289 //
290 sla.Now(dt);
291
292 //
293 // Request nominal position for this time in the future (To+dt)
294 //
295 const ZdAz pointing = sla.CalcZdAz(fCosy->fRaDec); // [rad]
296 ZdAz dest = fCosy->AlignTrackingPos(pointing); // fix ambiguity
297
298 //ZdAz repos;
299 dest = fCosy->fBending(dest); // [rad]
300 if (!fCosy->CheckRange(dest))
301 break;
302
303 // Destination position at t+dt in re-units
304 dest *= TMath::RadToDeg(); // [re]
305
306 const ZdAz sepos = fCosy->GetSePos()*360; // [deg]
307
308 // Now calculate the distance to move from now
309 // to a time in t+dt.
310 dest -= sepos;
311
312 //
313 // Velocity to go [re/min] to reach the right position at time t+dt
314 // correct for the duration of RaDec2AltAz
315 //
316 const ZdAz v = dest * 60/dt; // [deg/min]
317 const ZdAz vt = v/360; // [rpm]
318
319 //Double_t kpZd = TMath::Abs(fCosy->fTrackingError.Zd()*TMath::RadToDeg()*60*4);
320 //Double_t kpAz = TMath::Abs(fCosy->fTrackingError.Az()*TMath::RadToDeg()*60*12);
321 //v.Zd(v.Zd()*(1+TMath::Min(0.3, kpZd)));
322 //v.Az(v.Az()*(1+TMath::Min(0.3, kpAz)));
323
324 if (LimitSpeed(v, sla))
325 {
326 gLog << dbg << "vt: " << v.Zd() << " " << v.Az() << "re/min" << endl;
327 gLog << "Dest: " << dest.Zd() << " " << dest.Az() << endl;
328 }
329
330 //
331 // check if the drive is fast enough to follow the star
332 //
333 if (TMath::Abs(vt.Zd())>0.5*fCosy->fMac2->GetVelMaxRev() ||
334 TMath::Abs(vt.Az())>0.5*fCosy->fMac1->GetVelMaxRev())
335 {
336 gLog << err << "ERROR - Tracking speed faster than 50% of possible maximum velocity." << endl;
337 gLog << "Zd: " << vt.Zd() << " Az: " << vt.Az() << endl;
338 break;
339 }
340
341 //
342 // Set theoretical velocity (as early after calculation as possible)
343 // Maybe we should attenuate the changes
344 //
345 if (!SetVelocity(vt))
346 break;
347
348 //
349 // Update speed as often as possible.
350 // make sure, that dt is around 10 times larger than the
351 // update time
352 //
353 // The loop should not be executed faster than the ramp of
354 // a change in the velocity can be followed.
355 // (This is important on fast machines >500MHz)
356 //
357 usleep(1000000); // 1s
358 }
359
360 sla.Now();
361
362 CancelThread();
363
364 // If CancelPoints are used we have to make this a Cleanup!
365 fCosy->StopMovement();
366
367 gLog << all << sla.GetTime() << " - Tracking stopped @ Zd=";
368 gLog << fCosy->fZdAzSoll.Zd()*TMath::RadToDeg() <<"deg Az=";
369 gLog << fCosy->fZdAzSoll.Az()*TMath::RadToDeg() <<"deg" << endl;
370}
371
372Int_t MTracking::Thread()
373{
374 if (!fCosy->fMac1 || !fCosy->fMac2)
375 return 3;
376
377 gLog << inf2 << "- Tracking Thread started (" << MTime(-1) << ")" << endl;
378
379 SlaStars sla(fCosy->fObservatory);
380 sla.Now();
381
382 ZdAz soll = sla.CalcZdAz(fCosy->fRaDec); // [rad]
383
384 //
385 // only update fTrackingError while tracking
386 //
387 bool phca1=false;
388 bool phcaz=false;
389
390 while (1)
391 {
392 // Make changes (eg wind) smoother - attenuation of control function
393 // This is the time constant which defines how fast
394 // you correct for external influences (like wind)
395 //const float weight = 1.; //0.3;
396
397 // Check for changes of the shaftencoder values
398 fCosy->fMac1->ResetHasChangedPos2();
399 fCosy->fMac2->ResetHasChangedPos2();
400 do
401 {
402 phcaz = fCosy->fMac1->HasChangedPos2();
403 phca1 = fCosy->fMac2->HasChangedPos2();
404
405 usleep(1);
406
407 TThread::CancelPoint();
408
409 } while (!phca1 && !phcaz);
410
411 // get current position and corresponding time of shaftencoders
412 const ZdAz istse = fCosy->GetSePos()*TMath::TwoPi(); // [deg]
413
414 const Double_t mjdaz = fCosy->fMac1->GetMjdPos2();
415 const Double_t mjdzd = fCosy->fMac2->GetMjdPos2();
416
417
418 // calculate offset for both axis (only one is needed)
419 // if Shaftencoder changed position, calculate nominal position
420 if (phca1)
421 {
422 ZdAz dummy = sla.CalcZdAz(fCosy->fRaDec, mjdzd);
423 dummy = fCosy->AlignTrackingPos(dummy);
424 fCosy->fZdAzSoll.Zd(dummy.Zd());
425 soll.Zd(fCosy->fBending(dummy).Zd()); // [rad]
426
427 fCosy->fTrackingError.Zd(soll.Zd()-istse.Zd());
428
429 TThread::CancelPoint();
430 }
431 if (phcaz)
432 {
433 ZdAz dummy = sla.CalcZdAz(fCosy->fRaDec, mjdaz);
434 dummy = fCosy->AlignTrackingPos(dummy);
435 fCosy->fZdAzSoll.Az(dummy.Az());
436 soll.Az(fCosy->fBending(dummy).Az()); // [rad]
437
438 fCosy->fTrackingError.Az(soll.Az()-istse.Az());
439
440 TThread::CancelPoint();
441 }
442 }
443
444 gLog << inf2 << "- Tracking Thread done. (" << MTime(-1) << ")" << endl;
445 return 0;
446}
Note: See TracBrowser for help on using the repository browser.