versor  3.0
C++11 library for Geometric algebra
vsr_linkages.h
Go to the documentation of this file.
1 /*
2  * =====================================================================================
3  *
4  * Filename: vsr_linkages.h
5  *
6  * Description: 3d linkages
7  *
8  * Version: 1.0
9  * Created: 02/10/2014 17:30:30
10  * Compiler: gcc4.7 or higher or clang 3.2 or higher
11  *
12  * Author: pablo colapinto
13  * Organization:
14  *
15  * =====================================================================================
16  */
17 
26 #ifndef vsr_linkages_INC
27 #define vsr_linkages_INC
28 
29 #include "vsr_chain.h"
30 
31 namespace vsr{ namespace cga {
32 
48  class Bennett : public Chain {
49 
50  VSR_PRECISION mLengthA;
51  VSR_PRECISION mLengthB;
52 
53  VSR_PRECISION mOffsetA;
54  VSR_PRECISION mOffsetB;
55 
56  VSR_PRECISION mTheta;
57  VSR_PRECISION mPhi;
58 
59  VSR_PRECISION mPhase;
60 
61  public:
62 
63  Bennett() : Chain() {}
64 
65  Bennett( VSR_PRECISION theta, VSR_PRECISION lengthA, VSR_PRECISION lengthB )
66  : Chain("RRRR"), mTheta(theta), mLengthA( lengthA ), mLengthB( lengthB ), mPhase(0) {
67  init();
68  }
69 
70  Bennett( VSR_PRECISION theta, VSR_PRECISION lengthA, VSR_PRECISION lengthB, VSR_PRECISION offset )
71  : Chain("RRRR"), mTheta(theta), mLengthA( lengthA ), mLengthB( lengthB ), mOffsetA(offset), mOffsetB(offset), mPhase(0) {
72  init();
73  }
74 
75 
76  void set( VSR_PRECISION theta, VSR_PRECISION lengthA, VSR_PRECISION lengthB, VSR_PRECISION offset=0.0){
77  mTheta = theta; mLengthA = lengthA; mLengthB = lengthB; mOffsetA = offset; mOffsetB = offset;
78  init();
79  }
80 
81  void init() {
82 
83  mPhi = asin( sin(mTheta) * mLengthB / mLengthA);
84 
85  mLink[0].pos(0,mLengthA, 0);//mOffsetA);
86  mLink[2].pos(0,mLengthA, 0);//mOffsetA);
87 
88  mLink[1].pos(0,mLengthB, 0);//mOffsetB);
89  mLink[3].pos(0,mLengthB, 0);//mOffsetB);
90 
91  Biv la = Biv::xz * mTheta/2.0;
92  Biv lb = Biv::xz * mPhi/2.0;
93 
94  mLink[0].rot() = Gen::rot(la);
95  mLink[2].rot() = Gen::rot(la);
96 
97  mLink[1].rot() = Gen::rot(-lb);
98  mLink[3].rot() = Gen::rot(-lb);
99 
100  }
101 
102  VSR_PRECISION lengthA() const { return mLengthA; }
103  VSR_PRECISION lengthB() const { return mLengthB; }
104  VSR_PRECISION& lengthA() { return mLengthA; }
105  VSR_PRECISION& lengthB() { return mLengthB; }
106 
107 
108  VSR_PRECISION offsetA() const { return mOffsetA; }
109  VSR_PRECISION offsetB() const { return mOffsetB; }
110  VSR_PRECISION& offsetA() { return mOffsetA; }
111  VSR_PRECISION& offsetB() { return mOffsetB; }
112 
113  VSR_PRECISION theta() const { return mTheta; }
114  VSR_PRECISION phi() const { return mPhi; }
115 
120  return ( nextSphere(1) ^ prevSphere(3) ).dual();//Round::dls(mFrame[1].pos(), mLengthB) ^ Round::dls(mFrame[3].pos(), mLengthA) ).dual();
121  }
122 
123  Pair pairMeet(){
124  return ( nextPlane(1) ^ circleMeet().dual() ).dual();
125  }
126 
127  Circle orbit(){
128  return ( nextPlane(3) ^ prevSphere(0) ).dual();//( mFrame[3].dxy() ^ Round::dls( mJoint[0].pos(), mLengthB ) ).dual();
129  }
130 
131 
132  /*-----------------------------------------------------------------------------
133  * Eval
134  *-----------------------------------------------------------------------------*/
135  Bennett& operator()( VSR_PRECISION amt ){
136 
137  mPhase = amt;
138  bool bSwitch = sin(amt) < 0 ? true : false;
139 
140  resetJoints();
141 
142  mJoint[0].rot() = Gen::rot( Biv::xy * amt/2.0 );
143  fk(1);
144 
145  mFrame[3].mot( mBaseFrame.mot() * !mLink[3].mot() );
146 
147  //calculate intersection
148  //auto dualMeet = nextSphere(1) ^ prevSphere(3);
149  auto dualMeet = nga::Round::dls_pnt(mFrame[1].pos(), mLengthB) ^ nga::Round::dls_pnt(mFrame[3].pos(), mLengthA);
150  //Pair p = (nextPlane(1)^dualMeet).dual();
151  Pair p = ( mFrame[1].dxy() ^ dualMeet).dual();
152 
153  //pick one
154  mFrame[2].pos() = Round::location( Round::split(p, !bSwitch) );
155 
156  Rot ry = mFrame[1].rot();
157  for (int i = 1; i < 4; ++i){
158  Vec y = Vec::y.spin(ry);
159  int next = i < 3 ? i + 1 : 0;
160  auto target = mFrame[next].vec();
161 
162  auto linkRot = Gen::ratio( mLink[i].vec().unit(), Vec::y );
163 
164  Vec dv = (target-mFrame[i].vec()).unit().spin( linkRot );
165 
166  //mJoint[i].rot() = Gen::ratio(y,dv);
167  mJoint[i].rot() = Gen::rot( Biv::xy * acos( ( dv <= y )[0] )/2.0 * (bSwitch ? -1 : 1 ) );
168 
169  // ry = mJoint[i].rot() * ry;
170  ry = ry * mJoint[i].rot() * mLink[i].rot();
171  }
172 
173  // calcJoints(1,true);
174 
175  fk();
176 
177  return *this;
178  }
179 
180 
181 
185  Bennett linkRatio(VSR_PRECISION th, VSR_PRECISION a = .5, VSR_PRECISION b =.5, VSR_PRECISION la = 0, VSR_PRECISION lb = 0){
186 
187  Bennett b2(mTheta * th, mLengthA * a, mLengthB * b);
188  b2.baseFrame() = Frame( mFrame[2].mot() * !mJoint[2].rot() );
189 
190  b2(mPhase);
191 
192  if (la==0) la = mLengthA; //else la = mLengthA;
193  if (lb==0) lb = mLengthB; //else lb *= mLengthB;
194 
195  Bennett b3(mTheta * th, la, lb);
196 
197  b3.baseFrame() = Frame( b2[2].mot() * !b2.joint(2).rot() );
198 
199  return b3( nga::Gen::iphi( b2.joint(2).rot() ) );
200 
201  }
202 
215  Bennett linkAt(int N=2, VSR_PRECISION th=1, VSR_PRECISION a = .5, VSR_PRECISION b =.5, VSR_PRECISION la = 0, VSR_PRECISION lb = 0){
216 
217  //necessary boolean to reverse direction
218  bool bSwitch = sin(mPhase) < 0 ? true : false;
219 
220  //make linkage relative to original
221  Bennett b2(mTheta * th, mLengthA * a, mLengthB * b);
222  //set baseframe of new linkage to nth frame and undo local in-socket transformation
223  b2.baseFrame() = Frame( mFrame[N].mot() * !mJoint[N].rot() );
224  //set phase of new linkage mechanism from nth joint's rotation
225  b2( bSwitch ? -nga::Gen::iphi( mJoint[N].rot()) : nga::Gen::iphi( mJoint[N].rot() ) );
226  //use linkAt_ to debug this point
227 
228  if (la==0) la = mLengthA; //else la = mLengthA;
229  if (lb==0) lb = mLengthB; //else lb *= mLengthB;
230 
231  //repeat
232  Bennett b3(mTheta * th, la, lb);
233  b3.baseFrame() = Frame( b2[2].mot() * !b2.joint(2).rot() );
234  for (int i=0;i<b3.num();++i){
235  b3[i].scale() = (*this)[i].scale();
236  }
237  return b3( bSwitch ? -nga::Gen::iphi( b2.joint(2).rot() ) : nga::Gen::iphi( b2.joint(2).rot() ) );
238 
239  }
240 
241  //alt
242  Bennett linkAt_(int N, VSR_PRECISION th=1, VSR_PRECISION a = .5, VSR_PRECISION b =.5, VSR_PRECISION la = 0, VSR_PRECISION lb = 0){
243 
244  bool bSwitch = sin(mPhase) < 0 ? true : false;
245 
246  Bennett b2(mTheta * th, mLengthA * a, mLengthB * b);
247  //set baseframe to nth frame and undo local transformation
248  b2.baseFrame() = Frame( mFrame[N].mot() * !mJoint[N].rot() );
249  //set phase of new linkage mechanism from nth joint's rotation
250  return b2( bSwitch ? -nga::Gen::iphi( mJoint[N].rot()) : nga::Gen::iphi( mJoint[N].rot() ) );
251 
252  }
253 
254  };
255 
256 
257 
261  class Pantograph {
262 
263  Chain mChainA, mChainB;
264 
265  VSR_PRECISION mRatio, mDecay;
266 
267  public:
268 
269  Pantograph(int n=1) : mChainA(n), mChainB(n), mRatio(1), mDecay(0)
270  {
271  }
272 
273  void alloc(int n) { mChainA.alloc(n); mChainB.alloc(n); }
274  void reset(){ mChainA.reset(); mChainB.reset(); }
275  void fk() { mChainA.fk(); mChainB.fk(); }
276 
277  void ratio(VSR_PRECISION amt) { mRatio = amt; }
278  void decay(VSR_PRECISION amt) { mDecay = amt; }
279 
280  VSR_PRECISION ratio() const { return mRatio; }
281  VSR_PRECISION decay() const { return mDecay; }
282 
283  void operator()() {
284 
285  bool flip = false;
286  VSR_PRECISION tRatio = mRatio;
287 
288  mChainA.fk();
289  mChainB.fk();
290 
291  Dlp dlp = mChainA[0].dxy().unit(); // /Dual xy plane
292 
293  for (int i = 0; i < mChainA.num(); i+=2 ){
294 
295  Dls da = mChainA.nextSphere(i);
296  Dls db = mChainB.nextSphere(i);
297 
298  Dls ta = flip ? da : da.dil( mChainA[i].pos(), log(tRatio) );
299  Dls tb = !flip ? db : db.dil( mChainB[i].pos(), log(tRatio) );
300 
301  Par tp = ta ^ tb;
302  bool isLegit = Round::size( tp, true ) > 0;
303 
304  if ( isLegit ){
305 
306  Par p = ( ta ^ tb ^ dlp ).dual();
307  Pnt pnt = Round::split(p,flip);
308 
309  mChainA[i+1].pos() = pnt;
310  mChainB[i+1].pos() = pnt;
311 
312  double a = ( 1.0 / tRatio );
313  double b = tRatio;
314 
315  if (i < mChainA.num() - 2){
316  mChainA[i+2].pos() = Round::null( mChainA[i].vec() +
317  ( ( mChainA[i+1].vec() - mChainA[i].vec() ) * (1 + ( (flip) ? b : a ) ) ) );
318  mChainB[i+2].pos() = Round::null( mChainB[i].vec() +
319  ( ( mChainB[i+1].vec() - mChainB[i].vec() ) * (1 + ( (flip) ? a : b ) ) ) );
320  }
321 
322  flip = !flip;
323 
324  tRatio *= (1-mDecay);
325  }
326  }
327 
328  mChainA.calcJoints();
329  mChainB.calcJoints();
330 
331  }
332 
333  Chain& chainA() { return mChainA; }
334  Chain& chainB() { return mChainB; }
335 
336  };
337 
338 
339 } }
340 
341 #endif /* ----- #ifndef vsr_linkages_INC ----- */
static std::vector< Point > split(const Pair &pp)
Split Points from Point Pair.
Bennett linkAt(int N=2, VSR_PRECISION th=1, VSR_PRECISION a=.5, VSR_PRECISION b=.5, VSR_PRECISION la=0, VSR_PRECISION lb=0)
A linked Bennett mechanism at joint N determined by ratio of original We first create a sublinkage in...
Definition: vsr_linkages.h:215
void calcJoints(int start=0, bool bLoop=false)
Derive Joint Rotations from Current Positions.
Definition: vsr_chain.h:531
NVec< 5 > Vec
Vector
Definition: vsr_cga3D_types.h:62
Point pos() const
Get Position.
Definition: vsr_cga3D_frame.h:138
Multivector spin(const MultivectorB< B > &b) const
Rotor (even) transformation \(RA\tilde{R}\)
Definition: vsr_multivector.h:178
Mot mot() const
Get Absolute Motor Relative to Origin.
Par Pair
Point Pair 2-blade \(\tau=p_a \wedge p_b=\{e_{12},e_{13},e_{23},e_{1}n_o,e_{2}n_o,e_{3}n_o,e_{1}n_\infty,e_{2}n_\infty,e_{3}n_\infty,n_{o}n_\infty\}\)
Definition: vsr_cga3D_types.h:129
PANTOGRAPH for scissor-like kinematics.
Definition: vsr_linkages.h:261
Vec y() const
Local y.
Generic Geometric Number Types (templated on an algebra and a basis )
Definition: vsr_algebra.h:69
static Rot rot(const Biv &b)
vsr::cga::Rotor from vsr::cga::Bivector
The bennett 4 bar linkage.
Definition: vsr_linkages.h:48
Dlp dxy() const
xy dual plane
Frame & scale(VSR_PRECISION s)
Set Scale.
Definition: vsr_cga3D_frame.h:83
vector< Frame > mFrame
Absolute frames of Joints = prevFrame * prevLink * joint.
Definition: vsr_chain.h:118
Dlp nextPlane(int k) const
Dual Plane of rotation of kth joint (translated by link rejection from yz)
Definition: vsr_chain.h:261
Vec vec() const
Get Euclidean Vector of position.
Definition: vsr_cga3D_frame.h:142
static Point location(const A &s)
Location (normalized) of A Round Element (normalized) (Shorthand)
Definition: vsr_cga3D_round.h:136
Dls nextSphere(int k) const
Sphere Centered at Joint K Going Through Joint K+1.
Definition: vsr_chain.h:252
Cir Circle
Direct Circle 3-blade \(\kappa=p_a \wedge p_b \wedge p_c\)
Definition: vsr_cga3D_types.h:130
void fk()
Forward Kinematics: Absolute Concatenations of previous frame, previous link, and current joint...
Definition: vsr_chain.h:335
Frame()
Default Constructor.
Frame & mot(const Mot &m)
Set position and orientation by motor (absolute)
A sequence of spatial Frames.
Definition: vsr_chain.h:107
vector< Frame > mLink
Relative Link to NEXT joint.
Definition: vsr_chain.h:116
Dls prevSphere(int k) const
Sphere Centered at Joint K Going Through Joint K-1.
Definition: vsr_chain.h:256
static VSR_PRECISION iphi(const GARot< A > &r)
Angle of Rotation from Rotor.
Definition: vsr_generic_op.h:339
static Rot ratio(const Vec &v, const Vec &v2)
vsr::cga::Rotor that takes one vec to another
Circle circleMeet()
Meet of 1st and 3rd spheres of possibilities.
Definition: vsr_linkages.h:119
the versor library namespace
Definition: vsr_algebra.h:29
Rotor rot() const
Get 4x4 Rotation Matrix.
Definition: vsr_cga3D_frame.h:97
static VSR_PRECISION size(const DualSphere &s, bool bDual=true)
Squared Size of a DualSphere (result could be negative)
Frame & joint(int k)
set kth joint's In Socket Transformation
Definition: vsr_chain.h:236
Frame mBaseFrame
default zero, to tie chains together, set this to another chain's frame.
Definition: vsr_chain.h:111
vector< Frame > mJoint
In Socket Transformation (RDHC, etc) SET THIS directly using joint(i) (all others follow after callin...
Definition: vsr_chain.h:113
static Point null(const Vec &v)
Null Point from a vec.
Bennett linkRatio(VSR_PRECISION th, VSR_PRECISION a=.5, VSR_PRECISION b=.5, VSR_PRECISION la=0, VSR_PRECISION lb=0)
A linked Bennett mechanism, determined by ratio of original.
Definition: vsr_linkages.h:185
static GADls< A > dls_pnt(const GAPnt< A > &p, VSR_PRECISION r=1.0)
Dual Sphere from Point and Radius (faster)
Definition: vsr_generic_op.h:630
NRot< 5 > Rot
Rotor
Definition: vsr_cga3D_types.h:64