|
@@ -24,10 +24,22 @@
|
|
|
#include <cstddef>
|
|
|
#include <functional>
|
|
|
|
|
|
+#include <time.h>
|
|
|
+#include <sstream>
|
|
|
+
|
|
|
+#include <iostream>
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
TestPose::TestPose() : Node("testpose_core")
|
|
|
{
|
|
|
using std::placeholders::_1;
|
|
|
|
|
|
+ simulated_frame_id_ = declare_parameter("simulated_frame_id", "base_link");
|
|
|
+ origin_frame_id_ = declare_parameter("origin_frame_id", "odom");
|
|
|
+
|
|
|
static constexpr std::size_t queue_size = 1;
|
|
|
rclcpp::QoS durable_qos(queue_size);
|
|
|
durable_qos.transient_local();
|
|
@@ -36,6 +48,13 @@ TestPose::TestPose() : Node("testpose_core")
|
|
|
// Note: this callback publishes topics above
|
|
|
pose_sub_ = create_subscription<geometry_msgs::msg::PoseStamped>(
|
|
|
"pose", queue_size, std::bind(&TestPose::callbackPose, this, _1));
|
|
|
+
|
|
|
+pub_odom_ = create_publisher<Odometry>("/localization/kinematic_state", durable_qos);
|
|
|
+pub_tf_ = create_publisher<tf2_msgs::msg::TFMessage>("/tf", durable_qos);
|
|
|
+
|
|
|
+ mptimer= create_wall_timer(100ms,std::bind(&TestPose::callbackTimer, this));
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
double calcDiffForRadian(const double lhs_rad, const double rhs_rad)
|
|
@@ -103,6 +122,59 @@ geometry_msgs::msg::TwistStamped calcTwist(
|
|
|
return twist;
|
|
|
}
|
|
|
|
|
|
+struct Quaternion {
|
|
|
+ double w, x, y, z;
|
|
|
+};
|
|
|
+
|
|
|
+struct EulerAngles {
|
|
|
+ double roll, pitch, yaw;
|
|
|
+};
|
|
|
+
|
|
|
+EulerAngles ToEulerAngles(Quaternion q) {
|
|
|
+ EulerAngles angles;
|
|
|
+
|
|
|
+ // roll (x-axis rotation)
|
|
|
+ double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
|
|
|
+ double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
|
|
|
+ angles.roll = std::atan2(sinr_cosp, cosr_cosp);
|
|
|
+
|
|
|
+ // pitch (y-axis rotation)
|
|
|
+ double sinp = 2 * (q.w * q.y - q.z * q.x);
|
|
|
+ if (std::abs(sinp) >= 1)
|
|
|
+ angles.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
|
|
|
+ else
|
|
|
+ angles.pitch = std::asin(sinp);
|
|
|
+
|
|
|
+ // yaw (z-axis rotation)
|
|
|
+ double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
|
|
|
+ double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
|
|
|
+ angles.yaw = std::atan2(siny_cosp, cosy_cosp);
|
|
|
+
|
|
|
+ return angles;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
|
|
|
+{
|
|
|
+ // Abbreviations for the various angular functions
|
|
|
+ double cy = cos(yaw * 0.5);
|
|
|
+ double sy = sin(yaw * 0.5);
|
|
|
+ double cp = cos(pitch * 0.5);
|
|
|
+ double sp = sin(pitch * 0.5);
|
|
|
+ double cr = cos(roll * 0.5);
|
|
|
+ double sr = sin(roll * 0.5);
|
|
|
+
|
|
|
+ Quaternion q;
|
|
|
+ q.w = cy * cp * cr + sy * sp * sr;
|
|
|
+ q.x = cy * cp * sr - sy * sp * cr;
|
|
|
+ q.y = sy * cp * sr + cy * sp * cr;
|
|
|
+ q.z = sy * cp * cr - cy * sp * sr;
|
|
|
+
|
|
|
+ return q;
|
|
|
+}
|
|
|
+
|
|
|
+//原文链接:https://blog.csdn.net/xiaoma_bk/article/details/79082629
|
|
|
+
|
|
|
void TestPose::callbackPose(geometry_msgs::msg::PoseStamped::SharedPtr pose_msg_ptr)
|
|
|
{
|
|
|
// TODO(YamatoAndo) check time stamp diff
|
|
@@ -111,3 +183,73 @@ void TestPose::callbackPose(geometry_msgs::msg::PoseStamped::SharedPtr pose_msg_
|
|
|
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+void TestPose::callbackTimer()
|
|
|
+{
|
|
|
+ std::cout<<" testpose. "<<std::endl;
|
|
|
+
|
|
|
+ double pitch,roll,yaw;
|
|
|
+ pitch = 0;
|
|
|
+ roll = 0;
|
|
|
+
|
|
|
+ yaw = 0;
|
|
|
+ Quaternion quat = ToQuaternion(yaw,pitch,roll);
|
|
|
+
|
|
|
+ nav_msgs::msg::Odometry msg;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ static double rel_x = 3705;
|
|
|
+ static double rel_y = 73765;
|
|
|
+ static double rel_z = 0;
|
|
|
+ static double vn = 0;
|
|
|
+ static double ve = 0;
|
|
|
+
|
|
|
+ msg.pose.pose.position.x = rel_x;
|
|
|
+ msg.pose.pose.position.y = rel_y;
|
|
|
+ msg.pose.pose.position.z = rel_z;
|
|
|
+
|
|
|
+ msg.pose.pose.orientation.x = quat.x;
|
|
|
+ msg.pose.pose.orientation.y = quat.y;
|
|
|
+ msg.pose.pose.orientation.z = quat.z;
|
|
|
+ msg.pose.pose.orientation.w = quat.w;
|
|
|
+
|
|
|
+ msg.twist.twist.linear.x = sqrt(pow(vn,2)+pow(ve,2));
|
|
|
+
|
|
|
+ publish_odometry(msg);
|
|
|
+ publish_tf(msg);
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void TestPose::publish_odometry(const Odometry & odometry)
|
|
|
+{
|
|
|
+ static int frame_id = 0;
|
|
|
+ frame_id++;
|
|
|
+ Odometry msg = odometry;
|
|
|
+ msg.header.frame_id = origin_frame_id_;
|
|
|
+ msg.header.stamp = get_clock()->now();
|
|
|
+ msg.child_frame_id = simulated_frame_id_;
|
|
|
+ pub_odom_->publish(msg);
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void TestPose::publish_tf(const Odometry & odometry)
|
|
|
+{
|
|
|
+ static int frame_id = 0;
|
|
|
+ frame_id++;
|
|
|
+ TransformStamped tf;
|
|
|
+ tf.header.stamp = get_clock()->now();
|
|
|
+ tf.header.frame_id = origin_frame_id_;
|
|
|
+ tf.child_frame_id = simulated_frame_id_;
|
|
|
+ tf.transform.translation.x = odometry.pose.pose.position.x;
|
|
|
+ tf.transform.translation.y = odometry.pose.pose.position.y;
|
|
|
+ tf.transform.translation.z = odometry.pose.pose.position.z;
|
|
|
+ tf.transform.rotation = odometry.pose.pose.orientation;
|
|
|
+
|
|
|
+ tf2_msgs::msg::TFMessage tf_msg{};
|
|
|
+ tf_msg.transforms.emplace_back(std::move(tf));
|
|
|
+ pub_tf_->publish(tf_msg);
|
|
|
+}
|
|
|
+
|