blob: 5e7520fdb60b3d31bd6e063abfd923b8ba947853 [file] [log] [blame]
Brian Silverman10fb0f32016-03-13 17:05:21 -04001#ifndef AOS_VISION_MATH_VECTOR_H_
2#define AOS_VISION_MATH_VECTOR_H_
3
4#include <cmath>
5
6#include "Eigen/Dense"
7
8namespace aos {
9namespace vision {
10
11// Represents an n-dimensional vector of doubles with various convenient
12// shortcuts for common operations.
13//
14// This includes overloads of various arithmetic operators for convenience.
15// Multiplication by doubles is scalar multiplication and multiplication by
16// other vectors is element-wise.
17//
18// Accessing elements which don't exist for a given size vector, mixing sizes of
19// vectors in appropriately, etc are compile-time errors.
20template <int size>
21class Vector {
22 public:
Parker Schuh6691f192017-01-14 17:01:02 -080023 Vector() : data_(::Eigen::Matrix<double, 1, size>::Zero()) {}
Brian Silverman10fb0f32016-03-13 17:05:21 -040024
25 Vector(double x, double y) { Set(x, y); }
26
27 Vector(double x, double y, double z) { Set(x, y, z); }
28
29 double Get(int index) const { return data_(index); }
30 void Set(int index, double value) { data_(index) = value; }
31
32 void Set(double x, double y) {
33 static_assert(size == 2, "illegal size");
34 data_(0) = x;
35 data_(1) = y;
36 }
37 void Set(double x, double y, double z) {
38 static_assert(size == 3, "illegal size");
39 data_(0) = x;
40 data_(1) = y;
41 data_(2) = z;
42 }
43 void Set(double x, double y, double z, double w) {
44 static_assert(size == 4, "illegal size");
45 data_(0) = x;
46 data_(1) = y;
47 data_(2) = z;
48 data_(3) = w;
49 }
50
51 double x() const {
52 static_assert(size >= 1, "illegal size");
53 return data_(0);
54 }
55 void x(double xX) {
56 static_assert(size >= 1, "illegal size");
57 data_(0) = xX;
58 }
59
60 double y() const {
61 static_assert(size >= 2, "illegal size");
62 return data_(1);
63 }
64 void y(double yY) {
65 static_assert(size >= 2, "illegal size");
66 data_(1) = yY;
67 }
68
69 double z() const {
70 static_assert(size >= 3, "illegal size");
71 return data_(2);
72 }
73 void z(double zZ) {
74 static_assert(size >= 3, "illegal size");
75 data_(2) = zZ;
76 }
77
78 double w() const {
79 static_assert(size >= 4, "illegal size");
80 return data_(3);
81 }
82 void w(double wW) {
83 static_assert(size >= 4, "illegal size");
84 data_(3) = wW;
85 }
86
87 // Fast part of length.
88 double MagSqr() const { return data_.squaredNorm(); }
89
90 // Length of the vector.
91 double Mag() const { return data_.norm(); }
92
93 // Get underlying data structure
Austin Schuhe6cfbe32019-03-10 18:05:57 -070094 // TODO(austin): Everyone uses column not row vectors.
Brian Silverman10fb0f32016-03-13 17:05:21 -040095 ::Eigen::Matrix<double, 1, size> GetData() const { return data_; }
96
97 // Set underlying data structure
98 void SetData(const ::Eigen::Matrix<double, 1, size> &other) { data_ = other; }
99
100 Vector<size> operator+(const Vector<size> &other) const {
101 Vector<size> nv = *this;
102 nv += other;
103 return nv;
104 }
105 Vector<size> operator+=(const Vector<size> &other) {
106 data_ += other.data_;
107 return *this;
108 }
109
110 Vector<size> operator-(const Vector<size> &other) const {
111 Vector<size> nv = *this;
112 nv -= other;
113 return nv;
114 }
115 Vector<size> operator-=(const Vector<size> &other) {
116 data_ -= other.data_;
117 return *this;
118 }
119
120 Vector<size> operator*(double other) {
121 Vector<size> nv = *this;
122 nv *= other;
123 return nv;
124 }
125 Vector<size> operator*=(double other) {
126 data_ *= other;
127 return *this;
128 }
129
130 Vector<size> operator*(const Vector<size> &other) const {
131 Vector<size> nv = *this;
132 nv *= other;
133 return nv;
134 }
135 Vector<size> operator*=(const Vector<size> &other) {
136 for (int i = 0; i < size; i++) {
137 Set(i, other.Get(i) * Get(i));
138 }
139 return *this;
140 }
141
142 bool operator==(const Vector<size> &other) const {
143 for (int i = 0; i < size; i++) {
144 if (Get(i) != other.Get(i)) {
145 return false;
146 }
147 }
148 return true;
149 }
150
151 double dot(const Vector<size> &other) const {
152 return data_.dot(other.GetData());
153 }
154
155 Vector<size> cross(const Vector<size> &other) const {
156 Vector<size> nv;
157 nv.SetData(data_.cross(other.GetData()));
158 return nv;
159 }
160
161 // Returns a vector in the same direction as this one with a magnitude of 1.
162 Vector<size> Normalized() const {
163 double mag = Mag();
164 Vector<size> nv;
165 for (int i = 0; i < size; i++) {
166 nv.Set(i, Get(i) / mag);
167 }
168 return nv;
169 }
170
171 // Returns the angle between this vector and the 0 vector.
172 // Only valid for 2-dimensional vectors.
173 double AngleToZero() const {
174 static_assert(size == 2, "illegal size");
175 return ::std::atan2(y(), x());
176 }
177
178 // Return the angle between this and other.
Parker Schuh6691f192017-01-14 17:01:02 -0800179 double AngleTo(const Vector<size> &other) const {
Brian Silverman10fb0f32016-03-13 17:05:21 -0400180 // cos(theta) = u.dot(v) / (u.magnitude() * v.magnitude())
181 return ::std::acos(dot(other) / (Mag() * other.Mag()));
182 }
183
184 // Returns the distance between this and other squared.
Parker Schuh6691f192017-01-14 17:01:02 -0800185 double SquaredDistanceTo(const Vector<size> &other) const {
Brian Silverman10fb0f32016-03-13 17:05:21 -0400186 Vector<size> tmp = *this - other;
187 return tmp.MagSqr();
188 }
189
Parker Schuh02f13f62019-02-16 16:42:41 -0800190 // Returns the distance between this and other.
191 double DistanceTo(const Vector<size> &other) const {
192 return std::sqrt(SquaredDistanceTo(other));
193 }
194
Brian Silverman10fb0f32016-03-13 17:05:21 -0400195 private:
196 // The actual data.
197 ::Eigen::Matrix<double, 1, size> data_;
198};
199
200// Returns the cross product of two points.
201inline double PointsCrossProduct(const Vector<2> &a, const Vector<2> &b) {
202 return a.x() * b.y() - a.y() * b.x();
203}
Parker Schuh02f13f62019-02-16 16:42:41 -0800204
205// Rotates along the z, y, and then x axis (all radians).
206inline Vector<3> Rotate(double rx, double ry, double rz, const Vector<3> vec) {
207 ::Eigen::AngleAxis<double> ax(rx, ::Eigen::Vector3d(1.0, 0.0, 0.0));
208 ::Eigen::AngleAxis<double> ay(ry, ::Eigen::Vector3d(0.0, 1.0, 0.0));
209 ::Eigen::AngleAxis<double> az(rz, ::Eigen::Vector3d(0.0, 0.0, 1.0));
210 Vector<3> result;
211 result.SetData(ax * ay * az * vec.GetData());
212 return result;
213}
214
Parker Schuh6691f192017-01-14 17:01:02 -0800215// scalar multiply
216template <int Size>
217inline Vector<Size> operator*(const double &lhs, Vector<Size> &rhs) {
218 Vector<Size> nv;
219 for (int i = 0; i < Size; i++) {
220 nv.Set(i, lhs * rhs.Get(i));
221 }
222 return nv;
223}
Brian Silverman10fb0f32016-03-13 17:05:21 -0400224
225} // namespace vision
226} // namespace aos
227
228#endif // AOS_VISION_MATH_VECTOR_H_