@@ -129,16 +129,9 @@ CartesianAdmittanceController::update(const rclcpp::Time & time, const rclcpp::D
129129 // Position error: desired - inner
130130 Eigen::Vector3d adm_pos_error = desired_SE3.translation () - inner_SE3_.translation ();
131131
132- // Orientation error: quaternion-based with antipodal check
133- Eigen::Quaterniond q_inner (inner_SE3_.rotation ());
134- Eigen::Quaterniond q_desired (desired_SE3.rotation ());
135- if (q_desired.coeffs ().dot (q_inner.coeffs ()) < 0.0 ) {
136- q_inner.coeffs () = -q_inner.coeffs ();
137- }
138- Eigen::Quaterniond q_error (q_inner.inverse () * q_desired);
139- Eigen::Vector3d adm_rot_error;
140- adm_rot_error << q_error.x (), q_error.y (), q_error.z ();
141- adm_rot_error = inner_SE3_.rotation () * adm_rot_error; // Rotate to world frame
132+ // Orientation error: SO(3) logarithmic map (world frame)
133+ Eigen::Vector3d adm_rot_error =
134+ pinocchio::log3 (desired_SE3.rotation () * inner_SE3_.rotation ().transpose ());
142135
143136 Eigen::Vector<double , 6 > adm_error;
144137 adm_error << adm_pos_error, adm_rot_error;
@@ -159,7 +152,6 @@ CartesianAdmittanceController::update(const rclcpp::Time & time, const rclcpp::D
159152
160153 // 10. Semi-implicit Euler integration
161154 double dt = period.seconds ();
162- if (dt <= 0.0 ) dt = 0.001 ; // safety
163155 inner_motion_ += accel * dt;
164156 // Update inner_SE3_ using exponential map
165157 pinocchio::SE3 delta = pinocchio::exp6 (pinocchio::Motion (inner_motion_ * dt));
@@ -382,9 +374,20 @@ CartesianAdmittanceController::on_configure(const rclcpp_lifecycle::State & /*pr
382374 " ft_sensor.frame is not set, using end_effector_frame for F/T wrench transformation. "
383375 " Set ft_sensor.frame to the actual sensor measurement frame for correct results." );
384376 } else {
377+ if (!model_.existFrame (params_.ft_sensor .frame )) {
378+ RCLCPP_ERROR (
379+ get_node ()->get_logger (),
380+ " F/T sensor frame '%s' does not exist in the robot model. Please check the "
381+ " ft_sensor.frame parameter and the URDF frames." ,
382+ params_.ft_sensor .frame .c_str ());
383+ return CallbackReturn::ERROR ;
384+ }
385385 ft_sensor_frame_id = model_.getFrameId (params_.ft_sensor .frame );
386- RCLCPP_INFO (get_node ()->get_logger (),
387- " Using F/T sensor frame: %s (id=%d)" , params_.ft_sensor .frame .c_str (), ft_sensor_frame_id);
386+ RCLCPP_INFO (
387+ get_node ()->get_logger (),
388+ " Using F/T sensor frame: %s (id=%d)" ,
389+ params_.ft_sensor .frame .c_str (),
390+ ft_sensor_frame_id);
388391 }
389392 q = Eigen::VectorXd::Zero (model_.nv );
390393 q_pin = Eigen::VectorXd::Zero (model_.nq );
@@ -635,7 +638,7 @@ void CartesianAdmittanceController::setStiffnessAndDamping() {
635638 nullspace_stiffness.diagonal () << params_.nullspace .stiffness * weights;
636639 nullspace_damping.diagonal () << 2.0 * nullspace_stiffness.diagonal ().cwiseSqrt ();
637640
638- if (params_.nullspace .damping ) {
641+ if (params_.nullspace .damping >= 0.0 ) {
639642 nullspace_damping.diagonal () = params_.nullspace .damping * weights;
640643 } else {
641644 nullspace_damping.diagonal () = 2.0 * nullspace_stiffness.diagonal ().cwiseSqrt ();
0 commit comments