【C++】ベクトルの回転の実装

私がよく使う3次元ベクトルの回転の実装をご紹介します。

Eigen

行列バージョン

Eigen::Vector3d Rotation(const Eigen::Vector3d& V, const Eigen::Vector3d& RPY)
{
	Eigen::Matrix3d Rot;
	Rot <<	cos(RPY(1))*cos(RPY(2)),	sin(RPY(0))*sin(RPY(1))*cos(RPY(2)) - cos(RPY(0))*sin(RPY(2)),	cos(RPY(0))*sin(RPY(1))*cos(RPY(2)) + sin(RPY(0))*sin(RPY(2)),
		cos(RPY(1))*sin(RPY(2)),	sin(RPY(0))*sin(RPY(1))*sin(RPY(2)) + cos(RPY(0))*cos(RPY(2)),	cos(RPY(0))*sin(RPY(1))*sin(RPY(2)) - sin(RPY(0))*cos(RPY(2)),
		-sin(RPY(1)),	sin(RPY(0))*cos(RPY(1)),	cos(RPY(0))*cos(RPY(1));
	return Rot*V;
}

行列バージョン(逆回転)

Eigen::Vector3d RotationInv(const Eigen::Vector3d& V, const Eigen::Vector3d& RPY)
{
	 Eigen::Matrix3d RotInv;
	RotInv <<	cos(RPY(1))*cos(RPY(2)),	cos(RPY(1))*sin(RPY(2)),	-sin(RPY(1)),
			sin(RPY(0))*sin(RPY(1))*cos(RPY(2)) - cos(RPY(0))*sin(RPY(2)),	sin(RPY(0))*sin(RPY(1))*sin(RPY(2)) + cos(RPY(0))*cos(RPY(2)),	sin(RPY(0))*cos(RPY(1)),
			cos(RPY(0))*sin(RPY(1))*cos(RPY(2)) + sin(RPY(0))*sin(RPY(2)),	cos(RPY(0))*sin(RPY(1))*sin(RPY(2)) - sin(RPY(0))*cos(RPY(2)),	cos(RPY(0))*cos(RPY(1));
	return RotInv*V;
}

クォータニオンバージョン

Eigen::Vector3d Rotation(const Eigen::Vector3d& V, const Eigen::Quaterniond& q)
{
	Eigen::Quaterniond q_xyz(0.0, V(0), V(1), V(2));
	Eigen::Quaterniond q_xyz_trans = q*q_xyz*q.inverse();
	Eigen::Vector3d Vtrans(q_xyz_trans.x(), q_xyz_trans.y(), q_xyz_trans.z());
	return Vtrans;
}

クォータニオンバージョン(逆回転)

Eigen::Vector3d RotationInv(const Eigen::Vector3d& V, const Eigen::Quaterniond& q)
{
	Eigen::Quaterniond q_xyz(0.0, V(0), V(1), V(2));
	Eigen::Quaterniond q_xyz_trans = q.inverse()*q_xyz*q;
	Eigen::Vector3d Vtrans(q_xyz_trans.x(), q_xyz_trans.y(), q_xyz_trans.z());
	return Vtrans;
}

ROS(tf::Quaternion)

ROSユーザー向けの実装です。
あまりメジャーではないと思いますが、私が個人的に好きな実装なので載せておきます笑。

Eigen::Vector3d Rotation(const Eigen::Vector3d& V, const Eigen::Vector3d& RPY)
{
	tf::Quaternion q_rot = tf::createQuaternionFromRPY(RPY(0), RPY(1), RPY(2));
	tf::Quaternion q_xyz(V(0), V(1), V(2), 0.0);
	tf::Quaternion q_xyz_trans = q_rot*q_xyz*q_rot.inverse();
	Eigen::Vector3d Vtrans(q_xyz_trans.x(), q_xyz_trans.y(), q_xyz_trans.z());
	return Vtrans;
}
Eigen::Vector3d RotationInv(const Eigen::Vector3d& V, const Eigen::Vector3d& RPY)
{
	tf::Quaternion q_rot = tf::createQuaternionFromRPY(RPY(0), RPY(1), RPY(2));
	tf::Quaternion q_xyz(V(0), V(1), V(2), 0.0);
	tf::Quaternion q_xyz_trans = q_rot.inverse()*q_xyz*q_rot;
	Eigen::Vector3d Vtrans(q_xyz_trans.x(), q_xyz_trans.y(), q_xyz_trans.z());
	return Vtrans;
}

さいごに

3次元ベクトルの回転の実装を何パターンかご紹介しました。

参考になれば幸いです。


以上です。

Ad.