NASA Astrobee Robot Software  0.19.1
Flight software for the Astrobee robots operating inside the International Space Station.
vive_solver.h
Go to the documentation of this file.
1 /* Copyright (c) 2017, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The Astrobee platform is licensed under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */
18 
19 #ifndef LOCALIZATION_VIVE_LOCALIZATION_SRC_VIVE_SOLVER_H_
20 #define LOCALIZATION_VIVE_LOCALIZATION_SRC_VIVE_SOLVER_H_
21 
22 // ROS includes
23 #include <ros/ros.h>
24 
25 // Common messages
26 #include <geometry_msgs/PoseStamped.h>
27 #include <nav_msgs/Path.h>
28 
29 // Our messages
30 #include <ff_hw_msgs/ViveLight.h>
31 #include <ff_hw_msgs/ViveLighthouses.h>
32 #include <ff_hw_msgs/ViveTrackers.h>
33 
34 // Ceres and logging
35 #include <ceres/ceres.h>
36 #include <ceres/rotation.h>
37 
38 // STL
39 #include <string>
40 #include <vector>
41 #include <map>
42 #include <fstream>
43 #include <numeric>
44 
45 // Local includes
46 #include "./vive.h"
47 
51 namespace vive_localization {
52 
54 // ROTATION FUNCTIONS //
56 
57 // Helper function to apply a transform b = Ra + t
58 template <typename T> inline
59 void TransformInPlace(const T transform[6], T x[3]) {
60  T tmp[3];
61  ceres::AngleAxisRotatePoint(&transform[3], x, tmp);
62  x[0] = tmp[0] + transform[0];
63  x[1] = tmp[1] + transform[1];
64  x[2] = tmp[2] + transform[2];
65 }
66 
67 // Helper function to invert a transform a = R'(b - t)
68 template <typename T> inline
69 void InverseTransformInPlace(const T transform[6], T x[3]) {
70  T aa[3], tmp[3];
71  tmp[0] = x[0] - transform[0];
72  tmp[1] = x[1] - transform[1];
73  tmp[2] = x[2] - transform[2];
74  aa[0] = -transform[3];
75  aa[1] = -transform[4];
76  aa[2] = -transform[5];
77  ceres::AngleAxisRotatePoint(aa, tmp, x);
78 }
79 
80 // Helper function to combine / multiply to transforms
81 // B ( A ( x ) ) = (B * A) (x)
82 // = Rb * (Ra x + Ta) + Tb
83 // = Rb * Ra * x + (Rb * Ta + Tb)
84 // | ROTATION | | TRANSLATION |
85 template <typename T> inline
86 void CombineTransforms(const T b[6], const T a[6], T ba[6]) {
87  T b_q[4], a_q[4], ba_q[4];
88  // Calculate translation component
89  for (size_t i = 0; i < 3; i++)
90  ba[i] = a[i];
91  TransformInPlace(b, ba);
92  // Calculate rotation component
93  ceres::AngleAxisToQuaternion(&a[3], a_q);
94  ceres::AngleAxisToQuaternion(&b[3], b_q);
95  ceres::QuaternionProduct(b_q, a_q, ba_q);
96  ceres::QuaternionToAngleAxis(ba_q, &ba[3]);
97 }
98 
99 // Helper function to calcuate the error between two transforms
100 template <typename T> inline
101 void TransformError(const T a[6], const T b[6], T err[6]) {
102  T a_aa[3], b_aa[3], a_q[4], b_q[4], q[4];
103  for (size_t i = 0; i < 3; i++) {
104  err[i] = a[i] - b[i];
105  a_aa[i] = a[3+i];
106  b_aa[i] = -b[3+i];
107  }
108  ceres::AngleAxisToQuaternion(a_aa, a_q);
109  ceres::AngleAxisToQuaternion(b_aa, b_q);
110  ceres::QuaternionProduct(a_q, b_q, q);
111  ceres::QuaternionToAngleAxis(q, &err[3]);
112 }
113 
115 // SMOOTHING COST FUNCTOR //
117 
118 // Trajectory is a sequence of states
119 typedef std::map<ros::Time, double[6]> Trajectory; // pos, att
120 
121 // Residual error between sequential poses
122 struct SmoothCost {
123  explicit SmoothCost(double smooth) : smooth_(smooth) {}
124  // Called by ceres-solver to calculate error
125  template <typename T>
126  bool operator()(const T* const prev_state, // PREV state
127  const T* const next_state, // NEXT state
128  T* residual) const {
129  // Error between two transforms
130  TransformError(prev_state, next_state, residual);
131  // Weighting
132  for (size_t i = 0; i < 6; i++)
133  residual[i] *= T(smooth_);
134  // Success!
135  return true;
136  }
137 
138  private:
139  double smooth_; // Smoothing factor -- just a weighting
140 };
141 
143 // LIGHT COST FUNCTOR //
145 
146 // Bundle of sensor measurements at a given instant in time
147 typedef std::map<ros::Time, // Time
148  std::map<uint8_t, // Lighthouse
149  std::map<std::string, // Tracker
150  std::map<uint8_t, // Sensor
151  std::map<uint8_t, // Axis
152  std::vector<double> // Sample
153  >
154  >
155  >
156  >
158 
159 // Residual error between predicted angles to a lighthouse
160 struct LightCost {
161  explicit LightCost(uint16_t sensor, double angles[2], bool correct)
162  : sensor_(sensor), correct_(correct) {
163  obs_[0] = angles[0];
164  obs_[1] = angles[1];
165  }
166  // Called by ceres-solver to calculate error
167  template <typename T>
168  bool operator()(const T* const vTl, // Lighthouse -> vive
169  const T* const vTb, // Body -> vive
170  const T* const bTh, // Head -> body
171  const T* const tTh, // Head -> tracking (light)
172  const T* const sensors, // Lighthouse calibration
173  const T* const params, // Tracker extrinsics
174  T* residual) const {
175  // Get the sensor position in the tracking frame
176  T x[3], angle[2];
177  x[0] = sensors[6 * sensor_ + 0];
178  x[1] = sensors[6 * sensor_ + 1];
179  x[2] = sensors[6 * sensor_ + 2];
180  // Project the sensor position into the lighthouse frame
181  InverseTransformInPlace(tTh, x); // light -> head
182  TransformInPlace(bTh, x); // head -> body
183  TransformInPlace(vTb, x); // body -> world
184  InverseTransformInPlace(vTl, x); // vive -> lighthouse
185  // Predict the angles - Note that the
186  Predict(params, x, angle, correct_);
187  // The residual angle error for the specific axis
188  residual[0] = angle[0] - T(obs_[0]);
189  residual[1] = angle[1] - T(obs_[1]);
190  // Success!
191  return true;
192  }
193 
194  private:
195  // Internal variables
196  uint16_t sensor_; // Sensor
197  double obs_[2]; // Observation
198  bool correct_; // Whether to correct the light measurements
199 };
200 
202 // SOLVER CLASS //
204 
205 // Class to solve the localization problem offline
206 class Solver {
207  public:
208  explicit Solver(ros::NodeHandle nh);
209  void Add(ff_hw_msgs::ViveTrackers::ConstPtr msg, ros::Time const& t);
210  void Add(ff_hw_msgs::ViveLighthouses::ConstPtr msg, ros::Time const& t);
211  void Add(ff_hw_msgs::ViveLight::ConstPtr msg, ros::Time const& t);
212  void Add(geometry_msgs::PoseStamped::ConstPtr msg, ros::Time const& t);
213  bool Calibrate();
214  bool Refine();
215  bool Register();
216  bool Solve();
217  void Publish(ros::Publisher & pub,
218  std::string const& frame, std::map<ros::Time, double[6]> const& x);
219  void PrintTransform(const double transform[6]);
220  void GetTruth(nav_msgs::Path & path);
221  void GetVive(nav_msgs::Path & path);
222 
223  private:
224  double res_, smooth_, min_angle_, max_angle_, duration_;
225  size_t count_;
226  bool correct_, calibrate_, refine_, register_,
227  refine_extrinsics_, refine_sensors_, refine_head_, refine_params_;
228  Eigen::Vector3d modification_vector;
229  Eigen::Quaterniond modification_quaternion;
230  ceres::Solver::Options options_; // Solver options
231  double wTv_[6]; // Registation
232  std::map<std::string, Eigen::Affine3d> calibration_;
233  LighthouseMap lighthouses_; // Lighthouse info
234  TrackerMap trackers_; // Tracker info
235  Trajectory trajectory_; // Trajectory
236  Trajectory correction_; // Corrections
237  LightMeasurements light_; // Light measurements
238  ros::Publisher pub_vive_, pub_ekf_; // Path publisher for trajectory
239 };
240 
241 } // namespace vive_localization
242 
243 #endif // LOCALIZATION_VIVE_LOCALIZATION_SRC_VIVE_SOLVER_H_
vive_localization::Solver::Solve
bool Solve()
Definition: vive_solver.cc:419
vive_localization::TransformError
void TransformError(const T a[6], const T b[6], T err[6])
Definition: vive_solver.h:101
vive_localization::Solver::Calibrate
bool Calibrate()
Definition: vive_solver.cc:160
vive_localization::Solver::Refine
bool Refine()
Definition: vive_solver.cc:289
vive_localization::Solver::PrintTransform
void PrintTransform(const double transform[6])
Definition: vive_solver.cc:544
vive_localization::Solver::Solver
Solver(ros::NodeHandle nh)
Definition: vive_solver.cc:27
vive_localization::TransformInPlace
void TransformInPlace(const T transform[6], T x[3])
Definition: vive_solver.h:59
vive_localization::TrackerMap
std::map< std::string, Tracker > TrackerMap
Definition: vive.h:100
point_cloud_common::Vector3d
Eigen::Vector3d Vector3d(const PointType &point)
Definition: utilities.h:328
vive_localization::SmoothCost
Definition: vive_solver.h:122
vive_localization::LighthouseMap
std::map< uint8_t, Lighthouse > LighthouseMap
Definition: vive.h:89
vive_localization::InverseTransformInPlace
void InverseTransformInPlace(const T transform[6], T x[3])
Definition: vive_solver.h:69
vive_localization::LightMeasurements
std::map< ros::Time, std::map< uint8_t, std::map< std::string, std::map< uint8_t, std::map< uint8_t, std::vector< double > > > > > > LightMeasurements
Definition: vive_solver.h:157
vive_localization::Solver::Register
bool Register()
Definition: vive_solver.cc:380
vive_localization::LightCost::LightCost
LightCost(uint16_t sensor, double angles[2], bool correct)
Definition: vive_solver.h:161
vive_localization::LightCost
Definition: vive_solver.h:160
vive_localization::SmoothCost::operator()
bool operator()(const T *const prev_state, const T *const next_state, T *residual) const
Definition: vive_solver.h:126
vive_localization::Solver::GetVive
void GetVive(nav_msgs::Path &path)
Definition: vive_solver.cc:589
vive_localization
Definition: vive.cc:34
vive.h
vive_localization::Solver::Add
void Add(ff_hw_msgs::ViveTrackers::ConstPtr msg, ros::Time const &t)
Definition: vive_solver.cc:123
vive_localization::LightCost::operator()
bool operator()(const T *const vTl, const T *const vTb, const T *const bTh, const T *const tTh, const T *const sensors, const T *const params, T *residual) const
Definition: vive_solver.h:168
vive_localization::SmoothCost::SmoothCost
SmoothCost(double smooth)
Definition: vive_solver.h:123
vive_localization::CombineTransforms
void CombineTransforms(const T b[6], const T a[6], T ba[6])
Definition: vive_solver.h:86
vive_localization::Solver::Publish
void Publish(ros::Publisher &pub, std::string const &frame, std::map< ros::Time, double[6]> const &x)
vive_localization::Solver::GetTruth
void GetTruth(nav_msgs::Path &path)
Definition: vive_solver.cc:563
vive_localization::Solver
Definition: vive_solver.h:206
vive_localization::Trajectory
std::map< ros::Time, double[6]> Trajectory
Definition: vive_solver.h:119
vive_localization::Predict
static void Predict(T const *params, T const *xyz, T *ang, bool correct)
Definition: vive.h:235
localization_common::Time
double Time
Definition: time.h:23