OnlineBodySchemaAdaptation  2.0
All Data Structures Files Functions Modules Pages
Public Member Functions | Protected Member Functions
handPoseEstimationModule Class Reference

Class handPoseEstimationModule. More...

#include <handPoseEstimationModule.h>

Inheritance diagram for handPoseEstimationModule:
handPoseEstimation_IDL

Public Member Functions

virtual bool configure (yarp::os::ResourceFinder &rf)
 
virtual bool interruptModule ()
 
virtual bool close ()
 
virtual bool updateModule ()
 
virtual double getPeriod ()
 
bool attach (yarp::os::RpcServer &source)
 
bool start ()
 Start (re-start) the hand pose estimation. More...
 
bool stop ()
 Stop the hand pose estimation. More...
 
bool pause ()
 Pause the hand pose estimation. More...
 
bool resume ()
 Resume the hand pose estimation. More...
 
yarp::os::Bottle lastOffsets ()
 Ask for the last estimated angular Offsets on the arm (7DoF) More...
 
bool quit ()
 Quit the module. More...
 
virtual bool read (yarp::os::ConnectionReader &connection) YARP_OVERRIDE
 
virtual std::vector< std::string > help (const std::string &functionName="--all")
 

Protected Member Functions

cv::Mat processImages (cv::Mat inputImage)
 The function applies a canny edge detector and a distance transform. More...
 
bool initializeSMCVariables ()
 Initialize the variables structs needed for the SMC to run. More...
 
bool initSMC ()
 Initialize the variables values for the SMC. More...
 
bool runSMCIteration ()
 Run one iteration of the Sequential Monte Carlo Parameters estimation. More...
 
void mergeAndFlipImages ()
 merge the left and right images. More...
 
void kernelDensityEstimation ()
 Perform the Kernel Density estimation with a multivariate gaussian kernel.
 
bool readArmJoints ()
 Read the arm joints. More...
 
bool readHeadJoints ()
 Read the head joints. More...
 
bool systematic_resampling (CvMat *oldParticlesState, CvMat *oldParticlesWeights, CvMat *newParticlesState, CvMat *cumWeight, float sum2)
 perform the systematic resampling step of the SMC algorithm More...
 

Detailed Description

Class handPoseEstimationModule.

Definition at line 53 of file handPoseEstimationModule.h.

Member Function Documentation

bool handPoseEstimationModule::initializeSMCVariables ( )
protected

Initialize the variables structs needed for the SMC to run.

Returns
true/false on success/failure

Definition at line 92 of file handPoseEstimationModule.cpp.

93 {
94  nParticles=200; // HardCoded since the Internal Model should be recompiled to support a different amount of particles
95 
96  //allocate memory for the particles;
97  particles=cvCreateMat(8,nParticles,CV_32FC1); // 0-6 Betas 7- likelihood
98  //fill the memory with zeros
99  cvSetZero(particles);
100 
101  //define ways of accessing the particles:
102  // Beta1
103  particles1 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
104  cvInitMatHeader( particles1, 1, nParticles, CV_32FC1, particles->data.ptr, particles->step );
105  // Beta2
106  particles2 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
107  cvInitMatHeader( particles2, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*1, particles->step );
108  // Beta3
109  particles3 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
110  cvInitMatHeader( particles3, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*2, particles->step );
111  // Beta4
112  particles4 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
113  cvInitMatHeader( particles4, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*3, particles->step );
114  // Beta5
115  particles5 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
116  cvInitMatHeader( particles5, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*4, particles->step );
117  // Beta6
118  particles6 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
119  cvInitMatHeader( particles6, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*5, particles->step );
120  // Beta7
121  particles7 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
122  cvInitMatHeader( particles7, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*6, particles->step );
123  // likelihood
124  particles8 = cvCreateMatHeader( 1,nParticles, CV_32FC1);
125  cvInitMatHeader( particles8, 1, nParticles, CV_32FC1, particles->data.ptr + particles->step*7, particles->step );
126 
127  //theta1-theta7
128  particles1to7 = cvCreateMatHeader( 7,nParticles, CV_32FC1);
129  cvInitMatHeader( particles1to7, 7, nParticles, CV_32FC1, particles->data.ptr, particles->step );
130 
131 
132  newParticles=cvCreateMat(8,nParticles,CV_32FC1);
133  newParticles1to7 = cvCreateMatHeader( 7,nParticles, CV_32FC1);
134  cvInitMatHeader( newParticles1to7, 7, nParticles, CV_32FC1, newParticles->data.ptr, newParticles->step );
135  // Resampling stuff
136  cumWeight =cvCreateMat(1,nParticles+1,CV_32FC1);
137  noise=cvCreateMat(7,nParticles,CV_32FC1);
138  cvSetZero(noise);
139  return true;
140 }
bool handPoseEstimationModule::initSMC ( )
protected

Initialize the variables values for the SMC.

Returns
true/false on success/failure

Definition at line 142 of file handPoseEstimationModule.cpp.

143 {
144  // Generate random particles
145 
146  srand((unsigned int)time(0)); //make sure random numbers are really random.
147  rngState = cvRNG(rand());
148 
149  cvRandArr( &rngState, particles1, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
150  //initialize Theta2
151  cvRandArr( &rngState, particles2, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
152  //initialize Theta3
153  cvRandArr( &rngState, particles3, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
154  //initialize Theta4
155  cvRandArr( &rngState, particles4, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
156  //initialize Theta5
157  cvRandArr( &rngState, particles5, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
158  //initialize Theta6
159  cvRandArr( &rngState, particles6, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
160  //initialize Theta7
161  cvRandArr( &rngState, particles7, CV_RAND_NORMAL, cvScalar(initialMean), cvScalar(initialStdDev));
162 
163  // Artificial Noise Initialization
164  artifNoiseStdDev = initialArtificialNoiseStdDev;
165  // Setting first particle as Zero offset
166  for (unsigned int joint=0;joint<8;joint++)
167  {
168  cvmSet(particles,joint,0,0.0);
169  }
170  return true;
171 }
yarp::os::Bottle handPoseEstimationModule::lastOffsets ( )
virtual

Ask for the last estimated angular Offsets on the arm (7DoF)

Returns
Bottle with last angular Offsets

Reimplemented from handPoseEstimation_IDL.

Definition at line 675 of file handPoseEstimationModule.cpp.

676 {
677  yInfo("lastOffsets command received");
678  Bottle reply;
679  reply = lastBestOffset;
680  return reply;
681 }
void handPoseEstimationModule::mergeAndFlipImages ( )
protected

merge the left and right images.

i.e., concatenate horizontally.

Definition at line 402 of file handPoseEstimationModule.cpp.

403 {
404  cv::hconcat(imageProcL, imageProcR,concatenatedImage);
405  cv::flip(concatenatedImage,concatenatedImage,0);
406  cvtColor(concatenatedImage,concatenatedImage,CV_GRAY2BGR);
407 }
bool handPoseEstimationModule::pause ( )
virtual

Pause the hand pose estimation.

The filter stop the generation of particles and waits for a resume command

Returns
true/false on success/failure

Reimplemented from handPoseEstimation_IDL.

Definition at line 661 of file handPoseEstimationModule.cpp.

662 {
663  paused = true;
664  yInfo("pause command received");
665  return true;
666 }
Mat handPoseEstimationModule::processImages ( cv::Mat  inputImage)
protected

The function applies a canny edge detector and a distance transform.

Returns
the processed image

Definition at line 552 of file handPoseEstimationModule.cpp.

553 {
554  Mat edges,dtImage;
555  Mat dtImage2,dtImage2_8;
556  cvtColor(inputImage,edges,CV_RGB2GRAY);
557 
558  // Image
559  blur( edges, edges, Size(3,3) );
560  Canny(edges,edges,65,3*65,3);
561  threshold(edges,edges,100,255,THRESH_BINARY_INV);
562  distanceTransform(edges,dtImage,CV_DIST_L2,CV_DIST_MASK_5);
563  cvtColor(dtImage,dtImage2,CV_GRAY2BGR);
564  dtImage.convertTo(dtImage2_8,CV_8UC3);
565  return dtImage2_8;
566 }
bool handPoseEstimationModule::quit ( )
virtual

Quit the module.

Returns
true/false on success/failure

Reimplemented from handPoseEstimation_IDL.

Definition at line 683 of file handPoseEstimationModule.cpp.

684 {
685  yInfo("quit command received");
686  closing = true;
687  return true;
688 }
bool handPoseEstimationModule::readArmJoints ( )
protected

Read the arm joints.

Returns
true/false on success/failure

Definition at line 568 of file handPoseEstimationModule.cpp.

569 {
570  // read Arm joint angles
571  Bottle *receive = armPort.read();
572 
573  string s1 = receive->toString();
574  char *str = new char[s1.size()+1];
575  strcpy(str, s1.c_str());
576  char * pch;
577  pch = strtok ( (char*) str," ");
578  int i=0;
579  while (pch != NULL)
580  {
581  encodersArm[i]=atof(pch);
582  pch = strtok (NULL, " ");
583  i++;
584  }
585 }
bool handPoseEstimationModule::readHeadJoints ( )
protected

Read the head joints.

Returns
true/false on success/failure

Definition at line 587 of file handPoseEstimationModule.cpp.

588 {
589  //Read Head Joint Angles
590  Bottle *receive = headPort.read();
591  string s2 = receive->toString();
592  char *str = new char[s2.size()+1];
593  strcpy(str, s2.c_str());
594  char * pch;
595  pch = strtok ( (char*) str," ");
596  int i=0;
597  while (pch != NULL)
598  {
599  encodersHead[i]=atof(pch);
600  pch = strtok (NULL, " ");
601  i++;
602  }
603 }
bool handPoseEstimationModule::resume ( )
virtual

Resume the hand pose estimation.

The filter resumes the generation of particles after a pause command

Returns
true/false on success/failure

Reimplemented from handPoseEstimation_IDL.

Definition at line 668 of file handPoseEstimationModule.cpp.

669 {
670  paused = false;
671  yInfo("resume command received");
672  return true;
673 }
bool handPoseEstimationModule::runSMCIteration ( )
protected

Run one iteration of the Sequential Monte Carlo Parameters estimation.

Returns
true/false on success/failure

Definition at line 173 of file handPoseEstimationModule.cpp.

174 {
175  // tmp variables
176  double maxLikelihood=0.0;
177  double sumLikelihood=0.0;
178  double likelihood=0.0;
179 
180  // prepare containers to send data through YARP
181  ImageOf<PixelBgr> &yarpReturnImage = LRimageOutputPort.prepare();
182  Bottle &outputParticles = particlesOutPort.prepare();
183  Bottle &outputHead= headOutPort.prepare();
184  // prepare concatenated Image
185  concatenatedImage.convertTo(concatenatedImage,CV_8UC3);
186  yarpReturnImage.resize(concatenatedImage.cols,concatenatedImage.rows);
187  concatenatedImage.copyTo( cvarrToMat( static_cast<IplImage*> ( yarpReturnImage.getIplImage() ) ) );
188  // Fill Bottle with offsets+encoders to generate
189  for(int index=0;index < nParticles;index++)
190  {
191  // Arm + offsets
192  for (unsigned int joint=0;joint<7;joint++)
193  {
194  outputParticles.addDouble(encodersArm[joint]+cvmGet(particles,joint,index));
195  if(index==0)
196  {
197  yInfo() << cvmGet(particles,joint,index);
198  }
199  }
200  // Fingers
201  for(unsigned int joint=7;joint<16;joint++)
202  {
203  outputParticles.addDouble(encodersArm[joint]);
204  }
205  }
206  outputParticles.addInt(nParticles); // n_particles
207 
208  // Fill Bottle with head encoders
209  for(int k=0;k<6;k++)
210  {
211  outputHead.addDouble(encodersHead[k]);
212  }
213 
214  //Send data to InternalModel
215  particlesOutPort.write();
216  headOutPort.write();
217  LRimageOutputPort.write();
218 
219  // Waitint for results
220  yInfo("Waiting for Hypotheses generation and evaluation");
221  Bottle *receivedLikelihood = likelihoodPort.read();
222  yInfo(" DONE");
223 
224  // Save the likelihood of each particle
225  for(int index=0;index<nParticles;index++)
226  {
227  likelihood = receivedLikelihood->pop().asDouble();
228  cvmSet(particles,7,index,likelihood);
229  sumLikelihood+=likelihood;
230  if(likelihood>maxLikelihood)
231  {
232  maxLikelihood=likelihood;
233  }
234  }
235  cvmSet(particles,7,0,0.0);
237 
238 
239  yInfo("Best likelihood: %f", (float) cvmGet(particles,7,maxWeightIndex));
240 
241  if(iteration>minimumIteration) // START sending offsets
242  {
243  // Send Best Particle
244  Bottle &bestOffset = offsetsPort.prepare();
245  bestOffset.clear();
246  for(int i=0;i<7;i++)
247  {
248  bestOffset.addDouble(cvmGet(particles,i,maxWeightIndex));
249  }
250  lastBestOffset.clear();
251  lastBestOffset = bestOffset;
252  bestOffset.addDouble(iteration);
253  offsetsPort.write();
254  }
255  // Resampling or not Resampling. That's the Question
256 
257  if(maxLikelihood>minimumLikelihood)
258  {
259  systematic_resampling(particles1to7,particles8,newParticles,cumWeight, sumLikelihood);
260  artifNoiseStdDev=artifNoiseStdDev*decreasedMultiplier;
261  }
262  else //I can't apply a resampling with all weights equal to 0!
263  {
264  cvCopy(particles,newParticles);
265  artifNoiseStdDev=artifNoiseStdDev*increasedMultiplier;
266  }
267  if(artifNoiseStdDev > upperBoundNoise)
268  {
269  artifNoiseStdDev = upperBoundNoise;
270  }
271  // Apply artificial Dynamics
272 
273  CvMat* A = cvCreateMat(8,8,CV_32FC1);
274  cvSetIdentity(A); //
275  cvMatMul(A,newParticles,particles);
276 
277  float mean = 0;
278  CvMat* noiseSingle;
279  noiseSingle = cvCreateMat(1,nParticles,CV_32FC1);
280  cvSetZero(noiseSingle);
281  if(artifNoiseStdDev < lowerBoundNoise) // lowerbound of artificial noise
282  {
283  artifNoiseStdDev = lowerBoundNoise;
284  }
285  cvRandArr( &rngState, noise, CV_RAND_NORMAL, cvScalar(mean), cvScalar(artifNoiseStdDev));
286  cvAdd(particles1to7,noise,particles1to7);
287  yInfo() << "ArtNoise: " << artifNoiseStdDev;
288  // Setting first particle as Zero offset
289  for (unsigned int joint=0;joint<8;joint++)
290  {
291  cvmSet(particles,joint,0,0.0);
292  }
293 
294  return true;
295 }
bool systematic_resampling(CvMat *oldParticlesState, CvMat *oldParticlesWeights, CvMat *newParticlesState, CvMat *cumWeight, float sum2)
perform the systematic resampling step of the SMC algorithm
void kernelDensityEstimation()
Perform the Kernel Density estimation with a multivariate gaussian kernel.
bool handPoseEstimationModule::start ( )
virtual

Start (re-start) the hand pose estimation.

The filter generates particles and update the particle distribution accordingly

Returns
true/false on success/failure

Reimplemented from handPoseEstimation_IDL.

Definition at line 644 of file handPoseEstimationModule.cpp.

645 {
646  iteration=0;
647  initSMC(); // Generated new particles
648  stopped = false;
649  yInfo("start command received");
650  return true;
651 }
bool initSMC()
Initialize the variables values for the SMC.
bool handPoseEstimationModule::stop ( )
virtual

Stop the hand pose estimation.

The filter stop the generation of particles and waits for a start command

Returns
true/false on success/failure

Reimplemented from handPoseEstimation_IDL.

Definition at line 653 of file handPoseEstimationModule.cpp.

654 {
655  stopped = true;
656  yInfo("stop command received");
657  return true;
658 
659 }
bool handPoseEstimationModule::systematic_resampling ( CvMat *  oldParticlesState,
CvMat *  oldParticlesWeights,
CvMat *  newParticlesState,
CvMat *  cumWeight,
float  sum2 
)
protected

perform the systematic resampling step of the SMC algorithm

Returns
true/false on success/failure

Definition at line 329 of file handPoseEstimationModule.cpp.

330 {
331  double u; //random number [0,1)
332  double sum;
333  int c1;
334  int rIndex; //index of the randomized array
335  int cIndex; //index of the cumulative weight array. cIndex -1 indicates which particle we think of resampling.
336  int npIndex; //%new particle index, tells me how many particles have been created so far.
337 
338  //%N is the number of particles.
339  //[lines, N] = size(oldParticlesWeight);
340  //in CPP, _nParticles is the number of particles.
341 
342 
343  //%NORMALIZE THE WEIGHTS, so that sum(oldParticles)=1.
344  //oldParticlesWeight = oldParticlesWeight / sum(oldParticlesWeight);
345  sum=0;
346 
347  for(c1=0;c1<nParticles;c1++)
348  {
349  ((float*)(oldParticlesWeights->data.ptr + oldParticlesWeights->step*0))[c1] = (((float*)(oldParticlesWeights->data.ptr + oldParticlesWeights->step*0))[c1])/(float)sum2;
350  }
351  for(c1=0;c1<nParticles;c1++)
352  {
353  sum+=((float*)(oldParticlesWeights->data.ptr + oldParticlesWeights->step*0))[c1];
354  }
355 
356  //%GENERATE N RANDOM VALUES
357  //u = rand(1)/N; %random value [0,1/N)
358  u=1/(double)nParticles*((double)rand()/(double)RAND_MAX);
359 
360  //%the randomized values are going to be u, u+1/N, u+2/N, etc.
361  //%instead of accessing this vector, the elements are computed on the fly:
362  //%randomVector(a)= (a-1)/N+u.
363 
364  ((float*)(cumWeight->data.ptr))[0]=0.0;
365  for(c1=0;c1<nParticles;c1++)
366  {
367  ((float*)(cumWeight->data.ptr))[c1+1]=((float*)(cumWeight->data.ptr))[c1]+((float*)(oldParticlesWeights->data.ptr + oldParticlesWeights->step*0))[c1];
368  }
369 
370  if(((float*)(cumWeight->data.ptr))[nParticles]!=1)
371  {
372  ((float*)(cumWeight->data.ptr))[nParticles]=1;
373  }
374 
375  //%PERFORM THE ACTUAL RESAMPLING
376  rIndex=0; //index of the randomized array
377  cIndex=1; //index of the cumulative weight array. cIndex -1 indicates which particle we think of resampling.
378  npIndex=0; //new particle index, tells me how many particles have been created so far.
379 
380  while(npIndex < nParticles)
381  {
382  if(((float*)(cumWeight->data.ptr))[cIndex]>=(double)rIndex/(double)nParticles+u) {
383  ((float*)(newParticlesState->data.ptr + newParticlesState->step*0))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*0))[cIndex-1];
384  ((float*)(newParticlesState->data.ptr + newParticlesState->step*1))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*1))[cIndex-1];
385  ((float*)(newParticlesState->data.ptr + newParticlesState->step*2))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*2))[cIndex-1];
386  ((float*)(newParticlesState->data.ptr + newParticlesState->step*3))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*3))[cIndex-1];
387  ((float*)(newParticlesState->data.ptr + newParticlesState->step*4))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*4))[cIndex-1];
388  ((float*)(newParticlesState->data.ptr + newParticlesState->step*5))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*5))[cIndex-1];
389  ((float*)(newParticlesState->data.ptr + newParticlesState->step*6))[npIndex]=((float*)(oldParticlesState->data.ptr + oldParticlesState->step*6))[cIndex-1];
390  ((float*)(newParticlesState->data.ptr + newParticlesState->step*7))[npIndex]=0; //initializing weight
391  rIndex=rIndex+1;
392  npIndex=npIndex+1;
393  }
394  else
395  {
396  cIndex=cIndex+1;
397  }
398  }
399  return false;
400 }

The documentation for this class was generated from the following files: