Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
DPPanTiltControlExtended.cpp
1 #include "DPPanTiltControlExtended.hh"
2 #include "Base/Common/W32Compat.hh"
3 #include "Base/Common/BIASpragma.hh"
4 #include <cstring>
5 
6 using namespace std;
7 using namespace BIAS;
8 
9 #ifdef BIAS_HAVE_PTHREADS
10 
11 pthread_mutex_t DPPanTiltControlExtended::condition_mutex = PTHREAD_MUTEX_INITIALIZER;
12 long DPPanTiltControlExtended::panThreaded_ = 0;
13 long DPPanTiltControlExtended::tiltThreaded_ = 0;
14 
15 #endif
16 
17 DPPanTiltControlExtended::DPPanTiltControlExtended()
18 {
19  // HACK : Set initial parameters for Point Grey Dragonfly (8mm)
20  xApertureAngle_ = 32.97;
21  yApertureAngle_ = 25.03;
22  xPictureSize_ = 320;
23  yPictureSize_ = 240;
24  followObjectMaxDiff_ = 400;
25  followObjectMinDiff_ = 30;
26  xPTSpeed_ = 0;
27  yPTSpeed_ = 0;
28  xPTDeltaSpeed_ = 0;
29  yPTDeltaSpeed_ = 0;
30  xPTDeltaSpeedTMinus1_ = 0;
31  yPTDeltaSpeedTMinus1_ = 0;
32 
33  KiX_ = KiY_= 0.0;
34  KdX_ = KdY_ = 0.0;
35  KpX_ = KpY_= 1.0;
36  ZiNiErrorX_ = 0;
37  ZiNiErrorY_ = 0;
38  ZiNiErrorTminus1X_ = 0;
39  ZiNiErrorTminus1Y_ = 0;
40  RPICounter_ = 0;
41 
42  ptuMatrix_.SetZYX(0,0,0);
43  deltaMatrix_.SetZYX(0,0,0);
44  sensorMatrixMinus1_.SetZYX(0,0,0);
45  handEyeMatrix_.SetZYX(0.0, 0.0, 0.0);
46  bInitComp_ = true;
47  panSpeedComp_ = 0;
48  tiltSpeedComp_ = 0;
49 }
50 
51 DPPanTiltControlExtended::~DPPanTiltControlExtended()
52 {
53 }
54 
55 void DPPanTiltControlExtended::SetKp(const BIAS::Vector<int> &kp)
56 {
57  KpX_ = kp[0];
58  KpY_ = kp[1];
59  KpX_ /= 100;
60  KpY_ /= 100;
61 }
62 
63 void DPPanTiltControlExtended::SetKi(const BIAS::Vector<int> &ki)
64 {
65  KiX_ = ki[0];
66  KiY_ = ki[1];
67  KiX_ /= 100;
68  KiY_ /= 100;
69 }
70 
71 void DPPanTiltControlExtended::SetKd(const BIAS::Vector<int> &kd)
72 {
73  KdX_ = kd[0];
74  KdY_ = kd[1];
75  KdX_ /= 100;
76  KdY_ /= 100;
77 }
78 
79 void DPPanTiltControlExtended::
80 CompensateHeliMovement(const BIAS::RMatrix &R)
81 {
82  double anglesPTU[3];
83  int steps[2];
84  long int pan, tilt;
85  BIAS::RMatrix compMatrix;
86 
87  if (!bInitComp_)
88  {
89  GetCurrentPosition(pan, tilt);
90 
91  // convert to radians and set
92  anglesPTU[2] = ((double)pan * panResolution_)* M_PI/180.0;
93  anglesPTU[1] = ((double)tilt * tiltResolution_)* M_PI/180.0;
94  anglesPTU[0] = 0.0;
95 
96  ptuMatrix_.SetZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
97  ptuMatrix_.GetRotationAnglesZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
98 
99  R.GetRotationAnglesZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
100 
101  deltaMatrix_ = R * sensorMatrixMinus1_.Transpose();
102 
103  sensorMatrixMinus1_.GetRotationAnglesZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
104 
105  deltaMatrix_.GetRotationAnglesZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
106 
107  compMatrix = ptuMatrix_ * handEyeMatrix_ * deltaMatrix_ *
108  handEyeMatrix_.Transpose() * ptuMatrix_.Transpose();
109 
110  compMatrix.GetRotationAnglesZYX(anglesPTU[0],anglesPTU[1],anglesPTU[2]);
111 
112  steps[0] = (int)(anglesPTU[2] * 180.0/M_PI / panResolution_);
113  steps[1] = (int)(anglesPTU[1] * 180.0/M_PI / tiltResolution_);
114 
115  panSpeedComp_ = (short int)(steps[0]/T_*1e6);
116  tiltSpeedComp_ =(short int)(steps[1]/T_*1e6);
117  if (!bDefaultOrientation_) {
118  panSpeedComp_ = -panSpeedComp_;
119  tiltSpeedComp_ = tiltSpeedComp_;
120  } else {
121  panSpeedComp_ = panSpeedComp_;
122  tiltSpeedComp_ = tiltSpeedComp_;
123  }
124  } else {
125  bInitComp_ = false;
126  }
127 
128  // save the given compensation matrix as last sensor matrix (t-1)
129  sensorMatrixMinus1_ = R;
130 }
131 
132 #ifdef BIAS_HAVE_PTHREADS
133 
134 void DPPanTiltControlExtended::StartCircularMovementThread()
135 {
136  pthread_create(&control_thread, NULL, this->threadFuncCircle_, this);
137 }
138 
139 void DPPanTiltControlExtended::
140 GetCurrentPositionDegreesThreaded(double &dPanDeg, double& dTiltDeg)
141 {
142  pthread_mutex_lock(&condition_mutex);
143  dPanDeg = panThreaded_ * panResolution_;
144  dTiltDeg = tiltThreaded_ * tiltResolution_;
145  pthread_mutex_unlock(&condition_mutex);
146 }
147 
148 void DPPanTiltControlExtended::
149 GetCurrentPositionRadiansThreaded(double &dPanRad, double& dTiltRad)
150 {
151  pthread_mutex_lock(&condition_mutex);
152  dPanRad = panThreaded_ * panResolution_ * M_PI / 180.0;
153  dTiltRad = tiltThreaded_ * tiltResolution_ * M_PI / 180.0;
154  pthread_mutex_unlock(&condition_mutex);
155 }
156 
157 void* DPPanTiltControlExtended::threadFuncCircle_(void *ptr)
158 {
160  ptc->SetMode(ABSOLUTEMODE);
161  ptc->SetSpeed(50,50);
162  // first move to zero
163  ptc->SetPosition(0,0);
164  await_completion();
165  // move up
166  ptc->SetPosition(0,200);
167  pthread_mutex_lock(&condition_mutex);
168  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
169  pthread_mutex_unlock(&condition_mutex);
170  while(panThreaded_ != 0 && tiltThreaded_ != 200){
171  biasusleep(100);
172  pthread_mutex_lock(&condition_mutex);
173  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
174  pthread_mutex_unlock(&condition_mutex);
175  }
176  // move to upper left
177  ptc->SetPosition(200,200);
178  while(panThreaded_ != 200 && tiltThreaded_ != 200){
179  biasusleep(100);
180  pthread_mutex_lock(&condition_mutex);
181  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
182  pthread_mutex_unlock(&condition_mutex);
183  }
184  // move to lower left
185  ptc->SetPosition(200,-200);
186  while(panThreaded_ != 200 && tiltThreaded_ != -200){
187  biasusleep(100);
188  pthread_mutex_lock(&condition_mutex);
189  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
190  pthread_mutex_unlock(&condition_mutex);
191  }
192  // lower right
193  ptc->SetPosition(-200,-200);
194  while(panThreaded_ != -200 && tiltThreaded_ != -200){
195  biasusleep(100);
196  pthread_mutex_lock(&condition_mutex);
197  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
198  pthread_mutex_unlock(&condition_mutex);
199  }
200  // move to upper right
201  ptc->SetPosition(-200,200);
202  while(panThreaded_ != -200 && tiltThreaded_ != 200){
203  biasusleep(100);
204  pthread_mutex_lock(&condition_mutex);
205  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
206  pthread_mutex_unlock(&condition_mutex);
207  }
208  // move up
209  ptc->SetPosition(0,200);
210  while(panThreaded_ != 0 && tiltThreaded_ != 200){
211  biasusleep(100);
212  pthread_mutex_lock(&condition_mutex);
213  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
214  pthread_mutex_unlock(&condition_mutex);
215  }
216  // reset position to zero
217  ptc->SetPosition(0,0);
218  while(panThreaded_ != 0 && tiltThreaded_ != 0){
219  biasusleep(100);
220  pthread_mutex_lock(&condition_mutex);
221  ptc->GetCurrentPosition(panThreaded_,tiltThreaded_);
222  pthread_mutex_unlock(&condition_mutex);
223  }
224  return NULL;
225 }
226 
227 #endif // BIAS_HAVE_PTHREADS
228 
229 void DPPanTiltControlExtended::
230 FollowMidPos(const BIAS::Vector2<double> &newMean)
231 {
232  // distance on the image plane
233  int d[2];
234  d[0] = -((int)xPictureSize_/2)+(int)newMean[0];
235  d[1] = -((int)yPictureSize_/2)+(int)newMean[1];
236 
237  // the angle which the camera has to turn
238  float beta[2];
239  beta[0] = ((float)d[0]/(float)xPictureSize_) * xApertureAngle_;
240  beta[1] = ((float)d[1]/(float)yPictureSize_) * yApertureAngle_;
241 
242  // now calculate positions from angle
243  int stepsPerDegreePan = (int)(1.0/panResolution_);
244  int stepsPerDegreeTilt = (int)(1.0/tiltResolution_);
245  int steps[2];
246  steps[0] = (int)(beta[0] * stepsPerDegreePan);
247  steps[1] = (int)(beta[1] * stepsPerDegreeTilt);
248 
249  // switch sign
250  if (bDefaultOrientation_) {
251  steps[0] = -steps[0];
252  } else {
253  //steps[1] = -steps[1];
254  }
255 
256  if (steps[0] > followObjectMinDiff_ && steps[0] < followObjectMaxDiff_)
257  {
258  set_desired(PAN, POSITION, (PTU_PARM_PTR *) &steps[0],RELATIVE);
259  await_completion();
260  //cout << "DPPanTiltControlExtended : Now following mid pos, steps x = " << steps[0] << endl;
261  }
262  if (steps[1] > followObjectMinDiff_ && steps[1] < followObjectMaxDiff_)
263  {
264  set_desired(TILT, POSITION, (PTU_PARM_PTR *) &steps[1],RELATIVE);
265  await_completion();
266  //cout << "DPPanTiltControlExtended : Now following mid pos, steps y = " << steps[1] << endl;
267  }
268 }
269 
270 void DPPanTiltControlExtended::
271 PIDSpeedAdjustFollow(const BIAS::Vector2<double> &newMean)
272 {
273  // distance on the image plane
274  double error[2];
275  error[0] = -((double)xPictureSize_/2)+newMean[0];
276  error[1] = -((double)yPictureSize_/2)+newMean[1];
277 
278  ZiNiErrorX_+=(int)error[0];
279  ZiNiErrorY_+=(int)error[1];
280 
281  double maxSpeedScaleX = (error[0]/xPictureSize_);
282  double maxSpeedScaleY = (error[1]/yPictureSize_);
283 
284  // now calculate new speeds
285  xPTSpeed_ = (short int)(maxSpeed_ * maxSpeedScaleX
286  * KpX_); // * error[0]); // / xPictureSize_;
287  yPTSpeed_ = (short int)(maxSpeed_ * maxSpeedScaleY
288  * KpY_); // * error[1]); // / yPictureSize_;
289 
290  // add the integrative part to the speed (sum of all errors over time)
291  xPTSpeed_ += (short int)KiX_ * ZiNiErrorX_;
292  yPTSpeed_ += (short int)KiY_ * ZiNiErrorY_;
293 
294  // add the derivative part to the speed (d e(t)/dt)
295  xPTSpeed_ += (short int)(KdX_ * (error[0]- ZiNiErrorTminus1X_));
296  yPTSpeed_ += (short int)(KdY_ * (error[1]- ZiNiErrorTminus1Y_));
297 
298  // now save actual error as t-1 error
299  ZiNiErrorTminus1X_=(int)error[0];
300  ZiNiErrorTminus1Y_=(int)error[1];
301 
302  // switch speeds if camera upside down
303  if(bDefaultOrientation_) {
304  xPTSpeed_ = -xPTSpeed_;
305  } else {
306  //yPTSpeed_ = -yPTSpeed_;
307  }
308  // add the speeds from the helicopter movement compensation calculation
309  xPTSpeed_ += panSpeedComp_;
310  yPTSpeed_ += tiltSpeedComp_;
311 
312  // and set the new speeds
313  set_desired(PAN, SPEED, (PTU_PARM_PTR *) &xPTSpeed_, ABSOLUTE);
314  set_desired(TILT, SPEED, (PTU_PARM_PTR *) &yPTSpeed_, ABSOLUTE);
315 
316  cout << " DPPanTiltControlExtended : Set speed to " << xPTSpeed_ << ", " << yPTSpeed_ << endl;
317 }
318 
319 void DPPanTiltControlExtended::
320 RecursivePIControl(const BIAS::Vector2<double> &newMean)
321 {
322  // distance on the image plane
323  int error[2];
324  error[0] = (int)(newMean[0]-xPictureSize_/2);
325  error[1] = (int)(newMean[1]-yPictureSize_/2);
326 
327  if(RPICounter_ == 0)
328  {
329  // u(0) (e(k-1) and u(k-1) are zero here)
330  // scale maxspeed with picturesize / error = speed relative to error
331  xPTDeltaSpeed_=(short int)(KpX_*(1+T_/(2*Tn_))*error[0]);
332  yPTDeltaSpeed_=(short int)(KpY_*(1+T_/(2*Tn_))*error[1]);
333 
334  // switch speeds if camera upside down
335  if(bDefaultOrientation_)
336  xPTDeltaSpeed_ = -xPTDeltaSpeed_;
337  else
338  yPTDeltaSpeed_ = -yPTDeltaSpeed_;
339 
340  // and set the new speeds
341  set_desired(PAN,SPEED,(PTU_PARM_PTR *) &xPTDeltaSpeed_, RELATIVE);
342  set_desired(TILT,SPEED,(PTU_PARM_PTR *) &yPTDeltaSpeed_, RELATIVE);
343 
344  // save the speed for next iteration
345  xPTDeltaSpeedTMinus1_ = xPTDeltaSpeed_;
346  yPTDeltaSpeedTMinus1_ = yPTDeltaSpeed_;
347 
348  // save the error here
349  ErrorTMinus1_.push_back(error[0]);
350  ErrorTMinus1_.push_back(error[1]);
351 
352  RPICounter_++;
353  }
354  else
355  {
356  // u(1) (u(k-2) is zero here)
357  xPTDeltaSpeed_ = (short int)(KpX_*(1+(T_/(2*Tn_)))
358  *error[0]+KpX_*(-1+(T_/(2*Tn_)))*ErrorTMinus1_[0]
359  +0.1*xPTDeltaSpeedTMinus1_);
360 
361  yPTDeltaSpeed_ = (short int)(KpY_*(1+(T_/(2*Tn_)))
362  *error[1]+KpY_*(-1+(T_/(2*Tn_)))*ErrorTMinus1_[1]
363  +yPTDeltaSpeedTMinus1_);
364 
365 
366  // switch speeds if camera upside down
367  if(bDefaultOrientation_)
368  xPTDeltaSpeed_ = -xPTDeltaSpeed_;
369  else
370  yPTDeltaSpeed_ = -yPTDeltaSpeed_;
371 
372  // and set the new speeds
373  set_desired(PAN,SPEED,(PTU_PARM_PTR *) &xPTDeltaSpeed_, RELATIVE);
374  set_desired(TILT,SPEED,(PTU_PARM_PTR *) &yPTDeltaSpeed_, RELATIVE);
375 
376  // now save speeds and errors for the next iteration
377  xPTDeltaSpeedTMinus1_ = xPTDeltaSpeed_;
378  yPTDeltaSpeedTMinus1_ = yPTDeltaSpeed_;
379 
380  ErrorTMinus1_[0] = error[0];
381  ErrorTMinus1_[1] = error[1];
382  }
383 }
int GetRotationAnglesZYX(double &PhiX, double &PhiY, double &PhiZ) const
Get Euler angles for this rotation matrix in order ZYX.
char SetSpeed(int nPanSpeed, int nTiltSpeed)
Set speed for movement.
Extended controller interface for Directed Perception Pan Tilt Unit.
3D rotation matrix
Definition: RMatrix.hh:49
void GetCurrentPosition(long &lPanPos, long &lTiltPos)
void SetPosition(int nPanPos, int nTiltPos, bool bWaitComplete=true)
Set the current position of the PTU in steps.
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Definition: Matrix3x3.cpp:167
int SetMode(int nMode)
Set the mode in which the camera is to operate.