@@ -205,27 +205,29 @@ namespace pinocchio
205205 void calc (JointDataDerived & data, const typename Eigen::MatrixBase<ConfigVector> & qs) const
206206 {
207207 data.joint_q = qs.template segment <NQ>(idx_q ());
208+ int index_span = findSpan (qs);
209+ int first_index = index_span - degree;
210+
208211 // Basis functions and their derivatives
209212 data.N .setZero ();
210213 data.N_der .setZero ();
211- for (int i = 0 ; i < nbCtrlFrames ; i++)
214+ for (int i = first_index ; i < index_span + 1 ; i++)
212215 {
213216 data.N [i] = bsplineBasis (i, degree, data.joint_q [0 ]);
214217 data.N_der [i] = bsplineBasisDerivative (i, degree, data.joint_q [0 ]);
215218 }
216-
217219 // Compute joint transform M
218- data.M = ctrlFrames[0 ];
220+ data.M = ctrlFrames[first_index ];
219221 // joint subspace S
220222 data.S .matrix ().setZero ();
221- for (int i = 0 ; i < nbCtrlFrames - 1 ; ++i )
223+ for (int i = first_index + 1 ; i < index_span + 1 ; i++ )
222224 {
223- const Scalar phi_i = data.N .tail (nbCtrlFrames - ( i + 1 ) ).sum ();
224- const Scalar phi_dot_i = data.N_der .tail (nbCtrlFrames - ( i + 1 ) ).sum ();
225+ const Scalar phi_i = data.N .segment (i, index_span - i + 1 ).sum ();
226+ const Scalar phi_dot_i = data.N_der .segment (i, index_span - i + 1 ).sum ();
225227
226- data.M = data.M * exp6 (relativeMotions[i] * phi_i);
227- data.S .matrix () = exp6 (relativeMotions[i] * phi_i).actInv (data.S )
228- + relativeMotions[i].toVector () * phi_dot_i;
228+ data.M = data.M * exp6 (relativeMotions[i - 1 ] * phi_i);
229+ data.S .matrix () = exp6 (relativeMotions[i - 1 ] * phi_i).actInv (data.S )
230+ + relativeMotions[i - 1 ].toVector () * phi_dot_i;
229231 }
230232 }
231233
@@ -238,11 +240,14 @@ namespace pinocchio
238240 data.joint_q = qs.template segment <NQ>(idx_q ());
239241 data.joint_v = vs.template segment <NV>(idx_v ());
240242
243+ int index_span = findSpan (qs);
244+ int first_index = index_span - degree;
245+
241246 // Basis functions and their derivatives
242247 data.N .setZero ();
243248 data.N_der .setZero ();
244249 data.N_der2 .setZero ();
245- for (int i = 0 ; i < nbCtrlFrames; ++i )
250+ for (int i = first_index ; i < index_span + 1 ; i++ )
246251 {
247252 data.N [i] = bsplineBasis (i, degree, data.joint_q [0 ]);
248253 data.N_der [i] = bsplineBasisDerivative (i, degree, data.joint_q [0 ]);
@@ -252,20 +257,20 @@ namespace pinocchio
252257 // Compute time derivative of S (for bias acceleration c)
253258 data.S .matrix ().setZero ();
254259 data.c .setZero ();
255- data.M = ctrlFrames[0 ];
256- for (int i = 0 ; i < nbCtrlFrames - 1 ; ++i )
260+ data.M = ctrlFrames[first_index ];
261+ for (int i = first_index + 1 ; i < index_span + 1 ; i++ )
257262 {
258- const Scalar phi_i = data.N .tail (nbCtrlFrames - ( i + 1 ) ).sum ();
259- const Scalar phi_dot_i = data.N_der .tail (nbCtrlFrames - ( i + 1 ) ).sum ();
260- const Scalar phi_ddot_i = data.N_der2 .tail (nbCtrlFrames - ( i + 1 ) ).sum ();
263+ const Scalar phi_i = data.N .segment (i, index_span - i + 1 ).sum ();
264+ const Scalar phi_dot_i = data.N_der .segment (i, index_span - i + 1 ).sum ();
265+ const Scalar phi_ddot_i = data.N_der2 .segment (i, index_span - i + 1 ).sum ();
261266
262- data.M = data.M * exp6 (relativeMotions[i] * phi_i);
267+ data.M = data.M * exp6 (relativeMotions[i - 1 ] * phi_i);
263268 data.c =
264- relativeMotions[i] * phi_ddot_i
265- + exp6 (relativeMotions[i] * phi_i)
266- .actInv (data.c + Motion (data.S .matrix ()).cross (relativeMotions[i]) * phi_dot_i);
267- data.S .matrix () = exp6 (relativeMotions[i] * phi_i).actInv (data.S )
268- + relativeMotions[i].toVector () * phi_dot_i;
269+ relativeMotions[i - 1 ] * phi_ddot_i
270+ + exp6 (relativeMotions[i - 1 ] * phi_i)
271+ .actInv (data.c + Motion (data.S .matrix ()).cross (relativeMotions[i - 1 ]) * phi_dot_i);
272+ data.S .matrix () = exp6 (relativeMotions[i - 1 ] * phi_i).actInv (data.S )
273+ + relativeMotions[i - 1 ].toVector () * phi_dot_i;
269274 }
270275
271276 data.c = data.c * data.joint_v [0 ];
@@ -383,6 +388,29 @@ namespace pinocchio
383388 PINOCCHIO_ALIGNED_STD_VECTOR (Motion) relativeMotions;
384389
385390 private:
391+ template <typename ConfigVector>
392+ int findSpan (const typename Eigen::MatrixBase<ConfigVector> & qs) const
393+ {
394+ // Edge case
395+ if (qs[0 ] >= Scalar (1.0 ))
396+ return nbCtrlFrames - 1 ;
397+
398+ int low = degree;
399+ int high = nbCtrlFrames;
400+ int mid = low;
401+
402+ while (low < high)
403+ {
404+ mid = low + (high - low) / 2 ;
405+ if (qs[0 ] < knots[mid])
406+ high = mid;
407+ else
408+ low = mid + 1 ;
409+ }
410+
411+ return low - 1 ;
412+ }
413+
386414 Scalar bsplineBasis (int i, int k, const Scalar x) const
387415 {
388416 if (k == 0 )
0 commit comments