SF2 C++ FRC Class Library
Sensor Fusion Framework (SF2) for FRC
Unit.h
1 /* ============================================
2  SF2 source code is placed under the MIT license
3  Copyright (c) 2017 Kauai Labs
4 
5  Permission is hereby granted, free of charge, to any person obtaining a copy
6  of this software and associated documentation files (the "Software"), to deal
7  in the Software without restriction, including without limitation the rights
8  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  copies of the Software, and to permit persons to whom the Software is
10  furnished to do so, subject to the following conditions:
11 
12  The above copyright notice and this permission notice shall be included in
13  all copies or substantial portions of the Software.
14 
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  THE SOFTWARE.
22  ===============================================
23  */
24 
25 #ifndef SRC_UNIT_UNIT_H_
26 #define SRC_UNIT_UNIT_H_
27 
28 #include <vector>
29 #include <string>
30 
31 using namespace std;
32 
33 class Unit {
34 public:
35  float convertToPrimaryUnits(float value) {
36  return value;
37  }
38  float convertFromPrimaryUnits(float value) {
39  return value;
40  }
41 };
42 
43 class IUnit {
44 public:
45  virtual string getName() = 0;
46  virtual string getAbbreviation() = 0;
47 };
48 
49 class IUnitFamily {
50 public:
51  virtual IUnit& getPrimaryUnit() = 0;
52  virtual vector<IUnit *>& getSecondaryUnits() = 0; /* May return an empty list. */
53 };
54 
56 public:
57  virtual IUnitFamily& getUnitFamily() = 0;
58 };
59 
60 class Unitless: public IUnit {
61 public:
62  string getName() {
63  return "(Unitless)";
64  }
65  string getAbbreviation() {
66  return "(u)";
67  }
68 };
69 
71 public:
72  class Volts: public Unit, public IUnit {
73  public:
74  string getName() {
75  return "Volts";
76  }
77  string getAbbreviation() {
78  return "V";
79  }
80  };
81  Volts primary_unit;
82  vector<IUnit *> secondary_units;
83  IUnit& getPrimaryUnit() {
84  return primary_unit;
85  }
86  vector<IUnit *>& getSecondaryUnits() {
87  return secondary_units;
88  }
89 };
90 
92 public:
93  class Amps: public Unit, public IUnit {
94  public:
95  string getName() {
96  return "Amps";
97  }
98  string getAbbreviation() {
99  return "A";
100  }
101  };
102  Amps primary_unit;
103  vector<IUnit *> secondary_units;
104  IUnit& getPrimaryUnit() {
105  return primary_unit;
106  }
107 
108  vector<IUnit *>& getSecondaryUnits() {
109  return secondary_units;
110  }
111 };
112 
113 class Distance: public IUnitFamily {
114  static Distance *p_unit_family;
115 public:
116  class DistanceUnit: public Unit, public IUnitDescendant {
117  public:
118  IUnitFamily& getUnitFamily() {
119  return *Distance::p_unit_family;
120  }
121  };
122 
123  class Meters: public DistanceUnit, public IUnit {
124  public:
125  string getName() {
126  return "Meters";
127  }
128  string getAbbreviation() {
129  return "m";
130  }
131  };
132  class Inches: public DistanceUnit, public IUnit {
133  public:
134  static constexpr float METERS_PER_INCH = .0254f;
135  static constexpr float INCHES_PER_METER = 1.0f / METERS_PER_INCH;
136 
137  string getName() {
138  return "Inches";
139  }
140  string getAbbreviation() {
141  return "in";
142  }
143  float convertToPrimaryUnits(float value) {
144  return value * METERS_PER_INCH;
145  }
146  float convertFromPrimaryUnits(float value) {
147  return value * INCHES_PER_METER;
148  }
149  };
150  class Feet: public DistanceUnit, public IUnit {
151  public:
152  static constexpr float INCHES_PER_FOOT = 12.0f;
153  static constexpr float METERS_PER_FOOT = Inches::METERS_PER_INCH
154  * INCHES_PER_FOOT;
155  static constexpr float FEET_PER_METER = 1.0f / METERS_PER_FOOT;
156 
157  string getName() {
158  return "Feet";
159  }
160  string getAbbreviation() {
161  return "ft";
162  }
163  float convertToPrimaryUnits(float value) {
164  return value * METERS_PER_FOOT;
165  }
166  float convertFromPrimaryUnits(float value) {
167  return value * FEET_PER_METER;
168  }
169  };
170  class Millimeters: public DistanceUnit, public IUnit {
171  public:
172  static constexpr float MILLIMETERS_PER_METER = 1000.0f;
173  static constexpr float METERS_PER_MILLIMETER = 1.0f / 1000.0f;
174 
175  string getName() {
176  return "Millimeters";
177  }
178  string getAbbreviation() {
179  return "m";
180  }
181  float convertToPrimaryUnits(float value) {
182  return value * METERS_PER_MILLIMETER;
183  }
184  float convertFromPrimaryUnits(float value) {
185  return value * MILLIMETERS_PER_METER;
186  }
187  };
188  class Centimeters: public DistanceUnit, public IUnit {
189  public:
190  static constexpr float CENTIMETERS_PER_METER = 100.0f;
191  static constexpr float METERS_PER_CENTIMETER = 1.0f / 100.0f;
192 
193  string getName() {
194  return "Centimeters";
195  }
196  string getAbbreviation() {
197  return "cm";
198  }
199  float convertToPrimaryUnits(float value) {
200  return value * METERS_PER_CENTIMETER;
201  }
202  float convertFromPrimaryUnits(float value) {
203  return value * CENTIMETERS_PER_METER;
204  }
205  };
206 
207  Meters meters;
208  Inches inches;
209  Feet feet;
210  Millimeters millimeters;
211  Centimeters centimeters;
212  vector<IUnit *> secondary_units;
213 
214  IUnit& getPrimaryUnit() {
215  return meters;
216  }
217  ;
218  Distance() {
219  secondary_units.push_back(&inches);
220  secondary_units.push_back(&feet);
221  secondary_units.push_back(&millimeters);
222  secondary_units.push_back(&centimeters);
223  }
224  vector<IUnit *>& getSecondaryUnits() {
225  return secondary_units;
226  }
227 };
228 
229 class Angle: public IUnitFamily {
230  static Angle *p_unit_family;
231  static constexpr float PI = 3.14159265358979f;
232 public:
233  class AngleUnit: public Unit, public IUnit, public IUnitDescendant {
234  IUnitFamily& getUnitFamily() {
235  return *Angle::p_unit_family;
236  }
237  };
238 
239  class Radians: public AngleUnit {
240  public:
241  string getName() {
242  return "Radians";
243  }
244  string getAbbreviation() {
245  return "rad";
246  }
247  };
248 
249  class Degrees: public AngleUnit {
250  public:
251  /* Range: -180.0 to 180.0 */
252  static constexpr float RADIANS_TO_DEGREES = (float) (180.0 / Angle::PI);
253  static constexpr float DEGREES_TO_RADIANS = (float) (Angle::PI / 180.0);
254  string getName() {
255  return "Degrees";
256  }
257  string getAbbreviation() {
258  return "deg";
259  }
260  float convertToPrimaryUnits(float value) {
261  return value * DEGREES_TO_RADIANS;
262  }
263  float convertFromPrimaryUnits(float value) {
264  return value * RADIANS_TO_DEGREES;
265  }
266  };
267 
268  class CompassHeading: public AngleUnit {
269  public:
270  /* North is 0 degrees, range 0-360. */
271  static constexpr float DEGREES_IN_HALF_CIRCLE = 180.0f;
272  string getName() {
273  return "Heading";
274  }
275  string getAbbreviation() {
276  return "deg";
277  }
278  float convertToPrimaryUnits(float value) {
279  return (value - DEGREES_IN_HALF_CIRCLE)
280  * Degrees::DEGREES_TO_RADIANS;
281  }
282  float convertFromPrimaryUnits(float value) {
283  return (value * Degrees::RADIANS_TO_DEGREES)
284  + DEGREES_IN_HALF_CIRCLE;
285  }
286  };
287  class Revolutions: public AngleUnit {
288  public:
289  static constexpr float REVOLUTIONS_TO_RADIANS = (float) (2.0f
290  * Angle::PI);
291  static constexpr float RADIANS_TO_REVOLUTIONS = 1.0f
292  / REVOLUTIONS_TO_RADIANS;
293  string getName() {
294  return "Revolutions";
295  }
296  string getAbbreviation() {
297  return "ref";
298  }
299  float convertToPrimaryUnits(float value) {
300  return value * REVOLUTIONS_TO_RADIANS;
301  }
302  float convertFromPrimaryUnits(float value) {
303  return value * RADIANS_TO_REVOLUTIONS;
304  }
305  };
306 
307  Radians radians;
308  vector<IUnit *> secondary_units;
309  Degrees degrees;
310  CompassHeading compass;
311  Revolutions revolutions;
312  IUnit& getPrimaryUnit() {
313  return radians;
314  }
315  ;
316  Angle() {
317  secondary_units.push_back(&degrees);
318  secondary_units.push_back(&compass);
319  secondary_units.push_back(&revolutions);
320  }
321  vector<IUnit *>& getSecondaryUnits() {
322  return secondary_units;
323  }
324 };
325 
326 class Time: public IUnitFamily {
327  static Time *p_unit_family;
328 public:
330  public:
331  IUnitFamily& getUnitFamily() {
332  return *Time::p_unit_family;
333  }
334  };
335 
336  class Nanoseconds : public TimeUnit, public IUnit {
337  public:
338  static constexpr float SECONDS_TO_NANOSECONDS = (float) (1.0f * 1000000000);
339  static constexpr float NANOSECONDS_TO_SECONDS = (float) (1.0f / 1000000000);
340 
341  string getName() {
342  return "Nanoseconds";
343  }
344 
345  string getAbbreviation() {
346  return "ns";
347  }
348 
349  float convertToPrimaryUnits(float value) {
350  return value * NANOSECONDS_TO_SECONDS;
351  }
352 
353  float convertFromPrimaryUnits(float value) {
354  return value * SECONDS_TO_NANOSECONDS;
355  }
356  };
357 
358  class Microseconds : public TimeUnit, public IUnit {
359  public:
360  static constexpr float SECONDS_TO_MICROSECONDS = (float) (1.0f * 1000000);
361  static constexpr float MICROSECONDS_TO_SECONDS = (float) (1.0f / 1000000);
362 
363  string getName() {
364  return "Microseconds";
365  }
366 
367  string getAbbreviation() {
368  return "us";
369  }
370 
371  float convertToPrimaryUnits(float value) {
372  return value * MICROSECONDS_TO_SECONDS;
373  }
374 
375  float convertFromPrimaryUnits(float value) {
376  return value * SECONDS_TO_MICROSECONDS;
377  }
378  };
379 
380 class Milliseconds : public TimeUnit, public IUnit {
381  public:
382  static constexpr float SECONDS_TO_MILLISECONDS = (float) (1.0f * 1000);
383  static constexpr float MILLISECONDS_TO_SECONDS = (float) (1.0f / 1000);
384 
385  string getName() {
386  return "Milliseconds";
387  }
388 
389  string getAbbreviation() {
390  return "ms";
391  }
392 
393  float convertToPrimaryUnits(float value) {
394  return value * MILLISECONDS_TO_SECONDS;
395  }
396 
397  float convertFromPrimaryUnits(float value) {
398  return value * SECONDS_TO_MILLISECONDS;
399  }
400 };
401 
402  class Seconds: public TimeUnit, public IUnit {
403  public:
404  string getName() {
405  return "Seconds";
406  }
407  string getAbbreviation() {
408  return "sec";
409  }
410  };
411  class Hours: public TimeUnit, public IUnit {
412  public:
413  static constexpr float HOURS_TO_SECONDS = (float) (60 * 60);
414  static constexpr float SECONDS_TO_HOURS = (float) (1.0f
415  / HOURS_TO_SECONDS);
416  string getName() {
417  return "Hours";
418  }
419  string getAbbreviation() {
420  return "hr";
421  }
422  float convertToPrimaryUnits(float value) {
423  return value * HOURS_TO_SECONDS;
424  }
425  float convertFromPrimaryUnits(float value) {
426  return value * SECONDS_TO_HOURS;
427  }
428  };
429  class Minutes: public TimeUnit, public IUnit {
430  public:
431  static constexpr float MINUTES_TO_SECONDS = (float) (60);
432  static constexpr float SECONDS_TO_MINUTES = (float) (1.0f
433  / MINUTES_TO_SECONDS);
434  string getName() {
435  return "Minutes";
436  }
437  string getAbbreviation() {
438  return "min";
439  }
440  float convertToPrimaryUnits(float value) {
441  return value * MINUTES_TO_SECONDS;
442  }
443  float convertFromPrimaryUnits(float value) {
444  return value * SECONDS_TO_MINUTES;
445  }
446  };
447 
448  Nanoseconds nanoseconds;
449  Microseconds microseconds;
450  Milliseconds milliseconds;
451  Seconds seconds;
452  Hours hours;
453  Minutes minutes;
454  IUnit& getPrimaryUnit() {
455  return seconds;
456  }
457 
458  vector<IUnit *> secondary_units;
459  Time() {
460  secondary_units.push_back(&hours);
461  secondary_units.push_back(&minutes);
462  secondary_units.push_back(&milliseconds);
463  secondary_units.push_back(&microseconds);
464  secondary_units.push_back(&nanoseconds);
465  }
466 
467  vector<IUnit *>& getSecondaryUnits() {
468  return secondary_units;
469  }
470 };
471 
473  static SecondDerivative *p_unit_family;
474 public:
475  class SecondDerivativeUnit: public Unit, public IUnitDescendant {
476  public:
477  IUnitFamily& getUnitFamily() {
478  return *SecondDerivative::p_unit_family;
479  }
480  };
481  class SecondsSquared: public Unit, public IUnit {
482  string getName() {
483  return "Squared Seconds";
484  }
485  string getAbbreviation() {
486  return "s^2";
487  }
488  };
489  SecondsSquared seconds_squared;
490  vector<IUnit *> secondary_units;
491  IUnit& getPrimaryUnit() {
492  return seconds_squared;
493  }
494  vector<IUnit *>& getSecondaryUnits() {
495  return secondary_units;
496  }
497 };
498 
500  static ThirdDerivative *p_unit_family;
501 public:
502  class ThirdDerivativeUnit: public Unit, public IUnitDescendant {
503  public:
504  IUnitFamily& getUnitFamily() {
505  return *ThirdDerivative::p_unit_family;
506  }
507  };
508  class SecondsCubed: public Unit, public IUnit {
509  public:
510  string getName() {
511  return "Cubed Seconds";
512  }
513  string getAbbreviation() {
514  return "s^3";
515  }
516  };
517  SecondsCubed seconds_cubed;
518  vector<IUnit *> secondary_units;
519  IUnit& getPrimaryUnit() {
520  return seconds_cubed;
521  }
522  vector<IUnit *>& getSecondaryUnits() {
523  return secondary_units;
524  }
525 };
526 
527 #endif /* SRC_UNIT_UNIT_H_ */
Definition: Unit.h:150
Definition: Unit.h:358
Definition: Unit.h:132
Definition: Unit.h:472
Definition: Unit.h:72
Definition: Unit.h:123
Definition: Unit.h:287
Definition: Unit.h:93
Definition: Unit.h:116
Definition: Unit.h:329
Definition: Unit.h:508
Definition: Unit.h:411
Definition: Unit.h:43
Definition: Unit.h:481
Definition: Unit.h:70
Definition: Unit.h:170
Definition: Unit.h:33
Definition: Unit.h:91
Definition: Unit.h:229
Definition: Unit.h:239
Definition: Unit.h:113
Definition: Unit.h:55
Definition: Unit.h:380
Definition: Unit.h:499
Definition: Unit.h:429
Definition: Unit.h:233
Definition: Unit.h:249
Definition: Unit.h:336
Definition: Unit.h:188
Definition: Unit.h:326
Definition: Unit.h:60
Definition: Unit.h:402
Definition: Unit.h:268
Definition: Unit.h:49