SPIDAR API Library  0x16033101
Space Interface Device for Artificial Reality
PoseEstimation.hpp
Go to the documentation of this file.
1 
5 #ifndef SPIDAR_POSE_ESTIMATION_HPP
6 #define SPIDAR_POSE_ESTIMATION_HPP
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <cmath>
11 
12 #include "../math/Vector.hpp"
13 #include "../math/Matrix.hpp"
14 #include "../math/Cholesky.hpp"
15 
16 namespace Spidar
17 {
18 namespace Core
19 {
25 template <class T>
27 {
28 public:
29  typedef T TraitsType;
30 
31  static const size_t MOTOR_COUNT = TraitsType::MOTOR_COUNT;
32 
33  typedef typename TraitsType::SpecType SpecType;
34 
35  typedef typename TraitsType::ValueType ValueType;
36  typedef typename TraitsType::VectorType VectorType;
37  typedef typename TraitsType::QuaternionType QuaternionType;
38 
39  typedef typename TraitsType::PoseType PoseType;
40  typedef typename TraitsType::WireType WireType;
41 
42  typedef typename TraitsType::ValueFilterType ValueFilterType;
43  typedef typename TraitsType::VectorFilterType VectorFilterType;
44 
46  PoseEstimation(void) : initialized_(false), repeatCount_(64), sigma_(ValueType(0.001)) {};
47 
49  ~PoseEstimation(void) {};
50 
52  ValueType gripRadius(void) const { return gripRadius_; }
53 
55  const PoseType& pose(void) const { return pose_; }
56 
58  const WireType& wireVector(void) const { return wireVector_; }
59 
60  bool initialize(const SpecType& spec, uint32_t frequency);
61  void calibrate(const int32_t(&count)[MOTOR_COUNT]);
62  void estimate(const int32_t (&count)[MOTOR_COUNT]);
63 
64 private:
65  void makeWireVector(void);
66  void convertWireLength(const int32_t (&count)[MOTOR_COUNT]);
67 
68  bool initialized_;
69  size_t repeatCount_;
70  ValueType sigma_;
71 
72  ValueType controlFrequency_;
73 
74  ValueType gripRadius_;
75 
76  PoseType pose_;
77 
78  WireType wireVector_;
79 
81  ValueType lengthPerCount_[MOTOR_COUNT];
82 
84  long wireOffsetCount_[MOTOR_COUNT];
85 
87  VectorType motorPosition_[MOTOR_COUNT];
88 
90  VectorType gripPosition_[MOTOR_COUNT];
91 
93  ValueFilterType deltaLengthFilter_[MOTOR_COUNT];
94 
96  VectorFilterType velocityFilter_;
97 
99  VectorFilterType angularVelocityFilter_;
100 
101 }; // end of class PoseEstimation.
102 
111 template <class T>
112 bool PoseEstimation<T>::initialize(const SpecType& spec, uint32_t frequency)
113 {
114  // デバイス情報
115  const double PI = 3.14159265358979323846;
116 
117  for (size_t i=0; i<MOTOR_COUNT; ++i)
118  {
119  motorPosition_[i] = spec.motorPosition[i];
120  gripPosition_[i] = spec.gripPosition[i];
121 
122  ValueType lengthPerCount = static_cast<ValueType>(spec.pulleyRadius[i] * 2.0 * PI / spec.encoderResolution[i]);
123 
124  lengthPerCount_[i] = lengthPerCount * spec.encoderDirection[i];
125  wireOffsetCount_[i] = static_cast<long>((motorPosition_[i] - gripPosition_[i]).norm() / lengthPerCount_[i]);
126  }
127 
128  gripRadius_ = spec.gripRadius;
129 
130  // ローパスフィルタ
131  double timeConstatnt = 0.008;
132 
133  if (spec.majorLoopTimeConstant > 0) timeConstatnt = spec.majorLoopTimeConstant;
134 
135  double deltaTime = 1.0 / static_cast<ValueType>(frequency);
136 
137  velocityFilter_.initialize(deltaTime, spec.majorLoopTimeConstant);
138  angularVelocityFilter_.initialize(deltaTime, spec.majorLoopTimeConstant);
139 
140  for (size_t i=0; i<MOTOR_COUNT; ++i)
141  {
142  deltaLengthFilter_[i].initialize(deltaTime, spec.majorLoopTimeConstant);
143  }
144  return true;
145 }
146 
152 template <class T>
153 void PoseEstimation<T>::calibrate(const int32_t (&count)[MOTOR_COUNT])
154 {
155  pose_.clear();
156 
157  velocityFilter_.clear();
158  angularVelocityFilter_.clear();
159 
160  for (size_t i=0; i<MOTOR_COUNT; ++i)
161  {
162  deltaLengthFilter_[i].clear();
163  }
164 
165  makeWireVector();
166 
167  convertWireLength(count);
168 
169  estimate(count);
170 }
171 
177 template <class T>
178 void PoseEstimation<T>::estimate(const int32_t (&count)[MOTOR_COUNT])
179 {
180  // エンコーダ値からワイヤ長への変換
181  convertWireLength(count);
182 
183  PoseType prevPose = pose_;
184 
188 
189  // ワイヤ長の変化量 = 計測ワイヤ長 - 算出ワイヤ長
190  ValueType deltaLength[8];
191 
192  // repeatCount_回,繰り返しグリップの姿勢を計算
193  for (size_t step=0; step<repeatCount_; ++step)
194  {
195  // 行列の初期化
196  for (int i=0; i<8; ++i)
197  {
198  a[0][i] = wireVector_.direction[i].x();
199  a[1][i] = wireVector_.direction[i].y();
200  a[2][i] = wireVector_.direction[i].z();
201  a[3][i] = wireVector_.moment[i].x();
202  a[4][i] = wireVector_.moment[i].y();
203  a[5][i] = wireVector_.moment[i].z();
204 
205  deltaLength[i] = wireVector_.estimate[i] - wireVector_.measurement[i] - deltaLengthFilter_[i].value();
206  }
207 
208  // 対称行列の計算
209  ata = a * a.trans();
210 
211  // ベクトルv(求めた姿勢の変化量 = a * deltaLength)の初期化
212  for(int i=0; i<6; ++i)
213  {
214  v[i] = 0;
215  for(int k=0; k<8; ++k)
216  {
217  v[i] += a[i][k] * deltaLength[k];
218  }
219 
220  // 対角成分にsigma_を加える.
221  ata[i][i] += sigma_;
222  }
223 
224  // コレスキー法で解く
225  Math::Cholesky::solve(ata, v);
226 
227  // 出力
228  VectorType deltaPosition, deltaRotation;
229 
230  deltaPosition[0] = v[0];
231  deltaPosition[1] = v[1];
232  deltaPosition[2] = v[2];
233 
234  deltaRotation[0] = v[3];
235  deltaRotation[1] = v[4];
236  deltaRotation[2] = v[5];
237 
238  // 値の有効性の確認
239  if (deltaPosition.norm() > FLT_EPSILON)
240  {
241  pose_.position += deltaPosition;
242  }
243 
244  if (deltaRotation.norm() > FLT_EPSILON)
245  {
246  pose_.rotation = (pose_.rotation.derivative(deltaRotation) + pose_.rotation).unit();
247  }
248 
249  // ワイヤベクトルの再計算
250  makeWireVector();
251  }
252 
253  // ローパスフィルタを通し,速度を[m/ms]から[m/s]へ,角速度を[rad/ms]から[rad/s]へ変換
254  pose_.velocity = velocityFilter_.filter(pose_.position - prevPose.position) * controlFrequency_;
255  pose_.angularVelocity = angularVelocityFilter_.filter(pose_.rotation.angularVelocity(pose_.rotation - prevPose.rotation)) * controlFrequency_;
256 
257  // ローパスフィルタ
258  for (size_t i=0; i<8; ++i)
259  {
260  deltaLengthFilter_[i].filter(wireVector_.estimate[i] - wireVector_.measurement[i]);
261  }
262 }
263 
267 template <class T>
269 {
270  for (size_t i=0; i<MOTOR_COUNT; ++i)
271  {
272  // 現在の姿勢でのグリップ上のワイヤの接続位置を回転させて計算
273  VectorType rotateGripPos = pose_.rotation.rotate(gripPosition_[i]);
274 
275  // ワイヤベクトル(ワイヤの接続位置->モータ位置のベクトル)を計算
276  VectorType wireVector = motorPosition_[i] - (rotateGripPos + pose_.position);
277 
278  // 推定したワイヤ長はワイヤベクトルのノルム
279  wireVector_.estimate[i] = wireVector.norm();
280 
281  // ノルムで正規化しワイヤ方向を計算
282  wireVector_.direction[i] = wireVector / wireVector_.estimate[i];
283 
284  // 回転モーメントは外積から計算
285  wireVector_.moment[i] = rotateGripPos.cross(wireVector_.direction[i]);
286  }
287 }
288 
293 template <class T>
294 void PoseEstimation<T>::convertWireLength(const int32_t (&count)[MOTOR_COUNT])
295 {
296  for(size_t i=0; i<MOTOR_COUNT; ++i)
297  {
298  wireVector_.measurement[i] = lengthPerCount_[i] * (wireOffsetCount_[i] + count[i]);
299  }
300 }
301 
302 } // end of namespace Core.
303 } // end of namespace Spidar.
304 
305 #endif // SPIDAR_POSE_ESTIMATION_HPP
306 
307 // end of file.
308 
TraitsType::ValueType ValueType
値の型
static const size_t MOTOR_COUNT
モータの数(=ワイヤの本数)
bool initialize(const SpecType &spec, uint32_t frequency)
初期化関数です.
SPIDARライブラリのルート名前空間です.
ベクトルクラスです.
Definition: Vector.hpp:24
TraitsType::QuaternionType QuaternionType
四元数の型
TraitsType::ValueFilterType ValueFilterType
値のためのローパスフィルタの型
TraitsType::WireType WireType
ワイヤベクトルの型
void estimate(const int32_t(&count)[MOTOR_COUNT])
グリップ姿勢の推定を行います.
姿勢推定を行い,ワイヤベクトルを計算するクラスです.
static void solve(MatrixType &mat, VectorType &vec)
コレスキー分解を用いて連立一次方程式を解きます.
Definition: Cholesky.hpp:75
TraitsType::VectorFilterType VectorFilterType
ベクトルのためのローパスフィルタの型
行列クラスです.
Definition: Matrix.hpp:25
void calibrate(const int32_t(&count)[MOTOR_COUNT])
グリップ姿勢のキャリブレーションを行います.
TraitsType::VectorType VectorType
ベクトルの型
PoseEstimation(void)
コンストラクタ.
~PoseEstimation(void)
デストラクタ.
const WireType & wireVector(void) const
ワイヤベクトルを取得します.
TraitsType::SpecType SpecType
デバイス情報の型
TraitsType::PoseType PoseType
グリップ姿勢の型
const PoseType & pose(void) const
グリップ姿勢を取得します.
ValueType gripRadius(void) const
グリップ半径を取得します.