/*---------------------------------------------------------------------------* Project: horizon File: hid_GyroscopeReader.h Copyright 2010 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: $ *---------------------------------------------------------------------------*/ /*! @file @brief GyroscopeReaderクラスを定義します */ #ifndef NN_HID_CTR_GYROSCOPEREADER_H_ #define NN_HID_CTR_GYROSCOPEREADER_H_ #include #include #include #include #include #include #include #include #include #include namespace nn { namespace hid { namespace CTR { /*! @brief ゼロ点のドリフト修正の強度を設定する列挙体です */ enum ZeroDriftMode { GYROSCOPE_ZERODRIFT_LOOSE, //!< センサの値がある程度変動していても、安定しているとみなして修正が行われるモードです。 GYROSCOPE_ZERODRIFT_STANDARD,//!< GYROSCOPE_ZERODRIFT_LOOSE と GYROSCOPE_ZERODRIFT_TIGHT の中間にあたるモードです。 GYROSCOPE_ZERODRIFT_TIGHT,//!< センサの値が定められた閾値以内の変動でないと、安定しているとみなさない厳密な修正が行われるモードです。 GYROSCOPE_ZERODRIFT_NUM }; /*! @brief ジャイロセンサのサンプリングデータを読み込むクラスです。 注意) ジャイロセンサのサンプリングは平均 10 msec 周期で行われます。 ジャイロセンサのサンプリングは、本クラスのインスタンスを生成した段階から行われるため、 サンプリングデータを読み込めるのは、インスタンス生成後 10 msec 経過した後になります。 また、内部にAccelerometerReaderのインスタンスを保持しているため、ジャイロセンサを使用する際には加速度センサも自動的に起動状態となります。 nn::hid::GyroscopeReader::EnableAxisRotation( ) を使用することで、加工した出力値を得ることができます。 加工によって、センサが傾いて配置されているような出力値を得ることができます。 詳細は関数のリファレンスを参照してください。 ジャイロセンサの軸は以下のようになっています。
X+:十字ボタンの左方向
Y+:タッチパネルの実装面方向
Z+:十字ボタンの上方向
*/ class GyroscopeReader: private nn::util::NonCopyable { public: /*! @brief コンストラクタです。 インスタンスを生成する前に @ref nn::hid::CTR::Initialize( ) で初期化してください。 @param[in] pAccelerometrReader AccelerometerReaderへの参照を指定すると、参照するAccelerometerReaderの出力値を利用した補正を行います。 デフォルトではNULLが渡され、この場合内部に保持するデフォルトのAccelerometerReaderによって補正を行います。 */ GyroscopeReader(AccelerometerReader* pAccelerometerReader = NULL, Gyroscope& gyroscope = GetGyroscope()); /*! @brief デストラクタです。 */ ~GyroscopeReader(); /*! @brief ジャイロセンサのサンプリングデータを新しいものから順に読み込みます。以前に読み込んだデータは読み込まれません。 @param[out] pBufs 新しいものから順にサンプリングデータが読み込まれます。 @param[out] pReadLen 読み込んだサンプリングデータの数です。 @param[in] bufLen pBufs に読み込めるサンプリングデータの数を指定します。 @return なし。 */ void Read(GyroscopeStatus* pBufs, s32* pReadLen, s32 bufLen); /*! @brief 最新のジャイロセンサのサンプリングデータを読み込みます。 nn::hid::CTR::GyroscopeReader::Read( ) とちがい同じサンプリングデータを読み込むことが出来ます。 @param[out] pBuf サンプリングデータが読み込まれます。 @return サンプリングデータの読み込み結果を返します。
true ・・・ 読み込めました。
false ・・・ 読み込めませんでした。(GyroscopeReaderのインスタンス生成後あるいはスリープ復帰後の最初のサンプリングが行われ次第、読み込めます。) */ bool ReadLatest(GyroscopeStatus* pBuf); /*! @brief 内部状態を初期化します。 このとき、各種補正処理の設定も以下のようになります。 ゼロ点の遊び 無効になります。
加速度の補正 有効になります。
ゼロ点のドリフト補正 GYROSCOPE_ZERODRIFT_STANDARD に設定されます。
角速度の倍率 1.0 に設定されます。 @return なし。 */ void Reset(); /*! @brief Read 関数で得られる GyroscopeStatus 構造体の angle を任意の値にリセットします。 @param[in] ax ピッチ方向の角度。角度は 1.0 を 360度とした値です。 @param[in] ay ヨー方向の角度。角度は 1.0 を 360度とした値です。 @param[in] az ロール方向の角度。角度は 1.0 を 360度とした値です。 @return なし。 */ void SetAngle(f32 ax, f32 ay, f32 az); /*! @brief Read 関数で得られる GyroscopeStatus 構造体の direction を任意の値にリセットします。 @param[in] direction 設定する任意の3次元姿勢。 @return なし。 */ void SetDirection(const Direction& direction); /*! @brief Read 関数で得られる GyroscopeStatus 構造体の direction を内部で計算する際に使用する角速度の値にかける倍率を設定します。 たとえば、magification を 2.0f に設定した場合、90度回転させると GyroscopeStatus 構造体の direction は180度回転した姿勢として計算されます。 @param[in] magnification 三次元姿勢を計算する際に使用する角速度にかける倍率。 @return なし。 */ void SetDirectionMagnification(f32 magnification); /*! @brief 角速度を計算する際に掛ける倍率を各方向ごとに設定します。 @param[in] pitch pitch方向の角速度を計算する際に掛ける倍率。 @param[in] yaw yaw方向の角速度を計算する際に掛ける倍率。 @param[in] roll roll方向の角速度を計算する際に掛ける倍率。 @return なし。 */ void SetAngleMagnification(f32 pitch, f32 yaw, f32 roll); /* ------------------------------------------------------------------------ 各種補正機能をコントロールする関数 ------------------------------------------------------------------------ */ /* ゼロ点遊びに関するコントロール関数 */ /*! @brief ゼロ点の遊びを有効にします。 @return なし。 */ void EnableZeroPlay(); /*! @brief ゼロ点の遊びを無効にします。 @return なし。 */ void DisableZeroPlay(); /*! @brief ゼロ点の遊びが有効になっているか調べます。 @return 有効な場合にtrue,無効な場合にfalseが帰ります。 */ bool IsEnableZeroPlay() const; /*! @brief ゼロ点の遊びによる補正処理の働き具合を返します。 ゼロ点の遊びが無効の場合は0を返します。 @return 無効の場合は常に0が返ります。有効の場合は0以上の値が返ります。この値は補正処理の働き具合を示します。 現在の角速度が設定した遊びの値に近いほど0に近づき、遊びの範囲を越える速度になると0になります。 */ f32 GetZeroPlayEffect() const; /*! @brief 静止時(ゼロ点)の遊びを設定します。 遊びを設けると小さな動きに反応しなくなります。 設定した遊びはすべての方向に対して適用されます。 @param[in] radius ゼロ点の遊び具合。1.0f を 360 dps とした値を設定します。 @return なし。 */ void SetZeroPlayParam(f32 radius); /*! @brief ゼロ点の遊びを取得します。 遊びは 1.0f を 360 dps とした値になります。 @param[out] radius 現在のゼロ点の遊び具合をコピーするバッファ。 @return なし。 */ void GetZeroPlayParam(f32& radius) const; /*! @brief ゼロ点の遊びを初期化します。 初期値は 0.005f となります。 @return なし。 */ void ResetZeroPlayParam(); /*ゼロ点ドリフト修正に関するコントロール関数*/ /*! @brief ゼロ点のドリフト修正を有効にします。 @return なし。 */ void EnableZeroDrift(); /*! @brief ゼロ点のドリフト修正を無効にします。 @return なし。 */ void DisableZeroDrift(); /*! @brief ゼロ点のドリフト修正が有効になっているか調べます。 ゼロ点のドリフト修正は初期状態では有効となっています。 @return 有効な場合にtrue,無効な場合にfalseを返します。 */ bool IsEnableZeroDrift() const; /*! @brief ゼロ点のドリフト修正の効き具合を取得します。 この値は補正処理の働き具合を示し、1に近づくほどそのときの角速度で安定していることを意味します。 @return 無効の場合は負の値が返ります。有効の場合はゼロ以上の値が返ります。この値は補正処理の働き具合を示します。 1に近づくほどそのときの角速度で安定していることを意味します。 また、ゼロが返される期間は修正処理は行われません。 */ f32 GetZeroDriftEffect() const; /*! @brief ゼロ点のドリフト修正モードを初期化します。 初期値は GYROSCOPE_ZERODRIFT_STANDARD に設定されます。 @return なし。 */ void ResetZeroDriftMode(); /*! @brief ゼロ点のドリフト修正モードを設定します。 設定した内容はすべての方向に対して適用されます。 GYROSCOPE_ZERODRIFT_LOOSE の場合、センサーの値がある程度変動していても安定しているとみなし ゼロ点の値を修正しようとしますので、等速度運動時にも修正される場合があります。 そのような場合はより条件が厳しいモードに設定することで改善される場合があります。 デフォルトは GYROSCOPE_ZERODRIFT_STANDARD に設定されています。 @param[in] mode ゼロ点のドリフト修正モード @return なし。 */ void SetZeroDriftMode(const ZeroDriftMode& mode); /*! @brief ゼロ点のドリフト修正モードを取得します。 @param[out] mode 現在のゼロ点のドリフト修正モードをコピーするバッファ。 @return なし。 */ void GetZeroDriftMode(ZeroDriftMode& mode) const; /*加速度による補正に関するコントロール関数*/ /*! @brief 加速度補正を有効にします。 加速度補正はCTRの静止時に加速度センサの値を用いてジャイロセンサの姿勢計算を補正する機能です。 加速度補正が有効であるとき、ジャイロセンサと補正に使用する加速度センサの軸回転に関する設定が共通である必要があります。 詳細は nn::hid::GyroscopeReader::EnableAxisRotation( ) を参照してください。 @return なし。 */ void EnableAccRevise(); /*! @brief 加速度補正を無効にします。 @return なし。 */ void DisableAccRevise(); /*! @brief 加速度補正が有効になっているか調べます。 加速度補正は初期状態では有効となっています。 @return 有効な場合にtrue,無効な場合にfalseを返します。 */ bool IsEnableAccRevise() const; /*! @brief 加速度補正処理の働き具合が返されます。 @return 加速度補正処理が無効の場合は常に0を返します。有効の場合は0以上の値が返ります。 この値は補正処理の働き具合を示し、1に近いほどRead関数・ReadLatest関数で得られるGyroscopeStatus.directionの方向を加速度の方向に近づけるように補正がかかっています。 */ f32 GetAccReviseEffect() const; /*! @brief 加速度補正具合を設定します。 設定した内容はすべての方向に対して適用されます。 @param[in] revisePower 加速度補正の重み。0 から 1 の間の値を設定してください。値が大きいほど急激に補正がかかります。 @param[in] reviseRange 加速度補正の有効範囲。重力加速度を中心にこの範囲内の加速度センサの値を補正計算に使用します。 1.0f は重力加速度の大きさを意味します。 つまり、0.4f を指定した場合は 0.6f から 1.4f の範囲に収まる加速度センサの値を補正計算に使用します。 @return なし。 */ void SetAccReviseParam(f32 revisePower, f32 reviseRange); /*! @brief 加速度補正具合を取得します。 @param[out] revisePower 現在の加速度補正具合をコピーするバッファ。 @param[out] reviseRange 現在の加速度補正の有効半径をコピーするバッファ。 @return なし。 */ void GetAccReviseParam(f32& revisePower, f32& reviseRange) const; /*! @brief 加速度補正具合を初期化します。 初期値は加速度補正処理の重み(revisePower)が 0.030f、加速度補正の有効半径(reviseRange)が 0.400f となります。 @return なし。 */ void ResetAccReviseParam(); /*! @brief ジャイロセンサの軸回転を有効にします。 軸回転が有効なとき、nn::hid::CTR::GyroscopeReader::SetRotationAxis( ) で設定された回転行列使用し、サンプリングデータに回転変換処理を行った値が出力されるようになります。 この処理によって、CTR内にセンサが傾いて配置されているかのように扱うことができます。 軸回転を行い、かつ加速度補正も行う場合には、加速度センサの設定に注意する必要があります。
この場合には、参照しているAccelerometerReaderの軸回転とジャイロセンサの軸回転の設定が共通でなければいけません。
デフォルトのAccelerometerReaderを使用している場合には nn::hid::CTR::GyroscopeReader::EnableAxisRotation( ), nn::hid::CTR::GyroscopeReader::DisableAxisRotation( ), nn::hid::CTR::GyroscopeReader::SetAxisRotationMatrix( ), nn::hid::CTR::GyroscopeReader::ResetAxisRotationMatrix( ) の各関数コール時にSDK側でデフォルトの @ref nn::hid::CTR::AccelerometerReaderの対応する関数をコールして設定を共通化しますが、コンストラクタで独自の@ref nn::hid::CTR::AccelerometerReaderインスタンスを 指定した場合には、これらの設定をアプリ側で揃える必要があります。
軸回転の設定が共通でない場合、加速度補正が不適切に働く可能性がありますのでご注意ください。 初期値は無効になっています。 */ void EnableAxisRotation(); /*! @brief ジャイロセンサの軸回転を無効にします。 初期値は無効になっています。 */ void DisableAxisRotation(); /*! @brief ジャイロセンサの軸回転が有効か無効か調べます。 @return 軸回転が有効であればtrue,無効であればfalseを返します。 */ bool IsEnableAxisRotation(); /*! @brief ジャイロセンサの軸回転で使用する回転行列を設定します。 */ void SetAxisRotationMatrix(nn::math::MTX34 mtx); /*! @brief ジャイロセンサの軸回転で使用する回転行列を取得します。 @return 設定されている回転行列 */ nn::math::MTX34 GetAxisRotationMatrix(); /*! @brief ジャイロセンサの軸回転で使用する回転行列を初期化します。 この時回転行列は nn::math::MTX34 の単位行列に設定され、これは軸回転が無効な場合と同等です。 */ void ResetAxisRotationMatrix(); private : void GetZeroDriftParam(f32& radius, s32& count, f32& power) const; void SetZeroDriftParam(f32 radius, s32 count, f32 power); f32 ReviseDirection_Acceleration(Direction& rev_dir, const nn::math::VEC3& acc); void CalculateGyroscopeAxisStatus( f32 *destSpeed, s32 *nearSamplingNum, f32 *zeroOffset, s32 srcSpeed, f32 speedScale, s32* oldValueArray); void CalculateDirection(); void InitializeCalibrationData(); public : /*! @brief ドリフト修正カウントの最大数 2のn乗 */ static const u32 GYROSCOPE_DRIFT_COUNT_MAX = 256; private : static const s32 GYROSCOPE_BUFFER_SIZE = 8; AccelerometerReader m_DefaultAccelerometerReader; GyroscopeStatus m_CurrentStatus; AccelerometerReader* m_pAccelerometerReader; nn::math::VEC3 m_SpeedOld; nn::math::VEC3 m_SpeedVector; nn::math::VEC3 m_SpeedScale; f32 m_DirectionMagnification; // 姿勢計算時の倍率 f32 m_Period; // 計算用係数 f32 m_FreqDegree; // 計算用係数 f32 m_FreqRadian; // 計算用係数 bool m_EnableZeroPlay; // ゼロ点に遊びを設けるか bool m_EnableZeroDrift; // ゼロ点自動補正するか bool m_EnableAccRevise; // 加速度で姿勢補正するか bool m_EnableRotate; f32 m_ZeroPlayRadius; // ゼロ点遊び半径 (1 = 360deg/sec) f32 m_ZeroDriftRadius; // ドリフトカウント許容半径 (1 = 360deg/sec) s32 m_ZeroDriftCount; // ドリフト修正カウント f32 m_ZeroDriftPower; // ドリフト修正パワー f32 m_AccRevisePower; // 加速度補正力 f32 m_AccReviseRange; // 加速度補正有効半径 f32 m_ZeroPlayEffect; // 遊び円の内側具合 0:外側 ~ 1:中心 f32 m_ZeroDriftEffect; // ドリフト修正カウントの続き具合 (0~1) f32 m_AccRevEffect; // 加速度補正がどれくらいかかっているか nn::math::VEC3 m_CalibrationZero; // キャリブレーション値 f64 m_CalibrationScale[3]; // キャリブレーション値 nn::math::VEC3 m_CountZero; // ゼロ点を示すカウント値 s32 m_CountIdx; // 最新が格納されているバッファインデクス s32 m_CountT[3][GYROSCOPE_DRIFT_COUNT_MAX]; // XYZハードウェア値 f32 m_DpsPitchMagnification; // pitch方向の角速度計算時の倍率 f32 m_DpsYawMagnification; // yaw方向の角速度計算時の倍率 f32 m_DpsRollMagnification; // roll方向の角速度計算時の倍率 NN_PADDING4; /*from Low*/ Gyroscope& m_Gyroscope; s32 m_IndexOfRead; s64 m_TickOfRead; /*rotate axis*/ nn::math::MTX34 m_RotateMtx; }; } // namespace CTR { } // namespace hid { } // namespace nn { #endif // #ifndef NN_HID_CTR_GYROSCOPEREADER_H_