/*---------------------------------------------------------------------------* 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 ジャイロセンサのサンプリングデータを読み込むクラスです。 */ class GyroscopeReader: private nn::util::NonCopyable { public: /*! @name コンストラクタ/デストラクタ @{ */ /*! @brief コンストラクタです。 インスタンスを生成する前に @ref nn::hid::CTR::Initialize( ) で初期化してください。
サンプリングを開始するために必要な設定を行います。
最初のインスタンスを生成してからサンプリングが開始されるまでにウェイト時間が必要な点にご注意ください。 @param[in] pAccelerometrReader AccelerometerReaderへの参照を指定すると、参照するAccelerometerReaderの出力値を利用した補正を行います。 デフォルトではNULLが渡され、この場合内部に保持するデフォルトのAccelerometerReaderによって補正を行います。 */ GyroscopeReader(AccelerometerReader* pAccelerometerReader = NULL, Gyroscope& gyroscope = GetGyroscope()); /*! @brief デストラクタです。 */ ~GyroscopeReader(); /*! @} */ /*! @name サンプリングデータの読み込み @{ */ /*! @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); /*! @} */ /*! @name リセット @{ */ /*! @brief 内部状態を初期化します。 このとき、各種補正処理の設定も以下のようになります。 加速度の補正 有効になります。
ゼロ点のドリフト補正 GYROSCOPE_ZERODRIFT_STANDARD に設定され、有効になります。
ゼロ点の遊び 無効になります。
軸回転 回転行列に単位行列が設定され、さらに無効になります。
角速度の倍率 すべて1.0 に設定されます
@return なし。 */ void Reset(); /*! @} */ /*! @name 出力値の設定 @{ */ /*! @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 角速度を計算する際に掛ける倍率を各方向ごとに設定します。 @param[in] pitch pitch方向の角速度を計算する際に掛ける倍率。 @param[in] yaw yaw方向の角速度を計算する際に掛ける倍率。 @param[in] roll roll方向の角速度を計算する際に掛ける倍率。 @return なし。 */ void SetAngleMagnification(f32 pitch, f32 yaw, f32 roll); /*! @brief Read 関数で得られる GyroscopeStatus 構造体の direction を内部で計算する際に使用する角速度の値にかける倍率を設定します。 たとえば、magification を 2.0f に設定した場合、90度回転させると GyroscopeStatus 構造体の direction は180度回転した姿勢として計算されます。 @param[in] magnification 三次元姿勢を計算する際に使用する角速度にかける倍率。 @return なし。 */ void SetDirectionMagnification(f32 magnification); /*! @} */ /*! @name ゼロ点の遊び @{ */ /*! @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(); /*! @} */ /*! @name ゼロ点ドリフトの補正 @{ */ /*! @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; /*! @} */ /*! @name 加速度補正 @{ */ /*! @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(); /*! @} */ /*! @name 軸回転 @{ */ /*! @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 ReadLocal(GyroscopeStatus* pBufs, s32* pReadLen, s32 bufLen); 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(); private : /* ドリフト修正カウントの最大数*/ static const u32 GYROSCOPE_DRIFT_COUNT_MAX = 256; //2のn乗であること private : static const s32 GYROSCOPE_LOCAL_BUFFER_SIZE = 32; s32 m_GyroscopeLocalBufferSize; GyroscopeStatus m_GyroscopeStatusLocalBuffer[GYROSCOPE_LOCAL_BUFFER_SIZE]; bool m_IsFirstRead; ZeroDriftMode m_ZeroDriftMode; NN_PADDING2; 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_