MRSL Motion Primitive Library  1.2
A motion primitive library for generating trajectory for mobile robots
primitive.h
Go to the documentation of this file.
1 
6 #ifndef MPL_PRIMITIVE_H
7 #define MPL_PRIMITIVE_H
8 #include <mpl_basis/data_type.h>
9 #include <mpl_basis/waypoint.h>
10 
11 #include "math.h"
12 
21 class Primitive1D {
22  public:
23  /************************* Constructors *************************/
26 
31  Primitive1D(const Vec6f& coeff) : c(coeff) {}
32 
34  Primitive1D(decimal_t p, decimal_t u) { c << 0, 0, 0, 0, u, p; }
35 
38  Primitive1D(Vec2f state, decimal_t u) { c << 0, 0, 0, u, state(1), state(0); }
39 
43  c << 0, 0, u, state(2), state(1), state(0);
44  }
45 
49  c << 0, u, state(3), state(2), state(1), state(0);
50  }
51 
55  c << 0, 0, 0, 0, (p2 - p1) / t, p1;
56  }
57 
61  decimal_t t) {
62  Mat4f A;
63  A << 0, 0, 0, 1, 0, 0, 1, 0, power(t, 3) / 6, t * t / 2, t, 1, t * t / 2, t,
64  1, 0;
65  Vec4f b;
66  b << p1, v1, p2, v2;
67  Vec4f cc = A.inverse() * b;
68  c << 0, 0, cc(0), cc(1), cc(2), cc(3);
69  }
70 
74  decimal_t v2, decimal_t a2, decimal_t t) {
75  Mat6f A;
76  A << 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
77  power(t, 5) / 120, power(t, 4) / 24, power(t, 3) / 6, t * t / 2, t, 1,
78  power(t, 4) / 24, power(t, 3) / 6, t * t / 2, t, 1, 0, power(t, 3) / 6,
79  t * t / 2, t, 1, 0, 0;
80  Vec6f b;
81  b << p1, v1, a1, p2, v2, a2;
82  c = A.inverse() * b;
83  }
84 
85  /*************************** Member functions **************************/
92  decimal_t J(decimal_t t, const Control::Control& control) const {
93  // i = 1, return integration of square of vel
94  if (control == Control::VEL || control == Control::VELxYAW)
95  return c(0) * c(0) / 5184 * power(t, 9) +
96  c(0) * c(1) / 576 * power(t, 8) +
97  (c(1) * c(1) / 252 + c(0) * c(2) / 168) * power(t, 7) +
98  (c(0) * c(3) / 72 + c(1) * c(2) / 36) * power(t, 6) +
99  (c(2) * c(2) / 20 + c(0) * c(4) / 60 + c(1) * c(3) / 15) *
100  power(t, 5) +
101  (c(2) * c(3) / 4 + c(1) * c(4) / 12) * power(t, 4) +
102  (c(3) * c(3) / 3 + c(2) * c(4) / 3) * power(t, 3) +
103  c(3) * c(4) * t * t + c(4) * c(4) * t;
104  // i = 2, return integration of square of acc
105  else if (control == Control::ACC || control == Control::ACCxYAW)
106  return c(0) * c(0) / 252 * power(t, 7) + c(0) * c(1) / 36 * power(t, 6) +
107  (c(1) * c(1) / 20 + c(0) * c(2) / 15) * power(t, 5) +
108  (c(0) * c(3) / 12 + c(1) * c(2) / 4) * power(t, 4) +
109  (c(2) * c(2) / 3 + c(1) * c(3) / 3) * power(t, 3) +
110  c(2) * c(3) * t * t + c(3) * c(3) * t;
111  // i = 3, return integration of square of jerk
112  else if (control == Control::JRK || control == Control::JRKxYAW)
113  return c(0) * c(0) / 20 * power(t, 5) + c(0) * c(1) / 4 * power(t, 4) +
114  (c(1) * c(1) + c(0) * c(2)) / 3 * power(t, 3) +
115  c(1) * c(2) * t * t + c(2) * c(2) * t;
116  // i = 4, return integration of square of snap
117  else if (control == Control::SNP || control == Control::SNPxYAW)
118  return c(0) * c(0) / 3 * power(t, 3) + c(0) * c(1) * t * t +
119  c(1) * c(1) * t;
120  else
121  return 0;
122  }
123 
125  Vec6f coeff() const { return c; }
126 
128  decimal_t p(decimal_t t) const {
129  return c(0) / 120 * power(t, 5) + c(1) / 24 * power(t, 4) +
130  c(2) / 6 * power(t, 3) + c(3) / 2 * t * t + c(4) * t + c(5);
131  }
132 
134  decimal_t v(decimal_t t) const {
135  return c(0) / 24 * power(t, 4) + c(1) / 6 * power(t, 3) + c(2) / 2 * t * t +
136  c(3) * t + c(4);
137  }
138 
140  decimal_t a(decimal_t t) const {
141  return c(0) / 6 * power(t, 3) + c(1) / 2 * t * t + c(2) * t + c(3);
142  }
143 
145  decimal_t j(decimal_t t) const { return c(0) / 2 * t * t + c(1) * t + c(2); }
146 
152  std::vector<decimal_t> extrema_v(decimal_t t) const {
153  std::vector<decimal_t> roots = solve(0, c(0) / 6, c(1) / 2, c(2), c(3));
154  std::vector<decimal_t> ts;
155  for (const auto& it : roots) {
156  if (it > 0 && it < t)
157  ts.push_back(it);
158  else if (it >= t)
159  break;
160  }
161  return ts;
162  }
163 
169  std::vector<decimal_t> extrema_a(decimal_t t) const {
170  std::vector<decimal_t> roots = solve(0, 0, c(0) / 2, c(1), c(2));
171  std::vector<decimal_t> ts;
172  for (const auto& it : roots) {
173  if (it > 0 && it < t)
174  ts.push_back(it);
175  else if (it >= t)
176  break;
177  }
178  return ts;
179  }
180 
186  std::vector<decimal_t> extrema_j(decimal_t t) const {
187  std::vector<decimal_t> ts;
188  if (c(0) != 0) {
189  decimal_t t_sol = -c(1) * 2 / c(0);
190  if (t_sol > 0 && t_sol < t) ts.push_back(t_sol);
191  }
192  return ts;
193  }
194 
195  public:
197  Vec6f c{Vec6f::Zero()};
198 };
199 
205 template <int Dim>
206 class Primitive {
207  public:
212 
220  Primitive(const Waypoint<Dim>& p, const VecDf& u, decimal_t t)
221  : t_(t), control_(p.control) {
222  if (control_ == Control::SNP) {
223  for (int i = 0; i < Dim; i++) {
224  Vec4f vec;
225  vec << p.pos(i), p.vel(i), p.acc(i), p.jrk(i);
226  prs_[i] = Primitive1D(vec, u(i));
227  }
228  } else if (control_ == Control::JRK) {
229  for (int i = 0; i < Dim; i++)
230  prs_[i] = Primitive1D(Vec3f(p.pos(i), p.vel(i), p.acc(i)), u(i));
231  } else if (control_ == Control::ACC) {
232  for (int i = 0; i < Dim; i++)
233  prs_[i] = Primitive1D(Vec2f(p.pos(i), p.vel(i)), u(i));
234  } else if (control_ == Control::VEL) {
235  for (int i = 0; i < Dim; i++) prs_[i] = Primitive1D(p.pos(i), u(i));
236  } else if (control_ == Control::SNPxYAW) {
237  for (int i = 0; i < Dim; i++) {
238  Vec4f vec;
239  vec << p.pos(i), p.vel(i), p.acc(i), p.jrk(i);
240  prs_[i] = Primitive1D(vec, u(i));
241  }
242  pr_yaw_ = Primitive1D(p.yaw, u(Dim));
243  } else if (control_ == Control::JRKxYAW) {
244  for (int i = 0; i < Dim; i++)
245  prs_[i] = Primitive1D(Vec3f(p.pos(i), p.vel(i), p.acc(i)), u(i));
246  pr_yaw_ = Primitive1D(p.yaw, u(Dim));
247  } else if (control_ == Control::ACCxYAW) {
248  for (int i = 0; i < Dim; i++)
249  prs_[i] = Primitive1D(Vec2f(p.pos(i), p.vel(i)), u(i));
250  pr_yaw_ = Primitive1D(p.yaw, u(Dim));
251  } else if (control_ == Control::VELxYAW) {
252  for (int i = 0; i < Dim; i++) prs_[i] = Primitive1D(p.pos(i), u(i));
253  pr_yaw_ = Primitive1D(p.yaw, u(Dim));
254  } else
255  printf("Null Primitive, check the control set-up of the Waypoint!\n");
256  }
257 
263  : t_(t), control_(p1.control) {
264  // Use jrk control
265  if (p1.control == Control::JRK && p2.control == Control::JRK) {
266  for (int i = 0; i < Dim; i++)
267  prs_[i] = Primitive1D(p1.pos(i), p1.vel(i), p1.acc(i), p2.pos(i),
268  p2.vel(i), p2.acc(i), t_);
269  }
270  // Use acc control
271  else if (p1.control == Control::ACC && p2.control == Control::ACC) {
272  for (int i = 0; i < Dim; i++)
273  prs_[i] = Primitive1D(p1.pos(i), p1.vel(i), p2.pos(i), p2.vel(i), t_);
274  }
275  // Use vel control
276  else if (p1.control == Control::VEL && p2.control == Control::VEL) {
277  for (int i = 0; i < Dim; i++)
278  prs_[i] = Primitive1D(p1.pos(i), p2.pos(i), t_);
279  }
280  // Use jrk & yaw control
281  else if (p1.control == Control::JRKxYAW && p2.control == Control::JRKxYAW) {
282  for (int i = 0; i < Dim; i++)
283  prs_[i] = Primitive1D(p1.pos(i), p1.vel(i), p1.acc(i), p2.pos(i),
284  p2.vel(i), p2.acc(i), t_);
285  pr_yaw_ = Primitive1D(p1.yaw, p2.yaw, t_);
286  }
287  // Use acc & yaw control
288  else if (p1.control == Control::ACCxYAW && p2.control == Control::ACCxYAW) {
289  for (int i = 0; i < Dim; i++)
290  prs_[i] = Primitive1D(p1.pos(i), p1.vel(i), p2.pos(i), p2.vel(i), t_);
291  pr_yaw_ = Primitive1D(p1.yaw, p2.yaw, t_);
292  }
293  // Use vel & yaw control
294  else if (p1.control == Control::VELxYAW && p2.control == Control::VELxYAW) {
295  for (int i = 0; i < Dim; i++)
296  prs_[i] = Primitive1D(p1.pos(i), p2.pos(i), t_);
297  pr_yaw_ = Primitive1D(p1.yaw, p2.yaw, t_);
298  }
299  // Null
300  else
301  printf("Null Primitive, check the control set-up of the Waypoint!\n");
302  }
303 
310  : t_(t), control_(control) {
311  for (int i = 0; i < Dim; i++) prs_[i] = Primitive1D(cs[i]);
312  if (cs.size() == Dim + 1) pr_yaw_ = Primitive1D(cs[Dim]);
313  }
314 
322  Waypoint<Dim> p(control_);
323  for (int k = 0; k < Dim; k++) {
324  p.pos(k) = prs_[k].p(t);
325  p.vel(k) = prs_[k].v(t);
326  p.acc(k) = prs_[k].a(t);
327  p.jrk(k) = prs_[k].j(t);
328  if (p.use_yaw) p.yaw = normalize_angle(pr_yaw_.p(t));
329  }
330  return p;
331  }
332 
336  decimal_t t() const { return t_; }
337 
339  Control::Control control() const { return control_; }
340 
345  Primitive1D pr(int k) const { return prs_[k]; }
347  Primitive1D pr_yaw() const { return pr_yaw_; }
348 
353  decimal_t max_vel(int k) const {
354  std::vector<decimal_t> ts = prs_[k].extrema_v(t_);
355  decimal_t max_v = std::max(std::abs(prs_[k].v(0)), std::abs(prs_[k].v(t_)));
356  for (const auto& it : ts) {
357  if (it > 0 && it < t_) {
358  decimal_t v = std::abs(prs_[k].v(it));
359  max_v = v > max_v ? v : max_v;
360  }
361  }
362  return max_v;
363  }
364 
369  decimal_t max_acc(int k) const {
370  std::vector<decimal_t> ts = prs_[k].extrema_a(t_);
371  decimal_t max_a = std::max(std::abs(prs_[k].a(0)), std::abs(prs_[k].a(t_)));
372  for (const auto& it : ts) {
373  if (it > 0 && it < t_) {
374  decimal_t a = std::abs(prs_[k].a(it));
375  max_a = a > max_a ? a : max_a;
376  }
377  }
378  return max_a;
379  }
380 
384  decimal_t max_jrk(int k) const {
385  std::vector<decimal_t> ts = prs_[k].extrema_j(t_);
386  decimal_t max_j = std::max(std::abs(prs_[k].j(0)), std::abs(prs_[k].j(t_)));
387  for (const auto& it : ts) {
388  if (it > 0 && it < t_) {
389  decimal_t j = std::abs(prs_[k].j(it));
390  max_j = j > max_j ? j : max_j;
391  }
392  }
393  return max_j;
394  }
395 
403  decimal_t J(const Control::Control& control) const {
404  decimal_t j = 0;
405  for (const auto& pr : prs_) j += pr.J(t_, control);
406  return j;
407  }
408 
410  decimal_t Jyaw() const { return pr_yaw_.J(t_, Control::VEL); }
411 
415  vec_E<Waypoint<Dim>> sample(int N) const {
416  vec_E<Waypoint<Dim>> ps(N + 1);
417  decimal_t dt = t_ / N;
418  for (int i = 0; i <= N; i++) ps[i] = evaluate(i * dt);
419  return ps;
420  }
421 
422  /************************** Public members ************************/
428  std::array<Primitive1D, Dim> prs_;
431 };
432 
435 
438 
439 /************************* Utils ******************************/
449 template <int Dim>
451  decimal_t ma = 0, decimal_t mj = 0,
452  decimal_t myaw = 0) {
453  if (pr.control() == Control::ACC)
454  return validate_xxx(pr, mv, Control::VEL);
455  else if (pr.control() == Control::JRK)
456  return validate_xxx(pr, mv, Control::VEL) &&
457  validate_xxx(pr, ma, Control::ACC);
458  else if (pr.control() == Control::SNP)
459  return validate_xxx(pr, mv, Control::VEL) &&
460  validate_xxx(pr, ma, Control::ACC) &&
461  validate_xxx(pr, mj, Control::JRK);
462  else if (pr.control() == Control::VELxYAW)
463  return validate_yaw(pr, myaw);
464  else if (pr.control() == Control::ACCxYAW)
465  return validate_yaw(pr, myaw) && validate_xxx(pr, mv, Control::VEL);
466  else if (pr.control() == Control::JRKxYAW)
467  return validate_yaw(pr, myaw) && validate_xxx(pr, mv, Control::VEL) &&
468  validate_xxx(pr, ma, Control::ACC);
469  else if (pr.control() == Control::SNPxYAW)
470  return validate_yaw(pr, myaw) && validate_xxx(pr, mv, Control::VEL) &&
471  validate_xxx(pr, ma, Control::ACC) &&
472  validate_xxx(pr, mj, Control::JRK);
473  else
474  return true;
475 }
482 template <int Dim>
484  Control::Control xxx) {
485  if (max <= 0) return true;
486  // check if max vel is violating the constraint
487  for (int i = 0; i < Dim; i++) {
488  if (xxx == Control::VEL && pr.max_vel(i) > max)
489  return false;
490  else if (xxx == Control::ACC && pr.max_acc(i) > max)
491  return false;
492  else if (xxx == Control::JRK && pr.max_jrk(i) > max)
493  return false;
494  }
495  return true;
496 }
497 
503 template <int Dim>
504 bool validate_yaw(const Primitive<Dim>& pr, decimal_t my) {
505  // ignore negative threshold
506  if (my <= 0) return true;
507  // check velocity angle at two ends, compare with my
508  vec_E<Waypoint<Dim>> ws(2);
509  ws[0] = pr.evaluate(0);
510  ws[1] = pr.evaluate(pr.t());
511  for (const auto& w : ws) {
512  const auto v = w.vel.template topRows<2>();
513  if (v(0) != 0 || v(1) != 0) { // if v is not zero
514  /*
515  decimal_t vyaw = std::atan2(v(1), v(0));
516  decimal_t dyaw = normalize_angle(vyaw - w.yaw);
517  if(std::abs(dyaw) > my) // if exceed the threshold
518  return false;
519  */
520  decimal_t d = v.normalized().dot(Vec2f(cos(w.yaw), sin(w.yaw)));
521  if (d < cos(my)) return false;
522  }
523  }
524  return true;
525 }
526 
528 template <int Dim>
529 void print(const Primitive<Dim>& p) {
530  std::cout << "Primitive: " << std::endl;
531  std::cout << "t: " << p.t() << std::endl;
532  for (int i = 0; i < Dim; i++)
533  std::cout << "dim[" << i << "]: " << p.pr(i).coeff().transpose()
534  << std::endl;
535  std::cout << "yaw: " << p.pr_yaw().coeff().transpose() << std::endl;
536 }
537 
539 template <int Dim>
540 void print_max(const Primitive<Dim>& p) {
541  Vecf<Dim> max_v, max_a, max_j;
542  for (int i = 0; i < Dim; i++) {
543  max_v(i) = p.max_vel(i);
544  max_a(i) = p.max_acc(i);
545  max_j(i) = p.max_jrk(i);
546  }
547  std::cout << "max_vel: " << max_v.transpose() << std::endl;
548  std::cout << "max_acc: " << max_a.transpose() << std::endl;
549  std::cout << "max_jrk: " << max_j.transpose() << std::endl;
550 }
551 
552 #endif
Polynomial roots solver.
Primitive(const Waypoint< Dim > &p1, const Waypoint< Dim > &p2, decimal_t t)
Construct from an initial state p1 and a goal state p2 for a given duration t.
Definition: primitive.h:262
Primitive1D pr_yaw_
Primitive for yaw.
Definition: primitive.h:430
Primitive< 2 > Primitive2D
Primitive for 2D.
Definition: primitive.h:434
bool validate_yaw(const Primitive< Dim > &pr, decimal_t my)
Check if the successor goes outside of the fov.
Definition: primitive.h:504
Primitive1D(Vec3f state, decimal_t u)
Definition: primitive.h:42
decimal_t j(decimal_t t) const
Return at time .
Definition: primitive.h:145
decimal_t a(decimal_t t) const
Return at time .
Definition: primitive.h:140
decimal_t max_acc(int k) const
Return max accleration along one axis.
Definition: primitive.h:369
Vecf< Dim > jrk
jerk in
Definition: waypoint.h:35
decimal_t J(const Control::Control &control) const
Return total efforts for the given duration.
Definition: primitive.h:403
decimal_t yaw
yaw
Definition: waypoint.h:36
Waypoint base class.
Definition: waypoint.h:23
Primitive1D class.
Definition: primitive.h:21
Primitive1D()
Empty constructor.
Definition: primitive.h:25
Vec6f coeff() const
Return coffecients.
Definition: primitive.h:125
Primitive1D(decimal_t p1, decimal_t p2, decimal_t t)
Definition: primitive.h:54
Eigen::Matrix< decimal_t, Eigen::Dynamic, 1 > VecDf
Eigen 1D float vector of dynamic size.
Definition: data_type.h:61
decimal_t p(decimal_t t) const
Return at time .
Definition: primitive.h:128
Primitive(const Waypoint< Dim > &p, const VecDf &u, decimal_t t)
Construct from an initial state p and an input control u for a given duration t.
Definition: primitive.h:220
Primitive1D(decimal_t p1, decimal_t v1, decimal_t p2, decimal_t v2, decimal_t t)
Definition: primitive.h:60
decimal_t power(decimal_t t, int n)
Return .
Definition: math.h:197
std::vector< decimal_t > extrema_v(decimal_t t) const
Return vector of time for velocity extrema.
Definition: primitive.h:152
std::vector< decimal_t > solve(decimal_t a, decimal_t b, decimal_t c, decimal_t d, decimal_t e)
General solver for .
Definition: math.h:117
Control
Enum for control input.
Definition: control.h:10
Waypoint< Dim > evaluate(decimal_t t) const
Return Waypoint at time .
Definition: primitive.h:321
decimal_t max_jrk(int k) const
Return max jerk along k-th dimension.
Definition: primitive.h:384
Vecf< Dim > acc
acceleration in
Definition: waypoint.h:34
std::vector< T, Eigen::aligned_allocator< T > > vec_E
Pre-allocated std::vector for Eigen using vec_E.
Definition: data_type.h:53
Vecf< 3 > Vec3f
Eigen 1D float vector of size 3.
Definition: data_type.h:80
Control::Control control
Control value.
Definition: waypoint.h:54
Vecf< Dim > vel
velocity in
Definition: waypoint.h:33
decimal_t Jyaw() const
Return total yaw efforts for the given duration.
Definition: primitive.h:410
Matf< 4, 4 > Mat4f
4x4 Matrix in float
Definition: data_type.h:102
Primitive1D(Vec2f state, decimal_t u)
Definition: primitive.h:38
std::vector< decimal_t > extrema_j(decimal_t t) const
Return vector of time for jerk extrema.
Definition: primitive.h:186
decimal_t v(decimal_t t) const
Return at time .
Definition: primitive.h:134
Primitive1D(decimal_t p, decimal_t u)
Construct 1D primitive from an initial state (p) and an input control (u)
Definition: primitive.h:34
decimal_t t() const
Return duration .
Definition: primitive.h:336
bool validate_xxx(const Primitive< Dim > &pr, decimal_t max, Control::Control xxx)
Check if the max velocity magnitude is within the threshold.
Definition: primitive.h:483
double decimal_t
Rename the float type used in lib.
Definition: data_type.h:49
Matf< 6, 6 > Mat6f
6x6 Matrix in float
Definition: data_type.h:104
Primitive(const vec_E< Vec6f > &cs, decimal_t t, Control::Control control)
Construct from given coefficients and duration .
Definition: primitive.h:309
Primitive1D(const Vec6f &coeff)
Construct from known coefficients.
Definition: primitive.h:31
Primitive1D pr_yaw() const
Get the yaw primitive.
Definition: primitive.h:347
Primitive1D(Vec4f state, decimal_t u)
Definition: primitive.h:48
std::vector< decimal_t > extrema_a(decimal_t t) const
Return vector of time for acceleration extrema.
Definition: primitive.h:169
Vec6f c
Coefficients.
Definition: primitive.h:197
Vecf< 2 > Vec2f
Eigen 1D float vector of size 2.
Definition: data_type.h:76
decimal_t max_vel(int k) const
Return max velocity along one axis.
Definition: primitive.h:353
Vecf< 6 > Vec6f
Column vector in float of size 6.
Definition: data_type.h:86
Defines all data types used in this lib.
Primitive()
Empty constructor.
Definition: primitive.h:211
bool use_yaw
If true, yaw will be used in primitive generation.
Definition: waypoint.h:52
Primitive1D(decimal_t p1, decimal_t v1, decimal_t a1, decimal_t p2, decimal_t v2, decimal_t a2, decimal_t t)
Definition: primitive.h:73
Primitive< 3 > Primitive3D
Primitive for 3D.
Definition: primitive.h:437
bool validate_primitive(const Primitive< Dim > &pr, decimal_t mv=0, decimal_t ma=0, decimal_t mj=0, decimal_t myaw=0)
Check if the max velocity magnitude is within the threshold.
Definition: primitive.h:450
Eigen::Matrix< decimal_t, N, 1 > Vecf
Eigen 1D float vector of size N.
Definition: data_type.h:56
Vecf< 4 > Vec4f
Eigen 1D float vector of size 4.
Definition: data_type.h:84
Waypoint classes.
vec_E< Waypoint< Dim > > sample(int N) const
Sample N+1 Waypoints using uniformed time.
Definition: primitive.h:415
Primitive1D pr(int k) const
Get the 1D primitive.
Definition: primitive.h:345
void print_max(const Primitive< Dim > &p)
Print max dynamic infomation in primitive p.
Definition: primitive.h:540
Control::Control control_
Control.
Definition: primitive.h:426
Primitive class.
Definition: primitive.h:206
decimal_t t_
Duration.
Definition: primitive.h:424
Vecf< Dim > pos
position in
Definition: waypoint.h:32
Control::Control control() const
Get the control indicator.
Definition: primitive.h:339
std::array< Primitive1D, Dim > prs_
By default, primitive class contains Dim 1D primitive.
Definition: primitive.h:428
decimal_t J(decimal_t t, const Control::Control &control) const
Return total efforts of 1D primitive for the given duration: .
Definition: primitive.h:92
void print(const Primitive< Dim > &p)
Print all coefficients in primitive p.
Definition: primitive.h:529