grasp
All Data Structures Namespaces Functions Modules
forceClosure.cpp
1 #include <iCub/grasp/forceClosure.h>
2 
3 using namespace std;
4 using namespace yarp::os;
5 using namespace yarp::sig;
6 using namespace yarp::math;
7 using namespace iCub::ctrl;
8 
9 static double cross2D(const Vector &v1, const Vector &v2)
10 {
11  return (v1[0]*v2[1])-(v1[1]*v2[0]);
12 }
13 
14 static bool included(double cosine, double angle)
15 {
16  double alpha1=(M_PI/2)+angle;
17  double alpha2=(M_PI/2)-angle;
18 
19  double cosMin=cos(alpha1);
20  double cosMax=cos(alpha2);
21 
22  return (cosine>cosMin)&&(cosine<cosMax);
23 }
24 
25 static bool computeIntersectionPoint(const yarp::sig::Vector &line1, const yarp::sig::Vector &line2, yarp::sig::Vector &point)
26 {
27  point.resize(2,0.0);
28  if (line2[0]-line1[0]==0)
29  return false;
30  point[0]=(line1[1]-line2[1])/(line2[0]-line1[0]);
31  point[1]=(line1[0]*point[0])+line1[1];
32  return true;
33 }
34 
35 static yarp::sig::Vector projectVectorOnThePlane(const yarp::sig::Vector &v, const yarp::sig::Vector &plane)
36 {
37  yarp::sig::Vector projection=v-(dot(v,plane)*plane);
38  projection/=norm(projection);
39  return projection;
40 }
41 
42 static void computeLineParameters(const Vector &x1, const Vector &x2, Vector &line)
43 {
44  line.resize(2,0.0);
45  line[0]=1.0e+10;
46 
47  if ((x2[0]-x1[0])!=0.0)
48  line[0]=(x2[1]-x1[1])/(x2[0]-x1[0]);
49 
50  line[1]=x1[1]-(line[0]*x1[0]);
51 }
52 
53 static bool pointInCone(const vector<Vector> &a1, const vector<Vector> &a2, const vector<Vector> &a3, const yarp::sig::Vector &c)
54 {
55  Vector intersectionPoint(2);
56  for (unsigned int i=0; i<a1.size(); i++)
57  {
58  for (unsigned int j=0; j<a2.size(); j++)
59  {
60  if (computeIntersectionPoint(a1[i],a2[j],intersectionPoint))
61  {
62  if (sign(cross2D(intersectionPoint-c,a3.at(0)))*sign(cross2D(intersectionPoint-c,a3.at(1)))<0)
63  return true;
64  }
65  }
66  }
67  return false;
68 }
69 
70 static yarp::sig::Vector transformVector(const yarp::sig::Vector &v, const yarp::sig::Matrix &orientation)
71 {
72  return orientation.submatrix(0,2,0,2).transposed()*v;
73 }
74 
75 static yarp::sig::Vector transformPoint(const yarp::sig::Vector &p, const yarp::sig::Matrix &orientation)
76 {
77  Vector pHom(4); pHom[3]=1.0;
78  pHom.setSubvector(0,p);
79  return (SE3inv(orientation)*pHom).subVector(0,2);
80 }
81 
82 static bool verifySameHalfPlane(const Vector &normal1, const Vector &normal2, const Vector &normal3)
83 {
84  Vector line1;
85  Vector line2;
86  Vector line3;
87 
88  Vector tmp(2); tmp=0.0;
89 
90  computeLineParameters(normal1,tmp,line1);
91  computeLineParameters(normal2,tmp,line2);
92  computeLineParameters(normal3,tmp,line3);
93 
94  //Sign with respect to the line on which vector normal1 lies
95  double signv2=sign(normal2[1]-(line1[0]*normal2[0])-line1[1]);
96  double signv3=sign(normal3[1]-(line1[0]*normal3[0])-line1[1]);
97 
98  if ((signv2==signv3)||(signv2==0)||(signv3==0))
99  return false;
100 
101  //Sign with respect to the line on which vector normal2 lies
102  double signv1=sign(normal1[1]-(line2[0]*normal1[0])-line2[1]);
103  signv3=sign(normal3[1]-(line2[0]*normal3[0])-line2[1]);
104 
105  if ((signv1==signv3)||(signv1==0)||(signv3==0))
106  return false;
107 
108  //Sign with respect to the line on which vector normal3 lies
109  signv1=sign(normal1[1]-(line3[0]*normal1[0])-line3[1]);
110  signv2=sign(normal2[1]-(line3[0]*normal2[0])-line3[1]);
111 
112  if ((signv1==signv2)||(signv1==0)||(signv2==0))
113  return false;
114 
115  return true;
116 }
117 
118 static bool verifyConesIntersection(const yarp::sig::Vector &c1, const yarp::sig::Vector &c2, const yarp::sig::Vector &c3, const std::vector<iCub::grasp::ConeBounds> &conesBounds2D)
119 {
120  Vector line11, line12, line21, line22, line31, line32;
121 
122  computeLineParameters(c1+conesBounds2D.at(0).n1,c1,line11);
123  computeLineParameters(c1+conesBounds2D.at(0).n2,c1,line12);
124 
125  vector<Vector> a1; a1.push_back(line11); a1.push_back(line12);
126  computeLineParameters(c2+conesBounds2D.at(1).n1,c2,line21);
127  computeLineParameters(c2+conesBounds2D.at(1).n2,c2,line22);
128 
129  vector<Vector> a2; a2.push_back(line21);a2.push_back(line22);
130  computeLineParameters(c3+conesBounds2D.at(2).n1,c3,line31);
131  computeLineParameters(c3+conesBounds2D.at(2).n2,c3,line32);
132 
133  vector<Vector> a3; a3.push_back(line31); a3.push_back(line32);
134 
135  if (pointInCone(a1,a2,a3,c3))
136  return true;
137  if (pointInCone(a1,a3,a2,c2))
138  return true;
139  if (pointInCone(a2,a3,a1,c1))
140  return true;
141 
142  return false;
143 }
144 
145 static Matrix findOrientationForPlane(const iCub::grasp::ContactPoints &contactPoints, const Vector &plane)
146 {
147  Vector projection1=projectVectorOnThePlane(contactPoints.n1,plane);
148  Vector c=(contactPoints.c1+contactPoints.c2+contactPoints.c3)/3;
149 
150  Vector z=plane;
151  Vector x=projection1;
152  Vector y=cross(plane,x); y/=norm(y);
153 
154  Matrix orientation=eye(4,4);
155  orientation(0,0)=x[0]; orientation(1,0)=x[1]; orientation(2,0)=x[2];
156  orientation(0,1)=y[0]; orientation(1,1)=y[1]; orientation(2,1)=y[2];
157  orientation(0,2)=z[0]; orientation(1,2)=z[1]; orientation(2,2)=z[2];
158  orientation(0,3)=c[0]; orientation(1,3)=c[1]; orientation(2,3)=c[2];
159 
160  return orientation;
161 }
162 
163 static yarp::sig::Vector solveForT(const double &a, const double &b, const double &c)
164 {
165  yarp::sig::Vector t(2);
166  double normFact=sqrt((a*a)+(b*b));
167  double alpha=acos(a/normFact);
168 
169  if (abs(sin(alpha)-(b/normFact))>0.0001)
170  alpha=-alpha;
171 
172  double x0=asin(c/normFact);
173  double x1=M_PI-asin(c/normFact);
174 
175  t[0]=x0-alpha;
176  t[1]=x1-alpha;
177 
178  return t;
179 }
180 
181 static iCub::grasp::ConeBounds findConeBounds(const yarp::sig::Vector &c, const yarp::sig::Vector &n, const yarp::sig::Vector &plane, double alpha)
182 {
183  iCub::grasp::ConeBounds coneBounds;
184  //center of the circle at cone height=1
185  yarp::sig::Vector c0=c+n;
186  //vector to project on the plane where the circle lies to create a basis
187  yarp::sig::Vector tmp(3); tmp[0]=1.0; tmp[1]=0.0; tmp[2]=0.0;
188  //basis for the plane where the circle lies
189  yarp::sig::Vector x=projectVectorOnThePlane(tmp,n); x/=norm(x);
190  yarp::sig::Vector y=cross(n,x); y/=norm(y);
191 
192  //radius of the circle when the height of the cone is 1
193  double r=tan(alpha);
194 
195  //values to solve the system between the circle and the fact that the line between the point
196  //on the circle and the contact point must belongs to the plane
197  double A=r*dot(x,plane);
198  double B=r*dot(y,plane);
199  double C=(dot(c,plane))-(dot(c0,plane));
200 
201  //Finds the angle to which the circle meets the plane on two points
202  yarp::sig::Vector t=solveForT(A,B,C);
203 
204  //Two points on the circle where it meets the plane
205  yarp::sig::Vector P1=c0+(r*sin(t[0])*x)+(r*cos(t[0])*y);
206  yarp::sig::Vector P2=c0+(r*sin(t[1])*x)+(r*cos(t[1])*y);
207 
208  //Cone bound vectors
209  coneBounds.n1=(P1-c)/norm(P1-c);
210  coneBounds.n2=(P2-c)/norm(P2-c);
211 
212  return coneBounds;
213 }
214 
215 static bool verifyCondition2D(const iCub::grasp::ContactPoints &contactPoints, const Vector &plane, const std::vector<iCub::grasp::ConeBounds> &conesBounds)
216 {
217  Matrix orientation=findOrientationForPlane(contactPoints,plane);
218 
219  Vector projection1=projectVectorOnThePlane(contactPoints.n1,plane);
220  Vector projection2=projectVectorOnThePlane(contactPoints.n2,plane);
221  Vector projection3=projectVectorOnThePlane(contactPoints.n3,plane);
222 
223  Vector n1=transformVector(projection1,orientation);
224  Vector n2=transformVector(projection2,orientation);
225  Vector n3=transformVector(projection3,orientation);
226 
227  Vector c1=(transformPoint(contactPoints.c1,orientation)).subVector(0,1);
228  Vector c2=(transformPoint(contactPoints.c2,orientation)).subVector(0,1);
229  Vector c3=(transformPoint(contactPoints.c3,orientation)).subVector(0,1);
230 
231  std::vector<iCub::grasp::ConeBounds> conesBounds2D;
232  for (unsigned int i=0; i<conesBounds.size(); i++)
233  {
234  iCub::grasp::ConeBounds tmp;
235  tmp.n1=(transformVector(conesBounds[i].n1,orientation)).subVector(0,1);
236  tmp.n2=(transformVector(conesBounds[i].n2,orientation)).subVector(0,1);
237  conesBounds2D.push_back(tmp);
238  }
239 
240  return verifySameHalfPlane(n1,n2,n3)&&verifyConesIntersection(c1,c2,c3,conesBounds2D);
241 }
242 
243 bool iCub::grasp::isForceClosure(const iCub::grasp::ContactPoints &contactPoints)
244 {
245  Vector diff1=contactPoints.c1-contactPoints.c2;
246  Vector diff2=contactPoints.c1-contactPoints.c3;
247 
248  //Plane formed by the three contact points
249  Vector plane=cross(diff2,diff1); plane/=norm(plane);
250 
251  double cos1=(dot(plane,contactPoints.n1));
252  double cos2=(dot(plane,contactPoints.n2));
253  double cos3=(dot(plane,contactPoints.n3));
254 
255  //The friction cone does not meet the plane on a plane
256  if (!included(cos1,contactPoints.alpha1) || !included(cos2,contactPoints.alpha2) || !included(cos3,contactPoints.alpha3))
257  return false;
258 
259  ConeBounds bounds1=findConeBounds(contactPoints.c1,contactPoints.n1,plane,contactPoints.alpha1);
260  ConeBounds bounds2=findConeBounds(contactPoints.c2,contactPoints.n2,plane,contactPoints.alpha2);
261  ConeBounds bounds3=findConeBounds(contactPoints.c3,contactPoints.n3,plane,contactPoints.alpha3);
262 
263  std::vector<ConeBounds> conesBounds;
264  conesBounds.push_back(bounds1);
265  conesBounds.push_back(bounds2);
266  conesBounds.push_back(bounds3);
267 
268  return verifyCondition2D(contactPoints,plane,conesBounds);
269 }
270 
271 
Definition of the ForceClosure.
Definition: forceClosure.h:60