signals-cpp
Loading...
Searching...
No Matches
Signal.h
Go to the documentation of this file.
1#pragma once
2#include <algorithm>
3#include <limits>
4#include <Eigen/Core>
5#include <SO2.h>
6#include <SO3.h>
7#include <SE2.h>
8#include <SE3.h>
9#include "Utils.h"
10
11using namespace Eigen;
12
22
32
41
61template<typename T, typename BaseSignalSpec, typename TangentSignalSpec>
62class Signal
63{
64public:
65 using BaseType = typename BaseSignalSpec::Type;
66 using TangentType = typename TangentSignalSpec::Type;
67
71 struct SignalDP
72 {
73 double t;
76 };
77
81 struct
82 {
83 bool operator()(SignalDP a, SignalDP b) const
84 {
85 return a.t < b.t;
86 }
88
92
103
108 Signal(const Signal& other)
109 {
110 this->interpolationMethod = other.interpolationMethod;
111 this->extrapolationMethod = other.extrapolationMethod;
112 this->derivativeMethod = other.derivativeMethod;
113 this->t_ = other.t_;
114 this->x_ = other.x_;
115 this->xdot_ = other.xdot_;
116 this->signalHistory_ = other.signalHistory_;
117 this->needsSort_ = other.needsSort_;
118 }
119
125 {
127 for (auto signalDP : signalHistory_)
128 {
129 signalDot.update(signalDP.t, signalDP.xdot, true);
130 }
131 signalDot.update(t(), dot());
132 return signalDot;
133 }
134
135 template<typename S, typename BSS, typename TSS>
137
138 template<typename S, typename BSS, typename TSS>
140
141 template<typename S, typename BSS, typename TSS>
142 friend Signal<S, BSS, TSS> operator*(const double& l, const Signal<S, BSS, TSS>& r);
143
144 template<typename S, typename BSS, typename TSS>
145 friend Signal<S, BSS, TSS> operator*(const Signal<S, BSS, TSS>& l, const double& r);
146
151 double t() const
152 {
153 return t_;
154 }
155
161 {
162 return x_;
163 }
164
170 {
171 return xdot_;
172 }
173
179 BaseType operator()(const double& t) const
180 {
181 return xAt(t);
182 }
183
189 TangentType dot(const double& t) const
190 {
191 return xDotAt(t);
192 }
193
199 std::vector<BaseType> operator()(const std::vector<double>& t) const
200 {
201 std::vector<BaseType> xInterp;
202 for (size_t i = 0; i < t.size(); i++)
203 {
204 xInterp.push_back(xAt(t[i]));
205 }
206 return xInterp;
207 }
208
214 std::vector<TangentType> dot(const std::vector<double>& t) const
215 {
216 std::vector<TangentType> xDotInterp;
217 for (size_t i = 0; i < t.size(); i++)
218 {
219 xDotInterp.push_back(xDotAt(t[i]));
220 }
221 return xDotInterp;
222 }
223
229 {
230 interpolationMethod = method;
231 }
232
238 {
239 extrapolationMethod = method;
240 }
241
247 {
248 derivativeMethod = method;
249 }
250
254 void reset()
255 {
256 t_ = -1.0;
257 x_ = BaseSignalSpec::ZeroType();
258 xdot_ = TangentSignalSpec::ZeroType();
259 signalHistory_.clear();
260 needsSort_ = false;
261 }
262
270 bool update(const double& _t, const BaseType& _x, bool insertHistory = false)
271 {
272 TangentType _xdot;
273 if (!calculateDerivative(_t, _x, _xdot))
274 {
275 return false;
276 }
277 return update(_t, _x, _xdot, insertHistory);
278 }
279
288 bool update(const double& _t, const BaseType& _x, const TangentType& _xdot, bool insertHistory = false)
289 {
290 t_ = _t;
291 x_ = _x;
292 xdot_ = _xdot;
293 if (insertHistory)
294 {
295 if (insertIntoHistory(_t, _x, _xdot))
296 {
297 if (needsSort_)
298 {
299 std::sort(signalHistory_.begin(), signalHistory_.end(), SignalDPComparator);
300 needsSort_ = false;
301 }
302 return true;
303 }
304 else
305 {
306 return false;
307 }
308 }
309 return true;
310 }
311
318 bool update(const std::vector<double>& _tHistory, const std::vector<BaseType>& _xHistory)
319 {
320 size_t nTH = _tHistory.size();
321 size_t nXH = _xHistory.size();
322 if (nTH != nXH)
323 {
324 return false;
325 }
326 for (size_t i = 0; i < nXH; i++)
327 {
328 TangentType _xdot;
329 if (!calculateDerivative(_tHistory[i], _xHistory[i], _xdot))
330 {
331 return false;
332 }
333 if (!insertIntoHistory(_tHistory[i], _xHistory[i], _xdot))
334 {
335 return false;
336 }
337 }
338 if (needsSort_)
339 {
340 std::sort(signalHistory_.begin(), signalHistory_.end(), SignalDPComparator);
341 needsSort_ = false;
342 }
343 return true;
344 }
345
353 bool update(const std::vector<double>& _tHistory,
354 const std::vector<BaseType>& _xHistory,
355 const std::vector<TangentType>& _xdotHistory)
356 {
357 size_t nTH = _tHistory.size();
358 size_t nXH = _xHistory.size();
359 size_t nXDH = _xdotHistory.size();
360 if (nXH != nXDH || nXDH != nTH)
361 {
362 return false;
363 }
364 for (size_t i = 0; i < nXH; i++)
365 {
366 if (!insertIntoHistory(_tHistory[i], _xHistory[i], _xdotHistory[i]))
367 {
368 return false;
369 }
370 }
371 if (needsSort_)
372 {
373 std::sort(signalHistory_.begin(), signalHistory_.end(), SignalDPComparator);
374 needsSort_ = false;
375 }
376 return true;
377 }
378
383 static inline BaseType baseZero()
384 {
385 return BaseSignalSpec::ZeroType();
386 }
387
392 static inline TangentType tangentZero()
393 {
394 return TangentSignalSpec::ZeroType();
395 }
396
402 static inline T baseNorm(const BaseType& x)
403 {
404 return BaseSignalSpec::Norm(x);
405 }
406
412 static inline T tangentNorm(const TangentType& x)
413 {
414 return TangentSignalSpec::Norm(x);
415 }
416
417private:
418 double t_;
419 BaseType x_;
420 TangentType xdot_;
421 std::vector<SignalDP> signalHistory_;
422 bool needsSort_;
423
424 bool insertIntoHistory(const double& _t, const BaseType& _x, const TangentType& _xdot)
425 {
426 if (_t > t_)
427 {
428 t_ = _t;
429 x_ = _x;
430 xdot_ = _xdot;
431 }
432 if (signalHistory_.size() > 0)
433 {
434 double mostRecentTime = signalHistory_[signalHistory_.size() - 1].t;
435 if (_t == mostRecentTime)
436 {
437 return false;
438 }
439 else if (_t < mostRecentTime)
440 {
441 needsSort_ = true;
442 }
443 }
444 signalHistory_.push_back({_t, _x, _xdot});
445 return true;
446 }
447
448 BaseType xAt(const double& t) const
449 {
450 if (t == t_)
451 {
452 return x_;
453 }
454 else if (signalHistory_.size() > 0)
455 {
456 int idx = getInterpIndex(t);
457 if (idx < 0 || idx >= static_cast<int>(signalHistory_.size()))
458 {
459 switch (extrapolationMethod)
460 {
462 return BaseSignalSpec::NansType();
463 break;
465 if (idx < 0)
466 {
467 return signalHistory_[0].x;
468 }
469 else
470 {
471 return signalHistory_[signalHistory_.size() - 1].x;
472 }
473 break;
475 default:
476 return BaseSignalSpec::ZeroType();
477 break;
478 }
479 }
480 else
481 {
482 BaseType y = xAtIdx(idx);
483 TangentType dy;
484 switch (interpolationMethod)
485 {
487 dy = TangentSignalSpec::ZeroType();
488 break;
489 }
491 double t1 = tAtIdx(idx);
492 double t2 = tAtIdx(idx + 1);
493 BaseType y1 = xAtIdx(idx);
494 BaseType y2 = xAtIdx(idx + 1);
495 dy = (t - t1) / (t2 - t1) * (y2 - y1);
496 break;
497 }
499 double t0 = tAtIdx(idx - 1);
500 double t1 = tAtIdx(idx);
501 double t2 = tAtIdx(idx + 1);
502 double t3 = tAtIdx(idx + 2);
503 BaseType y0 = xAtIdx(idx - 1);
504 BaseType y1 = xAtIdx(idx);
505 BaseType y2 = xAtIdx(idx + 1);
506 BaseType y3 = xAtIdx(idx + 2);
507 dy =
508 (t - t1) / (t2 - t1) *
509 ((y2 - y1) + (t2 - t) / (2. * (t2 - t1) * (t2 - t1)) *
510 (((t2 - t) * (t2 * (y1 - y0) + t0 * (y2 - y1) - t1 * (y2 - y0))) / (t1 - t0) +
511 ((t - t1) * (t3 * (y2 - y1) + t2 * (y3 - y1) - t1 * (y3 - y2))) / (t3 - t2)));
512 break;
513 }
514 }
515 return y + dy;
516 }
517 }
518 else
519 {
520 return BaseSignalSpec::ZeroType();
521 }
522 }
523
524 TangentType xDotAt(const double& t) const
525 {
526 if (t == t_)
527 {
528 return xdot_;
529 }
530 else if (signalHistory_.size() > 0)
531 {
532 int idx = getInterpIndex(t);
533 if (idx < 0 || idx >= static_cast<int>(signalHistory_.size()))
534 {
535 switch (extrapolationMethod)
536 {
538 return TangentSignalSpec::NansType();
539 break;
541 if (idx < 0)
542 {
543 return signalHistory_[0].xdot;
544 }
545 else
546 {
547 return signalHistory_[signalHistory_.size() - 1].xdot;
548 }
549 break;
551 default:
552 return TangentSignalSpec::ZeroType();
553 break;
554 }
555 }
556 else
557 {
558 TangentType y = xDotAtIdx(idx);
559 TangentType dy;
560 switch (interpolationMethod)
561 {
563 dy = TangentSignalSpec::ZeroType();
564 break;
565 }
567 double t1 = tAtIdx(idx);
568 double t2 = tAtIdx(idx + 1);
569 TangentType y1 = xDotAtIdx(idx);
570 TangentType y2 = xDotAtIdx(idx + 1);
571 dy = (t - t1) / (t2 - t1) * (y2 - y1);
572 break;
573 }
575 double t0 = tAtIdx(idx - 1);
576 double t1 = tAtIdx(idx);
577 double t2 = tAtIdx(idx + 1);
578 double t3 = tAtIdx(idx + 2);
579 TangentType y0 = xDotAtIdx(idx - 1);
580 TangentType y1 = xDotAtIdx(idx);
581 TangentType y2 = xDotAtIdx(idx + 1);
582 TangentType y3 = xDotAtIdx(idx + 2);
583 dy =
584 (t - t1) / (t2 - t1) *
585 ((y2 - y1) + (t2 - t) / (2. * (t2 - t1) * (t2 - t1)) *
586 (((t2 - t) * (t2 * (y1 - y0) + t0 * (y2 - y1) - t1 * (y2 - y0))) / (t1 - t0) +
587 ((t - t1) * (t3 * (y2 - y1) + t2 * (y3 - y1) - t1 * (y3 - y2))) / (t3 - t2)));
588 break;
589 }
590 }
591 return y + dy;
592 }
593 }
594 else
595 {
596 return TangentSignalSpec::ZeroType();
597 }
598 }
599
600 // Implementation note: signal history size must > 0
601 int getInterpIndex(const double& t) const
602 {
603 if (t < signalHistory_[0].t)
604 {
605 return -1;
606 }
607 else if (t > signalHistory_[signalHistory_.size() - 1].t)
608 {
609 return static_cast<int>(signalHistory_.size());
610 }
611 else
612 {
613 for (size_t i = 0; i < signalHistory_.size(); i++)
614 {
615 double t_i = signalHistory_[i].t;
616 double t_ip1 = tAtIdx(i + 1);
617 if (t_i <= t && t_ip1 > t)
618 {
619 return static_cast<int>(i);
620 }
621 }
622 return -1;
623 }
624 }
625
626 double tAtIdx(const int& idx) const
627 {
628 if (idx < 0)
629 {
630 return signalHistory_[0].t + static_cast<double>(idx);
631 }
632 else if (idx >= signalHistory_.size())
633 {
634 return signalHistory_[signalHistory_.size() - 1].t +
635 static_cast<double>(idx - static_cast<int>(signalHistory_.size() - 1));
636 }
637 else
638 {
639 return signalHistory_[idx].t;
640 }
641 }
642
643 BaseType xAtIdx(const int& idx) const
644 {
645 if (idx < 0)
646 {
647 return signalHistory_[0].x;
648 }
649 else if (idx >= signalHistory_.size())
650 {
651 return signalHistory_[signalHistory_.size() - 1].x;
652 }
653 else
654 {
655 return signalHistory_[idx].x;
656 }
657 }
658
659 TangentType xDotAtIdx(const int& idx) const
660 {
661 if (idx < 0)
662 {
663 return signalHistory_[0].xdot;
664 }
665 else if (idx >= signalHistory_.size())
666 {
667 return signalHistory_[signalHistory_.size() - 1].xdot;
668 }
669 else
670 {
671 return signalHistory_[idx].xdot;
672 }
673 }
674
675 // Implementation note: should always be followed by a call to update()
676 bool calculateDerivative(const double& _t, const BaseType& _x, TangentType& _xdot)
677 {
678 const static double sigma = 0.05;
679 if (_t <= t_)
680 {
681 return false;
682 }
683 if (t_ >= 0)
684 {
685 const double dt = _t - t_;
686 const TangentType dx = _x - x_;
687 switch (derivativeMethod)
688 {
690 _xdot = (2. * sigma - dt) / (2. * sigma + dt) * xdot_ + 2. / (2. * sigma + dt) * dx;
691 break;
693 _xdot = dx / dt;
694 break;
695 }
696 }
697 else
698 {
699 _xdot = TangentSignalSpec::ZeroType();
700 }
701 return true;
702 }
703};
704
711template<typename T, typename BaseSignalSpec, typename TangentSignalSpec>
714{
716 lpr.x_ += r(l.t());
717 lpr.xdot_ += r.dot(l.t());
718 for (auto& signalDP : lpr.signalHistory_)
719 {
720 signalDP.x += r(signalDP.t);
721 signalDP.xdot += r.dot(signalDP.t);
722 }
723 return lpr;
724}
725
732template<typename T, typename BaseSignalSpec, typename TangentSignalSpec>
735{
740 lmr.needsSort_ = l.needsSort_;
741 lmr.t_ = l.t();
742 lmr.x_ = l() - r(l.t());
743 lmr.xdot_ = l.dot() - r.dot(l.t());
744 std::vector<double> tHistory;
745 std::vector<typename TangentSignalSpec::Type> xHistory;
746 std::vector<typename TangentSignalSpec::Type> xdotHistory;
747 for (auto& signalDP : l.signalHistory_)
748 {
749 tHistory.push_back(signalDP.t);
750 xHistory.push_back(signalDP.x - r(signalDP.t));
751 xdotHistory.push_back(signalDP.xdot - r.dot(signalDP.t));
752 }
753 lmr.update(tHistory, xHistory, xdotHistory);
754 return lmr;
755}
756
763template<typename T, typename BaseSignalSpec, typename TangentSignalSpec>
766{
768 lr.x_ *= l;
769 lr.xdot_ *= l;
770 for (auto& signalDP : lr.signalHistory_)
771 {
772 signalDP.x *= l;
773 signalDP.xdot *= l;
774 }
775 return lr;
776}
777
784template<typename T, typename BaseSignalSpec, typename TangentSignalSpec>
786 const double& r)
787{
789 lr.x_ *= r;
790 lr.xdot_ *= r;
791 for (auto& signalDP : lr.signalHistory_)
792 {
793 signalDP.x *= r;
794 signalDP.xdot *= r;
795 }
796 return lr;
797}
798
803template<typename T>
805{
806 using Type = T;
810 static Type ZeroType()
811 {
812 return (T)0.0;
813 }
814
817 static Type NansType()
818 {
819 return (T)1. / 0.;
820 }
821
826 static T Norm(const Type& a)
827 {
828 return a;
829 }
830};
831
837template<typename T, size_t d>
839{
840 using Type = Matrix<T, d, 1>;
844 static Type ZeroType()
845 {
846 return Type::Zero();
847 }
848
851 static Type NansType()
852 {
853 return Type::Constant(std::numeric_limits<T>::quiet_NaN());
854 }
855
860 static T Norm(const Type& a)
861 {
862 return a.norm();
863 }
864};
865
870template<typename T, typename ManifoldType>
872{
873 using Type = ManifoldType;
877 static Type ZeroType()
878 {
879 return Type::identity();
880 }
881
884 static Type NansType()
885 {
886 return Type::nans();
887 }
888
893 static T Norm(const Type& a)
894 {
895 return ManifoldType::Log(a).norm();
896 }
897};
898
899template<typename T>
901
902template<typename T>
903inline std::ostream& operator<<(std::ostream& os, const ScalarSignal<T>& x)
904{
905 os << "ScalarSignal at t=" << x.t() << ": " << x();
906 return os;
907}
908
909template<typename T, size_t d>
911
912template<typename T, size_t d>
913inline std::ostream& operator<<(std::ostream& os, const VectorSignal<T, d>& x)
914{
915 os << "VectorSignal at t=" << x.t() << ": " << x().transpose();
916 return os;
917}
918
919template<typename T, typename ManifoldType, size_t d>
921
922template<typename T, typename ManifoldType, size_t d>
923inline std::ostream& operator<<(std::ostream& os, const ManifoldSignal<T, ManifoldType, d>& x)
924{
925 os << "ManifoldSignal at t=" << x.t() << ": " << x();
926 return os;
927}
928
929#define MAKE_VECTOR_SIGNAL(Dimension) \
930 template<typename T> \
931 using Vector##Dimension##Signal = VectorSignal<T, Dimension>; \
932 typedef Vector##Dimension##Signal<double> Vector##Dimension##dSignal;
933
934#define MAKE_MANIF_SIGNAL(Manif, Dimension) \
935 template<typename T> \
936 using Manif##Signal = ManifoldSignal<T, Manif<T>, Dimension>; \
937 typedef Manif##Signal<double> Manif##dSignal;
938
Signal< T, VectorSignalSpec< T, d >, VectorSignalSpec< T, d > > VectorSignal
Definition Signal.h:910
DerivativeMethod
Methods for computing numerical derivatives of signals.
Definition Signal.h:37
@ FINITE_DIFF
Definition Signal.h:39
@ DIRTY
Definition Signal.h:38
#define MAKE_VECTOR_SIGNAL(Dimension)
Definition Signal.h:929
std::ostream & operator<<(std::ostream &os, const ScalarSignal< T > &x)
Definition Signal.h:903
Signal< T, BaseSignalSpec, TangentSignalSpec > operator+(const Signal< T, BaseSignalSpec, TangentSignalSpec > &l, const Signal< T, TangentSignalSpec, TangentSignalSpec > &r)
Add a tangent signal to a base signal.
Definition Signal.h:712
ScalarSignal< double > ScalardSignal
Definition Signal.h:939
Signal< T, ManifoldSignalSpec< T, ManifoldType >, VectorSignalSpec< T, d > > ManifoldSignal
Definition Signal.h:920
ExtrapolationMethod
Methods for extrapolating signal values outside the defined time range.
Definition Signal.h:27
@ ZEROS
Definition Signal.h:29
@ CLOSEST
Definition Signal.h:30
@ NANS
Definition Signal.h:28
InterpolationMethod
Methods for interpolating signal values between discrete time points.
Definition Signal.h:17
@ CUBIC_SPLINE
Definition Signal.h:20
@ ZERO_ORDER_HOLD
Definition Signal.h:18
@ LINEAR
Definition Signal.h:19
Signal< T, TangentSignalSpec, TangentSignalSpec > operator-(const Signal< T, BaseSignalSpec, TangentSignalSpec > &l, const Signal< T, BaseSignalSpec, TangentSignalSpec > &r)
Subtract one signal from another, producing a tangent signal.
Definition Signal.h:733
Signal< T, BaseSignalSpec, TangentSignalSpec > operator*(const double &l, const Signal< T, BaseSignalSpec, TangentSignalSpec > &r)
Multiply a signal by a scalar from the left.
Definition Signal.h:764
Signal< T, ScalarSignalSpec< T >, ScalarSignalSpec< T > > ScalarSignal
Definition Signal.h:900
#define MAKE_MANIF_SIGNAL(Manif, Dimension)
Definition Signal.h:934
Template class for time-series signals with interpolation, extrapolation, and derivative capabilities...
Definition Signal.h:63
static TangentType tangentZero()
Definition Signal.h:392
void setDerivativeMethod(DerivativeMethod method)
Definition Signal.h:246
static T baseNorm(const BaseType &x)
Definition Signal.h:402
double t() const
Get the current time of the signal.
Definition Signal.h:151
bool update(const double &_t, const BaseType &_x, const TangentType &_xdot, bool insertHistory=false)
Definition Signal.h:288
Signal(const Signal &other)
Definition Signal.h:108
void setExtrapolationMethod(ExtrapolationMethod method)
Definition Signal.h:237
friend Signal< S, BSS, TSS > operator*(const double &l, const Signal< S, BSS, TSS > &r)
std::vector< BaseType > operator()(const std::vector< double > &t) const
Definition Signal.h:199
friend Signal< S, BSS, TSS > operator*(const Signal< S, BSS, TSS > &l, const double &r)
friend Signal< S, TSS, TSS > operator-(const Signal< S, BSS, TSS > &l, const Signal< S, BSS, TSS > &r)
struct Signal::@053250032031010315204017007310244260026177164207 SignalDPComparator
Comparator for sorting signal data points by time.
void setInterpolationMethod(InterpolationMethod method)
Definition Signal.h:228
static BaseType baseZero()
Definition Signal.h:383
BaseType operator()(const double &t) const
Definition Signal.h:179
ExtrapolationMethod extrapolationMethod
Definition Signal.h:90
Signal()
Default constructor initializing with LINEAR interpolation, ZEROS extrapolation, and DIRTY derivative...
Definition Signal.h:96
static T tangentNorm(const TangentType &x)
Definition Signal.h:412
std::vector< TangentType > dot(const std::vector< double > &t) const
Definition Signal.h:214
typename BaseSignalSpec::Type BaseType
Definition Signal.h:65
bool update(const double &_t, const BaseType &_x, bool insertHistory=false)
Update the signal with a new value at a given time, computing derivative automatically.
Definition Signal.h:270
InterpolationMethod interpolationMethod
Definition Signal.h:89
bool update(const std::vector< double > &_tHistory, const std::vector< BaseType > &_xHistory, const std::vector< TangentType > &_xdotHistory)
Definition Signal.h:353
void reset()
Reset the signal to initial state, clearing all history.
Definition Signal.h:254
bool update(const std::vector< double > &_tHistory, const std::vector< BaseType > &_xHistory)
Definition Signal.h:318
BaseType operator()() const
Get the current signal value.
Definition Signal.h:160
typename TangentSignalSpec::Type TangentType
Definition Signal.h:66
TangentType dot() const
Get the current time derivative of the signal.
Definition Signal.h:169
Signal< T, ScalarSignalSpec< T >, ScalarSignalSpec< T > > dotSignal()
Definition Signal.h:124
TangentType dot(const double &t) const
Definition Signal.h:189
friend Signal< S, BSS, TSS > operator+(const Signal< S, BSS, TSS > &l, const Signal< S, TSS, TSS > &r)
Type specification for manifold-valued signals (e.g., SO2, SO3, SE2, SE3).
Definition Signal.h:872
static Type NansType()
Returns manifold element with NaN values.
Definition Signal.h:884
static T Norm(const Type &a)
Compute the norm of a manifold element via its logarithmic map.
Definition Signal.h:893
ManifoldType Type
Definition Signal.h:873
static Type ZeroType()
Returns identity element of the manifold.
Definition Signal.h:877
Type specification for scalar-valued signals.
Definition Signal.h:805
static Type NansType()
Returns NaN value for the scalar type.
Definition Signal.h:817
T Type
Definition Signal.h:806
static Type ZeroType()
Returns zero value for the scalar type.
Definition Signal.h:810
static T Norm(const Type &a)
Compute the norm (absolute value) of a scalar.
Definition Signal.h:826
Data point structure storing time, value, and derivative.
Definition Signal.h:72
TangentType xdot
Definition Signal.h:75
BaseType x
Definition Signal.h:74
double t
Definition Signal.h:73
Type specification for vector-valued signals.
Definition Signal.h:839
static Type NansType()
Returns vector filled with NaN values.
Definition Signal.h:851
static Type ZeroType()
Returns zero vector.
Definition Signal.h:844
static T Norm(const Type &a)
Compute the Euclidean norm of a vector.
Definition Signal.h:860
Matrix< T, d, 1 > Type
Definition Signal.h:840