11#include " gz_noisy_odometry/NoisyOdometryPlugin.hpp"
2- #include < gz/sim/components/Pose.hpp >
3- #include < gz/plugin/Register.hpp >
2+ #include < gz/sim/components/Pose.hh >
3+ #include < gz/plugin/Register.hh >
44#include < tf2/LinearMath/Quaternion.h>
55
66GZ_ADD_PLUGIN (
@@ -23,7 +23,6 @@ namespace custom_plugins
2323 model_ = gz::sim::Model (_entity);
2424 if (!model_.Valid (_ecm)) return ;
2525
26- // Parámetros del SDF
2726 gaussian_noise_coeff_ = _sdf->Get <double >(" gaussian_noise" , 0.05 ).first ;
2827 ros_topic_ = _sdf->Get <std::string>(" ros_topic" , " /turtlebot3/odom_noisy" ).first ;
2928 gz_cmd_vel_topic_ = _sdf->Get <std::string>(" gz_cmd_vel_topic" , " /turtlebot3/cmd_vel" ).first ;
@@ -74,42 +73,35 @@ namespace custom_plugins
7473 w_cmd = current_w_;
7574 }
7675
77- // MATEMÁTICA HÍBRIDA: Integración Estocástica Proporcional
78- // El ruido es proporcional a la velocidad y escalado por sqrt(dt) para un Random Walk correcto
79- double linear_noise = gaussian_noise_coeff_ * gz::math::Rand::DblNormal (0 , 1 ) * std::sqrt (dt) * std::abs (v_cmd);
80- double angular_noise = gaussian_noise_coeff_ * gz::math::Rand::DblNormal (0 , 1 ) * std::sqrt (dt) * std::abs (w_cmd);
76+ double linear_noise = gaussian_noise_coeff_ * gz::math::Rand::DblNormal (0 , 1 ) * std::abs (v_cmd);
77+ double angular_noise = gaussian_noise_coeff_ * gz::math::Rand::DblNormal (0 , 1 ) * std::abs (w_cmd);
8178
82- double v_noisy = v_cmd + ( linear_noise / dt) ;
83- double w_noisy = w_cmd + ( angular_noise / dt) ;
79+ double v_noisy = v_cmd + linear_noise;
80+ double w_noisy = w_cmd + angular_noise;
8481
85- // Actualización de orientación (Yaw)
86- double yaw_prev = noisy_pose_internal_.Rot ().Yaw ();
87- double yaw_new = yaw_prev + (w_noisy * dt);
88-
89- // Actualización de posición (Cinemática Diferencial)
90- double distance = v_noisy * dt;
91- noisy_pose_internal_.Pos ().X () += distance * std::cos (yaw_prev + (w_noisy * dt / 2.0 ));
92- noisy_pose_internal_.Pos ().Y () += distance * std::sin (yaw_prev + (w_noisy * dt / 2.0 ));
93-
94- gz::math::Quaterniond q_new;
95- q_new.SetFromEuler (0 , 0 , yaw_new);
96- noisy_pose_internal_.Rot () = q_new;
82+ double angle = w_noisy * dt;
83+ gz::math::Vector3d axis (0 , 0 , 1 );
84+ gz::math::Quaterniond deltaOrientation (std::cos (angle / 2.0 ), 0 , 0 , std::sin (angle / 2.0 ));
85+
86+ noisy_pose_internal_.Rot () = noisy_pose_internal_.Rot () * deltaOrientation;
87+ noisy_pose_internal_.Rot ().Normalize ();
88+
89+ gz::math::Vector3d deltaPos (v_noisy * dt, 0 , 0 );
90+ noisy_pose_internal_.Pos () += noisy_pose_internal_.Rot ().RotateVector (deltaPos);
9791
98- // Publicación en ROS 2
9992 nav_msgs::msg::Odometry odom_msg;
10093 odom_msg.header .stamp = ros_node_->now ();
10194 odom_msg.header .frame_id = frame_id_;
10295 odom_msg.child_frame_id = child_frame_id_;
10396
10497 odom_msg.pose .pose .position .x = noisy_pose_internal_.Pos ().X ();
10598 odom_msg.pose .pose .position .y = noisy_pose_internal_.Pos ().Y ();
106-
107- tf2::Quaternion q;
108- q.setRPY (0 , 0 , yaw_new);
109- odom_msg.pose .pose .orientation .x = q.x ();
110- odom_msg.pose .pose .orientation .y = q.y ();
111- odom_msg.pose .pose .orientation .z = q.z ();
112- odom_msg.pose .pose .orientation .w = q.w ();
99+ odom_msg.pose .pose .position .z = noisy_pose_internal_.Pos ().Z ();
100+
101+ odom_msg.pose .pose .orientation .x = noisy_pose_internal_.Rot ().X ();
102+ odom_msg.pose .pose .orientation .y = noisy_pose_internal_.Rot ().Y ();
103+ odom_msg.pose .pose .orientation .z = noisy_pose_internal_.Rot ().Z ();
104+ odom_msg.pose .pose .orientation .w = noisy_pose_internal_.Rot ().W ();
113105
114106 odom_msg.twist .twist .linear .x = v_noisy;
115107 odom_msg.twist .twist .angular .z = w_noisy;
0 commit comments