SF2 C++ FRC Class Library
Sensor Fusion Framework (SF2) for FRC
navXSensor.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 #ifndef NAVXSENSOR_H_
25 #define NAVXSENSOR_H_
26 
27 #include "sensor/ISensorDataSource.h"
28 #include "sensor/ISensorInfo.h"
29 #include "sensor/ISensorDataSubscriber.h"
30 #include "sensor/SensorDataSourceInfo.h"
31 #include "sensor/IProcessorInfo.h"
32 #include "time/TimestampedValue.h"
33 #include "time/TimestampInfo.h"
34 #include "orientation/Quaternion.h"
35 #include "quantity/Scalar.h"
36 #include "unit/Unit.h"
37 #include "RoboRIO.h"
38 #include "AHRS.h"
39 
40 #include <string>
41 #include <forward_list>
42 using namespace std;
43 
44 class navXSensor: public ISensorDataSource, public ITimestampedDataSubscriber, public ISensorInfo {
45  AHRS& navx_sensor;
46  RoboRIO roborio;
47  vector<SensorDataSourceInfo *> sensor_data_source_infos;
49  long last_system_timestamp;
50  long last_sensor_timestamp;
51  string sensor_name;
52  forward_list<ISensorDataSubscriber *> tsq_subscribers;
53  bool navx_callback_registered;
54  vector<IQuantity*> active_sensor_data_quantities;
55  TimestampInfo navx_tsinfo;
56  priority_mutex subscriber_mutex;
57  Quaternion quaternion;
58  Scalar yaw, pitch, roll;
59  Timestamp ts;
60  Angle::Degrees degrees;
61  Time::Milliseconds milliseconds;
62  Timestamp roborio_timestamp;
63 
64 public:
65  const static int QUANTITY_INDEX_QUATERNION = 0;
66  const static int QUANTITY_INDEX_YAW = 1;
67  const static int QUANTITY_INDEX_PITCH = 2;
68  const static int QUANTITY_INDEX_ROLL = 3;
69 
70  navXSensor(AHRS* navx_sensor, string sensor_name) :
71  navx_sensor(*navx_sensor),
72  navx_tsinfo(TimestampInfo::Scope::Sensor,
73  TimestampInfo::Basis::SinceLastReboot,
74  1.0 / Timestamp::MILLISECONDS_PER_SECOND, /* Resolution */
75  1.0 / Timestamp::MILLISECONDS_PER_SECOND, /* Accuracy */
76  1.0 / (360 * Timestamp::MILLISECONDS_PER_SECOND),/* Clock Drift - seconds per hour */
77  1.0 / Timestamp::MILLISECONDS_PER_SECOND, /* Average Latency */
78  ts) /* Clock drift/hour */ {
79  this->curr_data.setValid(true);
80  this->sensor_name = sensor_name;
81  this->navx_callback_registered = false;
82  long default_timestamp_value = 0;
83  Timestamp ts(default_timestamp_value,
84  Timestamp::TimestampResolution::Millisecond);
85  vector<IUnit *>ms_units = {&milliseconds};
86  this->sensor_data_source_infos.push_back(new SensorDataSourceInfo("Timestamp", ts, milliseconds));
87  vector<IUnit *> quaternion_units;
88  Quaternion::getUnits(quaternion_units);
89  this->sensor_data_source_infos.push_back(new SensorDataSourceInfo("Quaternion", quaternion,
90  quaternion_units));
91  this->sensor_data_source_infos.push_back(new SensorDataSourceInfo("Yaw", yaw, degrees));
92  this->sensor_data_source_infos.push_back(new SensorDataSourceInfo("Pitch", pitch, degrees));
93  this->sensor_data_source_infos.push_back(new SensorDataSourceInfo("Roll", roll, degrees));
94  SensorDataSourceInfo::getQuantityArray(this->sensor_data_source_infos,
95  active_sensor_data_quantities);
96  last_sensor_timestamp = 0;
97  last_system_timestamp = 0;
98  }
99 
100  ~navXSensor() {
101  for (auto p_sensor_data_source_info : sensor_data_source_infos) {
102  delete p_sensor_data_source_info;
103  }
104  }
105 
106  bool subscribe(ISensorDataSubscriber* subscriber) {
107  {
108  std::unique_lock<priority_mutex> sync(subscriber_mutex);
109  bool existing = false;
110  for (auto tsq_subscriber : tsq_subscribers) {
111  if (tsq_subscriber == subscriber) {
112  existing = true;
113  break;
114  }
115  }
116  if (existing)
117  return false;
118  }
119 
120  if (!navx_callback_registered) {
121  navx_callback_registered = this->navx_sensor.RegisterCallback(this,
122  NULL);
123  }
124  if (navx_callback_registered) {
125  std::unique_lock<priority_mutex> sync(subscriber_mutex);
126  tsq_subscribers.push_front(subscriber);
127  return true;
128  }
129  return false;
130  }
131 
132  bool unsubscribe(ISensorDataSubscriber* subscriber) {
133  std::unique_lock<priority_mutex> sync(subscriber_mutex);
134 
135  bool existing = false;
136  for (auto tsq_subscriber : tsq_subscribers) {
137  if (tsq_subscriber == subscriber) {
138  existing = true;
139  break;
140  }
141  }
142  if (existing) {
143  return false;
144  }
145  tsq_subscribers.remove(subscriber);
146  if (tsq_subscribers.empty()) {
147  if (navx_callback_registered) {
148  navx_callback_registered =
149  this->navx_sensor.DeregisterCallback(this);
150  }
151  }
152  return true;
153  }
154 
155  void timestampedDataReceived(long system_timestamp, long sensor_timestamp,
156  AHRSProtocol::AHRSUpdateBase& data, void * context) {
157  std::unique_lock<priority_mutex> sync(subscriber_mutex);
158  ((Timestamp *) active_sensor_data_quantities[0])->setTimestamp(sensor_timestamp);
159  ((Quaternion *) active_sensor_data_quantities[1])->set(data.quat_w, data.quat_x, data.quat_y, data.quat_z);
160  ((Scalar *)active_sensor_data_quantities[2])->set(data.yaw);
161  ((Scalar *)active_sensor_data_quantities[3])->set(data.pitch);
162  ((Scalar *)active_sensor_data_quantities[4])->set(data.roll);
163 
164  roborio.getProcessorTimestamp(roborio_timestamp);
165  for (ISensorDataSubscriber *subscriber : tsq_subscribers) {
166  subscriber->publish(active_sensor_data_quantities, roborio_timestamp);
167  }
168  }
169 
170  IProcessorInfo& getHostProcessorInfo() {
171  return roborio;
172  }
173 
174  string getMake() {
175  return "Kauai Labs";
176  }
177 
178  string getModel() {
179  return "navX-MXP";
180  }
181 
182  string getName() {
183  return sensor_name;
184  }
185 
186  void getSensorDataSourceInfos(vector<SensorDataSourceInfo*>& infos) {
187  infos = this->sensor_data_source_infos;
188  }
189 
190  bool getCurrent(vector<IQuantity*>& quantities, Timestamp& curr_ts) {
191  if (this->navx_sensor.IsConnected()) {
192  ((Timestamp *) quantities[0])->setTimestamp(this->navx_sensor.GetLastSensorTimestamp());
193  ((Quaternion *) quantities[1])->set(this->navx_sensor.GetQuaternionW(), this->navx_sensor.GetQuaternionX(),
194  this->navx_sensor.GetDisplacementY(), this->navx_sensor.GetQuaternionZ());
195  ((Scalar *)quantities[2])->set(this->navx_sensor.GetYaw());
196  ((Scalar *)quantities[3])->set(this->navx_sensor.GetPitch());
197  ((Scalar *)quantities[4])->set(this->navx_sensor.GetRoll());
198  roborio.getProcessorTimestamp(curr_ts);
199  return true;
200  } else {
201  return false;
202  }
203  }
204 
205  ISensorDataSource& getSensorDataSource() {
206  return *this;
207  }
208 
209  TimestampInfo& getSensorTimestampInfo() {
210  return navx_tsinfo;
211  }
212 
213  bool reset(int index) {
214  if (index == QUANTITY_INDEX_YAW) {
215  navx_sensor.ZeroYaw();
216  return true;
217  }
218  return false;
219  }
220 };
221 
222 #endif /* NAVXSENSOR_H_ */
void setValid(bool valid)
Sets whether this TimestampedValue is valid or not.
Definition: TimestampedValue.h:184
Definition: SensorDataSourceInfo.h:37
Definition: TimestampInfo.h:28
bool subscribe(ISensorDataSubscriber *subscriber)
Subscribes the provided subscriber object for callbacks whenever new TimestampedQuaternion data is re...
Definition: navXSensor.h:106
The Quaternion class provides methods to operate on a quaternion.
Definition: Quaternion.h:76
Interface to be implemented by any subscriber of Sensor Data of type T.
Definition: ISensorDataSubscriber.h:40
bool getCurrent(vector< IQuantity * > &quantities, Timestamp &curr_ts)
Retrieves the most recently-received Sensor Data value.
Definition: navXSensor.h:190
Definition: IProcessorInfo.h:31
bool reset(int index)
For those quantities which can be reset to their default (e.g., an IMU Yaw, or an encoder counter)...
Definition: navXSensor.h:213
Definition: Scalar.h:35
Definition: Unit.h:380
Definition: Unit.h:249
The ITimestampedQuaternionSensor interface should be implemented by any sensor which generates timest...
Definition: ISensorDataSource.h:42
Definition: Timestamp.h:30
Definition: RoboRIO.h:32
Definition: ISensorInfo.h:34
bool unsubscribe(ISensorDataSubscriber *subscriber)
Unsubscribes the previously-registered subscriber object for callbacks whenever new Sensor Data is re...
Definition: navXSensor.h:132
Definition: navXSensor.h:44