Skip to content

Commit 27b5d32

Browse files
committed
Start of Eigen/C++ version, not complete
1 parent a87c55a commit 27b5d32

File tree

1 file changed

+399
-0
lines changed

1 file changed

+399
-0
lines changed

mex/ne.cpp

Lines changed: 399 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,399 @@
1+
/**
2+
* \file ne.c
3+
* \author Peter Corke
4+
* \brief Compute the recursive Newton-Euler formulation
5+
*/
6+
7+
/*
8+
* Copyright (C) 1999-2008, by Peter I. Corke
9+
*
10+
* This file is part of The Robotics Toolbox for Matlab (RTB).
11+
*
12+
* RTB is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Lesser General Public License as published by
14+
* the Free Software Foundation, either version 3 of the License, or
15+
* (at your option) any later version.
16+
*
17+
* RTB is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Lesser General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Leser General Public License
23+
* along with RTB. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
/*
28+
* Compute the inverse dynamics via the recursive Newton-Euler formulation
29+
*
30+
* Requires: qd current joint velocities
31+
* qdd current joint accelerations
32+
* f applied tip force or load
33+
* grav the gravitational constant
34+
*
35+
* Returns: tau vector of bias torques
36+
*/
37+
#include "frne2.h"
38+
#include <iostream>
39+
#include <Eigen/Dense>
40+
41+
using namespace Eigen;
42+
43+
/*
44+
#define DEBUG
45+
*/
46+
47+
/*
48+
* Bunch of macros to make the main code easier to read. Dereference vectors
49+
* from the Link structures for the manipulator.
50+
*
51+
* Note that they return pointers (except for M(j) which is a scalar)
52+
*/
53+
#undef N
54+
55+
#define w(j) (&links[j].omega) /* angular velocity */
56+
#define wd(j) (&links[j].omega_d) /* angular acceleration */
57+
#define a(j) (&links[j].acc) /* linear acceleration */
58+
#define acc_cog(j) (&links[j].abar) /* linear acceln of COG */
59+
60+
#define f(j) (&links[j].f) /* force on link j due to link j-1 */
61+
#define n(j) (&links[j].n) /* torque on link j due to link j-1 */
62+
63+
#define R(j) (&links[j].R) /* link rotation matrix */
64+
#define M(j) (links[j].m) /* link mass */
65+
#define PSTAR(j) (&links[j].r) /* offset link i from link (j-1) */
66+
#define r_cog(j) (links[j].rbar) /* COG link j wrt link j */
67+
#define I(j) (links[j].I) /* inertia of link about COG */
68+
69+
/**
70+
* Recursive Newton-Euler algorithm.
71+
*
72+
* @Note the parameter \p stride which is used to allow for input and output
73+
* arrays which are 2-dimensional but in column-major (Matlab) order. We
74+
* need to access rows from the arrays.
75+
*
76+
*/
77+
void
78+
newton_euler (
79+
Robot *robot, /*!< robot object */
80+
double *tau, /*!< returned joint torques */
81+
double *qd, /*!< joint velocities */
82+
double *qdd, /*!< joint accelerations */
83+
double *fext, /*!< external force on manipulator tip */
84+
int stride /*!< indexing stride for qd, qdd */
85+
) {
86+
Map<Vector3d> gravity(robot->gravity);
87+
Vector3d qdv = Vector3d::Zero();
88+
Vector3d qddv = Vector3d::Zero();
89+
Vector3d F, N;
90+
Vector3d z0 = Vector3d::UnitZ();
91+
Vector3d zero = Vector3d::Zero();
92+
register int j;
93+
double t;
94+
Link *links = robot->links;
95+
96+
/*
97+
* angular rate and acceleration vectors only have finite
98+
* z-axis component
99+
*/
100+
qdv = qddv = zero;
101+
102+
/* setup external force/moment vectors */
103+
if (fext) {
104+
Vector3d f_tip(&fext[0]);
105+
Vector3d n_tip(&fext[3]);
106+
} else
107+
{
108+
Vector3d f_tip = Vector3d::Zero();
109+
Vector3d n_tip = Vector3d::Zero();
110+
}
111+
112+
113+
/******************************************************************************
114+
* forward recursion --the kinematics
115+
******************************************************************************/
116+
117+
if (robot->dhtype == MODIFIED) {
118+
/*
119+
* MODIFIED D&H CONVENTIONS
120+
*/
121+
for (j = 0; j < robot->njoints; j++) {
122+
123+
/* create angular vector from scalar input */
124+
qdv.z() = qd[j*stride];
125+
qddv.z() = qdd[j*stride];
126+
127+
switch (links[j].sigma) {
128+
case REVOLUTE:
129+
/*
130+
* calculate angular velocity of link j
131+
*/
132+
if (j == 0)
133+
w(j) = qdv;
134+
else {
135+
w(j) = R(j) * w(j-1) + qdv;
136+
}
137+
138+
/*
139+
* calculate angular acceleration of link j
140+
*/
141+
if (j == 0)
142+
wd(j) = qddv;
143+
else {
144+
wd(j) = qdv.cross(R(j) * w(j-1)) + R(j) * wd(j-1)) + qddv;
145+
}
146+
147+
/*
148+
* compute acc[j]
149+
*/
150+
if (j == 0) {
151+
a(j) = R(j) * gravity;
152+
} else {
153+
a(j) = a(j-1) + wd(j-1).cross(PSTAR(j)) + w(j-1).cross(w(j-1).cross(PSTAR(j)));
154+
}
155+
156+
break;
157+
158+
case PRISMATIC:
159+
/*
160+
* calculate omega[j]
161+
*/
162+
if (j == 0)
163+
w[j] = qdv;
164+
else
165+
w[j] = R[j] * w[j-1];
166+
167+
/*
168+
* calculate alpha[j]
169+
*/
170+
if (j == 0)
171+
*(wd(j)) = qddv;
172+
wd = qddv;
173+
else
174+
wd = R[j] * wd[j-1]l
175+
176+
/*
177+
* compute acc[j]
178+
*/
179+
if (j == 0)
180+
a[j] = gravity;
181+
else
182+
a[j] = R[j] * (w[j-1].cross(w[j-1], PSTAR[j]) + wd[j-1].cross(PSTAR[j]) + a[j-1]) +
183+
184+
2*(R[j]*w[j-1]).cross(qdv) + qddv;
185+
}
186+
break;
187+
}
188+
189+
/*
190+
* compute abar[j]
191+
*/
192+
acc_cog[j] = wd[j].cross(r_cog[j]) + w[j].cross(w[j].cross(r_cog[j]));
193+
acc_cog[j] += a[j];
194+
195+
#ifdef DEBUG
196+
vect_print("w", w(j));
197+
vect_print("wd", wd(j));
198+
vect_print("acc", a(j));
199+
vect_print("abar", acc_cog(j));
200+
#endif
201+
}
202+
} else {
203+
/*
204+
* STANDARD D&H CONVENTIONS
205+
*/
206+
for (j = 0; j < robot->njoints; j++) {
207+
208+
/* create angular vector from scalar input */
209+
qdv.z() = qd[j*stride];
210+
qddv.z() = qdd[j*stride];
211+
212+
switch (links[j].sigma) {
213+
case REVOLUTE:
214+
/*
215+
* calculate omega[j]
216+
*/
217+
if (j == 0)
218+
w[j] = R[j] * qdv;
219+
else
220+
w[j] = R[j] * (w[j-1] + qdv);
221+
222+
/*
223+
* calculate alpha[j]
224+
*/
225+
if (j == 0)
226+
wd[j] = R[j] * qddv;
227+
else {
228+
wd[j] = wd[j-1] + qddv + w[j-1].cross(qdv);
229+
}
230+
231+
/*
232+
* compute acc[j]
233+
*/
234+
a[j] = wd[j].cross(PSTAR[j]) + w[j].cross(w[j].cross(PSTAR[j]));
235+
if (j == 0) {
236+
a[j] += R[j] * gravity;
237+
} else
238+
a[j] += R[j] * a[j-1];
239+
break;
240+
241+
case PRISMATIC:
242+
/*
243+
* calculate omega[j]
244+
*/
245+
if (j == 0)
246+
w[j] = zero;
247+
else
248+
w[j] = R[j] * w[j-1];
249+
250+
/*
251+
* calculate alpha[j]
252+
*/
253+
if (j == 0)
254+
wd[j] = zero;
255+
else
256+
wd[j] = R[j] * wd[j-1];
257+
258+
/*
259+
* compute acc[j]
260+
*/
261+
if (j == 0)
262+
a[j] = R[j] * (qddv + robot.gravity);
263+
else
264+
a[j] = R[j] * (qddv + a[j-1]);
265+
266+
a[j] += wd[j].cross(PSTAR[j]) +
267+
2*w[j].cross(R[j]*qdv) +
268+
w[j].cross( w[j].cross(PSTAR[j]) );
269+
break;
270+
}
271+
/*
272+
* compute abar[j]
273+
*/
274+
acc_cog[j] = wd[j].cross(r_cog[j]) + w[j].cross(w[j].cross(r_cog[j])) + a[j];
275+
276+
#ifdef DEBUG
277+
vect_print("w", w(j));
278+
vect_print("wd", wd(j));
279+
vect_print("acc", a(j));
280+
vect_print("abar", acc_cog(j));
281+
#endif
282+
}
283+
}
284+
285+
/******************************************************************************
286+
* backward recursion part --the kinetics
287+
******************************************************************************/
288+
289+
if (robot->dhtype == MODIFIED) {
290+
/*
291+
* MODIFIED D&H CONVENTIONS
292+
*/
293+
for (j = robot->njoints - 1; j >= 0; j--) {
294+
295+
/*
296+
* compute F[j]
297+
*/
298+
F = acc_cog[j] * M[j];
299+
300+
/*
301+
* compute f[j]
302+
*/
303+
if (j == (robot->njoints-1))
304+
f[j] = f_tip + F;
305+
else
306+
f[j] = R[j+1] * f[j+1] + F;
307+
308+
/*
309+
* compute N[j]
310+
*/
311+
N = I[j] * wd[j] + w[j].cross(I[j] * w[j]);
312+
313+
/*
314+
* compute n[j]
315+
*/
316+
if (j == (robot->njoints-1))
317+
n[j] = n_tip;
318+
else
319+
n[j] = R[j+1] * n[j+1] + PSTAR[j+1].cross(R[j+1] * f[j+1])
320+
321+
n[j] += r_cog[j].cross(F) + N;
322+
323+
#ifdef DEBUG
324+
vect_print("f", f(j));
325+
vect_print("n", n(j));
326+
#endif
327+
}
328+
329+
} else {
330+
/*
331+
* STANDARD D&H CONVENTIONS
332+
*/
333+
for (j = robot->njoints - 1; j >= 0; j--) {
334+
335+
/*
336+
* compute f[j]
337+
*/
338+
F = acc_cog[j] * M[j];
339+
if (j != (robot->njoints-1))
340+
f[j] = R[j+1] * f[j+1] + F;
341+
else
342+
f[j] = f_tip + F;
343+
344+
/*
345+
* compute n[j]
346+
*/
347+
348+
N = I[j] * wd[j] + w[j].cross(I[j] * w[j]);
349+
350+
n[j] = (PSTAR[j] + r_cog[j]).cross(F);
351+
352+
if (j != (robot->njoints-1))
353+
n[j] += R[j+1] * (n[j+1] + R[j+1] * (n[j+1] + PSTAR[j]).cross(f[j+1]);
354+
else
355+
n[j] += n_tip + PSTAR[j].cross(f_tip);
356+
357+
n[j] += r_cog[j].cross(F) + N;
358+
#ifdef DEBUG
359+
vect_print("f", f(j));
360+
vect_print("n", n(j));
361+
#endif
362+
}
363+
}
364+
365+
/*
366+
* Compute the torque total for each axis
367+
*
368+
*/
369+
for (j=0; j < robot->njoints; j++) {
370+
double t;
371+
Vector3d tauv;
372+
Link *l = &links[j];
373+
374+
if (robot->dhtype == MODIFIED)
375+
tauv = z0;
376+
else
377+
tauv = R[j] * z0;
378+
379+
switch (l->sigma) {
380+
case REVOLUTE:
381+
t = n[j].dot(tauv);
382+
break;
383+
case PRISMATIC:
384+
t = f[j].dot(tauv);
385+
break;
386+
}
387+
388+
/*
389+
* add actuator dynamics and friction
390+
*/
391+
t += l->G * l->G * l->Jm * qdd[j*stride]; // inertia
392+
t += l->G * l->G * l->B * qd[j*stride]; // viscous friction
393+
t += fabs(l->G) * (
394+
(qd[j*stride] > 0 ? l->Tc[0] : 0.0) + // Coulomb friction
395+
(qd[j*stride] < 0 ? l->Tc[1] : 0.0)
396+
);
397+
tau[j*stride] = t;
398+
}
399+
}

0 commit comments

Comments
 (0)