1 /*---------------------------------------------------------------------------* 2 Project: horizon 3 File: hid_GyroscopeReader.h 4 5 Copyright 2010 Nintendo. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: $ 14 *---------------------------------------------------------------------------*/ 15 16 /*! @file 17 @brief GyroscopeReaderクラスを定義します 18 19 */ 20 21 #ifndef NN_HID_CTR_GYROSCOPEREADER_H_ 22 #define NN_HID_CTR_GYROSCOPEREADER_H_ 23 24 #include <nn/Handle.h> 25 #include <nn/Result.h> 26 #include <nn/types.h> 27 #include <nn/hid/CTR/hid_Result.h> 28 #include <nn/hid/CTR/hid_Api.h> 29 #include <nn/hid/CTR/hid_Gyroscope.h> 30 #include <nn/hid/CTR/hid_AccelerometerReader.h> 31 #include <nn/hid/CTR/hid_DeviceStatus.h> 32 #include <nn/util/util_SizedEnum.h> 33 #include <nn/util/util_NonCopyable.h> 34 35 36 namespace nn 37 { 38 namespace hid 39 { 40 namespace CTR 41 { 42 43 /*! 44 @brief ゼロ点のドリフト修正の強度を設定する列挙体です 45 */ 46 enum ZeroDriftMode 47 { 48 GYROSCOPE_ZERODRIFT_LOOSE, //!< センサの値がある程度変動していても、安定しているとみなして修正が行われるモードです。 49 GYROSCOPE_ZERODRIFT_STANDARD,//!< GYROSCOPE_ZERODRIFT_LOOSE と GYROSCOPE_ZERODRIFT_TIGHT の中間にあたるモードです。 50 GYROSCOPE_ZERODRIFT_TIGHT,//!< センサの値が定められた閾値以内の変動でないと、安定しているとみなさない厳密な修正が行われるモードです。 51 GYROSCOPE_ZERODRIFT_NUM 52 }; 53 54 55 /*! 56 @brief ジャイロセンサのサンプリングデータを読み込むクラスです。 57 58 注意) ジャイロセンサのサンプリングは平均 10 msec 周期で行われます。 59 60 ジャイロセンサのサンプリングは、本クラスのインスタンスを生成した段階から行われるため、 61 サンプリングデータを読み込めるのは、インスタンス生成後 10 msec 経過した後になります。 62 また、内部にAccelerometerReaderのインスタンスを保持しているため、ジャイロセンサを使用する際には加速度センサも自動的に起動状態となります。 63 64 nn::hid::GyroscopeReader::EnableAxisRotation( ) を使用することで、加工した出力値を得ることができます。 65 加工によって、センサが傾いて配置されているような出力値を得ることができます。 66 詳細は関数のリファレンスを参照してください。 67 68 ジャイロセンサの軸は以下のようになっています。<BR> 69 X+:十字ボタンの左方向<BR> 70 Y+:タッチパネルの実装面方向<BR> 71 Z+:十字ボタンの上方向<BR> 72 */ 73 class GyroscopeReader: private nn::util::NonCopyable<GyroscopeReader> 74 { 75 public: 76 77 78 /*! 79 @brief コンストラクタです。 80 81 インスタンスを生成する前に @ref nn::hid::CTR::Initialize( ) で初期化してください。 82 @param[in] pAccelerometrReader AccelerometerReaderへの参照を指定すると、参照するAccelerometerReaderの出力値を利用した補正を行います。 83 デフォルトではNULLが渡され、この場合内部に保持するデフォルトのAccelerometerReaderによって補正を行います。 84 85 */ 86 GyroscopeReader(AccelerometerReader* pAccelerometerReader = NULL, Gyroscope& gyroscope = GetGyroscope()); 87 88 /*! 89 @brief デストラクタです。 90 91 */ 92 ~GyroscopeReader(); 93 94 /*! 95 @brief ジャイロセンサのサンプリングデータを新しいものから順に読み込みます。以前に読み込んだデータは読み込まれません。 96 97 @param[out] pBufs 新しいものから順にサンプリングデータが読み込まれます。 98 @param[out] pReadLen 読み込んだサンプリングデータの数です。 99 @param[in] bufLen pBufs に読み込めるサンプリングデータの数を指定します。 100 @return なし。 101 102 */ 103 void Read(GyroscopeStatus* pBufs, s32* pReadLen, s32 bufLen); 104 105 /*! 106 @brief 最新のジャイロセンサのサンプリングデータを読み込みます。 nn::hid::CTR::GyroscopeReader::Read( ) とちがい同じサンプリングデータを読み込むことが出来ます。 107 108 @param[out] pBuf サンプリングデータが読み込まれます。 109 @return サンプリングデータの読み込み結果を返します。<BR> 110 true ・・・ 読み込めました。<BR> 111 false ・・・ 読み込めませんでした。(GyroscopeReaderのインスタンス生成後あるいはスリープ復帰後の最初のサンプリングが行われ次第、読み込めます。) 112 113 */ 114 bool ReadLatest(GyroscopeStatus* pBuf); 115 116 /*! 117 @brief 内部状態を初期化します。 118 119 このとき、各種補正処理の設定も以下のようになります。 120 121 ゼロ点の遊び 無効になります。<BR> 122 加速度の補正 有効になります。<BR> 123 ゼロ点のドリフト補正 GYROSCOPE_ZERODRIFT_STANDARD に設定されます。<BR> 124 角速度の倍率 1.0 に設定されます。 125 126 @return なし。 127 */ 128 void Reset(); 129 130 /*! 131 @brief Read 関数で得られる GyroscopeStatus 構造体の angle を任意の値にリセットします。 132 @param[in] ax ピッチ方向の角度。角度は 1.0 を 360度とした値です。 133 @param[in] ay ヨー方向の角度。角度は 1.0 を 360度とした値です。 134 @param[in] az ロール方向の角度。角度は 1.0 を 360度とした値です。 135 @return なし。 136 */ 137 void SetAngle(f32 ax, f32 ay, f32 az); 138 139 /*! 140 @brief Read 関数で得られる GyroscopeStatus 構造体の direction を任意の値にリセットします。 141 @param[in] direction 設定する任意の3次元姿勢。 142 @return なし。 143 */ 144 void SetDirection(const Direction& direction); 145 146 /*! 147 @brief Read 関数で得られる GyroscopeStatus 構造体の direction を内部で計算する際に使用する角速度の値にかける倍率を設定します。 148 149 たとえば、magification を 2.0f に設定した場合、90度回転させると GyroscopeStatus 構造体の direction は180度回転した姿勢として計算されます。 150 151 @param[in] magnification 三次元姿勢を計算する際に使用する角速度にかける倍率。 152 @return なし。 153 */ 154 void SetDirectionMagnification(f32 magnification); 155 156 /*! 157 @brief 角速度を計算する際に掛ける倍率を各方向ごとに設定します。 158 @param[in] pitch pitch方向の角速度を計算する際に掛ける倍率。 159 @param[in] yaw yaw方向の角速度を計算する際に掛ける倍率。 160 @param[in] roll roll方向の角速度を計算する際に掛ける倍率。 161 @return なし。 162 */ 163 void SetAngleMagnification(f32 pitch, f32 yaw, f32 roll); 164 165 /* ------------------------------------------------------------------------ 166 各種補正機能をコントロールする関数 167 ------------------------------------------------------------------------ */ 168 /* ゼロ点遊びに関するコントロール関数 */ 169 170 /*! 171 @brief ゼロ点の遊びを有効にします。 172 @return なし。 173 */ 174 void EnableZeroPlay(); 175 176 /*! 177 @brief ゼロ点の遊びを無効にします。 178 @return なし。 179 */ 180 void DisableZeroPlay(); 181 182 /*! 183 @brief ゼロ点の遊びが有効になっているか調べます。 184 @return 有効な場合にtrue,無効な場合にfalseが帰ります。 185 */ 186 bool IsEnableZeroPlay() const; 187 188 /*! 189 @brief ゼロ点の遊びによる補正処理の働き具合を返します。 190 191 ゼロ点の遊びが無効の場合は0を返します。 192 193 @return 無効の場合は常に0が返ります。有効の場合は0以上の値が返ります。この値は補正処理の働き具合を示します。 194 195 現在の角速度が設定した遊びの値に近いほど0に近づき、遊びの範囲を越える速度になると0になります。 196 */ 197 f32 GetZeroPlayEffect() const; 198 199 200 /*! 201 @brief 静止時(ゼロ点)の遊びを設定します。 202 203 遊びを設けると小さな動きに反応しなくなります。 204 205 設定した遊びはすべての方向に対して適用されます。 206 207 @param[in] radius ゼロ点の遊び具合。1.0f を 360 dps とした値を設定します。 208 @return なし。 209 */ 210 void SetZeroPlayParam(f32 radius); 211 212 /*! 213 @brief ゼロ点の遊びを取得します。 214 215 遊びは 1.0f を 360 dps とした値になります。 216 217 @param[out] radius 現在のゼロ点の遊び具合をコピーするバッファ。 218 @return なし。 219 */ 220 void GetZeroPlayParam(f32& radius) const; 221 222 /*! 223 @brief ゼロ点の遊びを初期化します。 224 225 初期値は 0.005f となります。 226 227 @return なし。 228 */ 229 void ResetZeroPlayParam(); 230 231 232 /*ゼロ点ドリフト修正に関するコントロール関数*/ 233 234 /*! 235 @brief ゼロ点のドリフト修正を有効にします。 236 @return なし。 237 */ 238 void EnableZeroDrift(); 239 240 /*! 241 @brief ゼロ点のドリフト修正を無効にします。 242 @return なし。 243 */ 244 void DisableZeroDrift(); 245 246 /*! 247 @brief ゼロ点のドリフト修正が有効になっているか調べます。 248 249 ゼロ点のドリフト修正は初期状態では有効となっています。 250 251 @return 有効な場合にtrue,無効な場合にfalseを返します。 252 */ 253 bool IsEnableZeroDrift() const; 254 255 /*! 256 @brief ゼロ点のドリフト修正の効き具合を取得します。 257 258 この値は補正処理の働き具合を示し、1に近づくほどそのときの角速度で安定していることを意味します。 259 260 @return 無効の場合は負の値が返ります。有効の場合はゼロ以上の値が返ります。この値は補正処理の働き具合を示します。 261 262 1に近づくほどそのときの角速度で安定していることを意味します。 263 264 また、ゼロが返される期間は修正処理は行われません。 265 */ 266 f32 GetZeroDriftEffect() const; 267 268 /*! 269 @brief ゼロ点のドリフト修正モードを初期化します。 270 271 初期値は GYROSCOPE_ZERODRIFT_STANDARD に設定されます。 272 273 @return なし。 274 */ 275 void ResetZeroDriftMode(); 276 277 /*! 278 @brief ゼロ点のドリフト修正モードを設定します。 279 280 設定した内容はすべての方向に対して適用されます。 281 282 GYROSCOPE_ZERODRIFT_LOOSE の場合、センサーの値がある程度変動していても安定しているとみなし 283 ゼロ点の値を修正しようとしますので、等速度運動時にも修正される場合があります。 284 285 そのような場合はより条件が厳しいモードに設定することで改善される場合があります。 286 287 デフォルトは GYROSCOPE_ZERODRIFT_STANDARD に設定されています。 288 289 @param[in] mode ゼロ点のドリフト修正モード 290 @return なし。 291 */ 292 void SetZeroDriftMode(const ZeroDriftMode& mode); 293 294 /*! 295 @brief ゼロ点のドリフト修正モードを取得します。 296 @param[out] mode 現在のゼロ点のドリフト修正モードをコピーするバッファ。 297 @return なし。 298 */ 299 void GetZeroDriftMode(ZeroDriftMode& mode) const; 300 301 302 303 304 /*加速度による補正に関するコントロール関数*/ 305 306 /*! 307 @brief 加速度補正を有効にします。 308 309 加速度補正はCTRの静止時に加速度センサの値を用いてジャイロセンサの姿勢計算を補正する機能です。 310 311 加速度補正が有効であるとき、ジャイロセンサと補正に使用する加速度センサの軸回転に関する設定が共通である必要があります。 312 313 詳細は nn::hid::GyroscopeReader::EnableAxisRotation( ) を参照してください。 314 315 @return なし。 316 */ 317 void EnableAccRevise(); 318 319 /*! 320 @brief 加速度補正を無効にします。 321 @return なし。 322 */ 323 void DisableAccRevise(); 324 325 /*! 326 @brief 加速度補正が有効になっているか調べます。 327 328 加速度補正は初期状態では有効となっています。 329 330 @return 有効な場合にtrue,無効な場合にfalseを返します。 331 */ 332 bool IsEnableAccRevise() const; 333 334 /*! 335 @brief 加速度補正処理の働き具合が返されます。 336 @return 加速度補正処理が無効の場合は常に0を返します。有効の場合は0以上の値が返ります。 337 338 この値は補正処理の働き具合を示し、1に近いほどRead関数・ReadLatest関数で得られるGyroscopeStatus.directionの方向を加速度の方向に近づけるように補正がかかっています。 339 */ 340 f32 GetAccReviseEffect() const; 341 342 /*! 343 @brief 加速度補正具合を設定します。 344 345 設定した内容はすべての方向に対して適用されます。 346 347 @param[in] revisePower 加速度補正の重み。0 から 1 の間の値を設定してください。値が大きいほど急激に補正がかかります。 348 @param[in] reviseRange 加速度補正の有効範囲。重力加速度を中心にこの範囲内の加速度センサの値を補正計算に使用します。 349 350 1.0f は重力加速度の大きさを意味します。 351 352 つまり、0.4f を指定した場合は 0.6f から 1.4f の範囲に収まる加速度センサの値を補正計算に使用します。 353 @return なし。 354 */ 355 void SetAccReviseParam(f32 revisePower, f32 reviseRange); 356 357 /*! 358 @brief 加速度補正具合を取得します。 359 @param[out] revisePower 現在の加速度補正具合をコピーするバッファ。 360 @param[out] reviseRange 現在の加速度補正の有効半径をコピーするバッファ。 361 @return なし。 362 */ 363 void GetAccReviseParam(f32& revisePower, f32& reviseRange) const; 364 365 /*! 366 @brief 加速度補正具合を初期化します。 367 368 初期値は加速度補正処理の重み(revisePower)が 0.030f、加速度補正の有効半径(reviseRange)が 0.400f となります。 369 370 @return なし。 371 */ 372 void ResetAccReviseParam(); 373 374 375 /*! 376 @brief ジャイロセンサの軸回転を有効にします。 377 378 軸回転が有効なとき、nn::hid::CTR::GyroscopeReader::SetRotationAxis( ) で設定された回転行列使用し、サンプリングデータに回転変換処理を行った値が出力されるようになります。 379 380 この処理によって、CTR内にセンサが傾いて配置されているかのように扱うことができます。 381 382 軸回転を行い、かつ加速度補正も行う場合には、加速度センサの設定に注意する必要があります。<BR> 383 この場合には、参照しているAccelerometerReaderの軸回転とジャイロセンサの軸回転の設定が共通でなければいけません。<BR> 384 デフォルトのAccelerometerReaderを使用している場合には nn::hid::CTR::GyroscopeReader::EnableAxisRotation( ), nn::hid::CTR::GyroscopeReader::DisableAxisRotation( ), 385 nn::hid::CTR::GyroscopeReader::SetAxisRotationMatrix( ), nn::hid::CTR::GyroscopeReader::ResetAxisRotationMatrix( ) の各関数コール時にSDK側でデフォルトの 386 @ref nn::hid::CTR::AccelerometerReaderの対応する関数をコールして設定を共通化しますが、コンストラクタで独自の@ref nn::hid::CTR::AccelerometerReaderインスタンスを 387 指定した場合には、これらの設定をアプリ側で揃える必要があります。<BR> 388 軸回転の設定が共通でない場合、加速度補正が不適切に働く可能性がありますのでご注意ください。 389 390 初期値は無効になっています。 391 */ 392 void EnableAxisRotation(); 393 394 /*! 395 @brief ジャイロセンサの軸回転を無効にします。 396 397 初期値は無効になっています。 398 */ 399 void DisableAxisRotation(); 400 401 /*! 402 @brief ジャイロセンサの軸回転が有効か無効か調べます。 403 @return 軸回転が有効であればtrue,無効であればfalseを返します。 404 */ 405 bool IsEnableAxisRotation(); 406 407 /*! 408 @brief ジャイロセンサの軸回転で使用する回転行列を設定します。 409 */ 410 void SetAxisRotationMatrix(nn::math::MTX34 mtx); 411 412 /*! 413 @brief ジャイロセンサの軸回転で使用する回転行列を取得します。 414 415 @return 設定されている回転行列 416 */ 417 nn::math::MTX34 GetAxisRotationMatrix(); 418 419 /*! 420 @brief ジャイロセンサの軸回転で使用する回転行列を初期化します。 421 この時回転行列は nn::math::MTX34 の単位行列に設定され、これは軸回転が無効な場合と同等です。 422 */ 423 void ResetAxisRotationMatrix(); 424 425 private : 426 void GetZeroDriftParam(f32& radius, s32& count, f32& power) const; 427 void SetZeroDriftParam(f32 radius, s32 count, f32 power); 428 f32 ReviseDirection_Acceleration(Direction& rev_dir, const nn::math::VEC3& acc); 429 void CalculateGyroscopeAxisStatus( 430 f32 *destSpeed, 431 s32 *nearSamplingNum, 432 f32 *zeroOffset, 433 s32 srcSpeed, 434 f32 speedScale, 435 s32* oldValueArray); 436 void CalculateDirection(); 437 void InitializeCalibrationData(); 438 439 public : 440 /*! @brief ドリフト修正カウントの最大数 2のn乗 */ 441 static const u32 GYROSCOPE_DRIFT_COUNT_MAX = 256; 442 443 444 private : 445 static const s32 GYROSCOPE_BUFFER_SIZE = 8; 446 447 AccelerometerReader m_DefaultAccelerometerReader; 448 449 GyroscopeStatus m_CurrentStatus; 450 AccelerometerReader* m_pAccelerometerReader; 451 452 nn::math::VEC3 m_SpeedOld; 453 nn::math::VEC3 m_SpeedVector; 454 nn::math::VEC3 m_SpeedScale; 455 f32 m_DirectionMagnification; // 姿勢計算時の倍率 456 457 f32 m_Period; // 計算用係数 458 f32 m_FreqDegree; // 計算用係数 459 f32 m_FreqRadian; // 計算用係数 460 461 bool m_EnableZeroPlay; // ゼロ点に遊びを設けるか 462 bool m_EnableZeroDrift; // ゼロ点自動補正するか 463 bool m_EnableAccRevise; // 加速度で姿勢補正するか 464 bool m_EnableRotate; 465 466 f32 m_ZeroPlayRadius; // ゼロ点遊び半径 (1 = 360deg/sec) 467 f32 m_ZeroDriftRadius; // ドリフトカウント許容半径 (1 = 360deg/sec) 468 s32 m_ZeroDriftCount; // ドリフト修正カウント 469 f32 m_ZeroDriftPower; // ドリフト修正パワー 470 f32 m_AccRevisePower; // 加速度補正力 471 f32 m_AccReviseRange; // 加速度補正有効半径 472 473 f32 m_ZeroPlayEffect; // 遊び円の内側具合 0:外側 ~ 1:中心 474 f32 m_ZeroDriftEffect; // ドリフト修正カウントの続き具合 (0~1) 475 f32 m_AccRevEffect; // 加速度補正がどれくらいかかっているか 476 477 nn::math::VEC3 m_CalibrationZero; // キャリブレーション値 478 f64 m_CalibrationScale[3]; // キャリブレーション値 479 480 nn::math::VEC3 m_CountZero; // ゼロ点を示すカウント値 481 s32 m_CountIdx; // 最新が格納されているバッファインデクス 482 s32 m_CountT[3][GYROSCOPE_DRIFT_COUNT_MAX]; // XYZハードウェア値 483 f32 m_DpsPitchMagnification; // pitch方向の角速度計算時の倍率 484 f32 m_DpsYawMagnification; // yaw方向の角速度計算時の倍率 485 f32 m_DpsRollMagnification; // roll方向の角速度計算時の倍率 486 NN_PADDING4; 487 488 /*from Low*/ 489 Gyroscope& m_Gyroscope; 490 s32 m_IndexOfRead; 491 s64 m_TickOfRead; 492 493 /*rotate axis*/ 494 nn::math::MTX34 m_RotateMtx; 495 496 }; 497 498 } // namespace CTR { 499 } // namespace hid { 500 } // namespace nn { 501 502 #endif // #ifndef NN_HID_CTR_GYROSCOPEREADER_H_ 503