@@ -62,41 +62,11 @@ CartesianController::state_interface_configuration() const {
6262
6363controller_interface::return_type
6464CartesianController::update (const rclcpp::Time & time, const rclcpp::Duration & /* period*/ ) {
65- size_t num_joints = params_.joints .size ();
66- for (size_t i = 0 ; i < num_joints; i++) {
67- // TODO(placeholder): later it might be better to get this thing prepared in the
68- // configuration part (not in the control loop)
69- auto joint_name = params_.joints [i];
70- auto joint_id = model_.getJointId (joint_name); // pinocchio joind id might be different
71- auto joint = model_.joints [joint_id];
72-
73- q_ref[i] = exponential_moving_average (q_ref[i], q_target[i], params_.filter .q_ref );
74-
75- // Filtering joint position measurement 1 uses previous q, 0 uses new q from measurement.
76- // q[i] = exponential_moving_average(q[i], state_interfaces_[i].get_value(), params_.filter.q);
77- #if ROS2_VERSION_ABOVE_HUMBLE
78- q[i] = exponential_moving_average (
79- q[i], state_interfaces_[i].get_optional ().value_or (q[i]), params_.filter .q );
80- #else
81- q[i] = exponential_moving_average (q[i], state_interfaces_[i].get_value (), params_.filter .q );
82- #endif
83-
84- if (continous_joint_types.count (joint.shortname ())) { // Then we are handling a continous
85- // joint that is SO(2)
86- q_pin[joint.idx_q ()] = std::cos (q[i]);
87- q_pin[joint.idx_q () + 1 ] = std::sin (q[i]);
88- } else { // simple revolute joint case
89- q_pin[joint.idx_q ()] = q[i];
90- }
91- #if ROS2_VERSION_ABOVE_HUMBLE
92- dq[i] = exponential_moving_average (
93- dq[i], state_interfaces_[num_joints + i].get_optional ().value_or (dq[i]), params_.filter .dq );
94- #else
95- dq[i] = exponential_moving_average (
96- dq[i], state_interfaces_[num_joints + i].get_value (), params_.filter .dq );
97- #endif
98- }
65+
66+ // Update current state information with EMA filtered values
67+ updateCurrentState ();
9968
69+ // Check if new targets available
10070 if (new_target_pose_) {
10171 parse_target_pose_ ();
10272 new_target_pose_ = false ;
@@ -147,15 +117,13 @@ CartesianController::update(const rclcpp::Time & time, const rclcpp::Duration &
147117 : pinocchio::ReferenceFrame::LOCAL_WORLD_ALIGNED ;
148118 pinocchio::computeFrameJacobian (model_, data_, q_pin, end_effector_frame_id, reference_frame, J);
149119
150- Eigen::MatrixXd J_pinv (model_.nv , 6 );
151120 J_pinv = pseudo_inverse (J, params_.nullspace .regularization );
152- Eigen::MatrixXd Id_nv = Eigen::MatrixXd::Identity (model_.nv , model_.nv );
153121 if (params_.nullspace .projector_type == " dynamic" || params_.use_operational_space ) {
154122 pinocchio::computeMinverse (model_, data_, q_pin);
155123 data_.Minv .triangularView <Eigen::StrictlyLower>() =
156124 data_.Minv .transpose ().triangularView <Eigen::StrictlyLower>();
157125 Mx_inv = J * data_.Minv * J.transpose ();
158- Mx = pseudo_inverse (Mx_inv);
126+ Mx = pseudo_inverse (Mx_inv, params_. operational_space_regularization );
159127 }
160128
161129 if (params_.nullspace .projector_type == " dynamic" ) {
@@ -221,7 +189,7 @@ CartesianController::update(const rclcpp::Time & time, const rclcpp::Duration &
221189 tau_d = exponential_moving_average (tau_d, tau_previous, params_.filter .output_torque );
222190
223191 if (!params_.stop_commands ) {
224- for (size_t i = 0 ; i < num_joints ; ++i) {
192+ for (size_t i = 0 ; i < params_. joints . size () ; ++i) {
225193#if ROS2_VERSION_ABOVE_HUMBLE
226194 (void )command_interfaces_[i].set_value (tau_d[i]);
227195#else
@@ -323,7 +291,8 @@ CartesianController::on_configure(const rclcpp_lifecycle::State & /*previous_sta
323291 return CallbackReturn::ERROR ;
324292 }
325293 }
326-
294+
295+ // Preallocate the matrices and vectors that will be used in the control loop
327296 end_effector_frame_id = model_.getFrameId (params_.end_effector_frame );
328297 q = Eigen::VectorXd::Zero (model_.nv );
329298 q_pin = Eigen::VectorXd::Zero (model_.nq );
@@ -333,6 +302,8 @@ CartesianController::on_configure(const rclcpp_lifecycle::State & /*previous_sta
333302 dq_ref = Eigen::VectorXd::Zero (model_.nv );
334303 tau_previous = Eigen::VectorXd::Zero (model_.nv );
335304 J = Eigen::MatrixXd::Zero (6 , model_.nv );
305+ J_pinv = Eigen::MatrixXd::Zero (model_.nv , 6 );
306+ Id_nv = Eigen::MatrixXd::Identity (model_.nv , model_.nv );
336307
337308 // Map the friction parameters to Eigen vectors
338309 fp1 = Eigen::Map<Eigen::VectorXd>(params_.friction .fp1 .data (), model_.nv );
@@ -491,41 +462,51 @@ void CartesianController::setStiffnessAndDamping() {
491462 }
492463}
493464
494- CallbackReturn
495- CartesianController::on_activate (const rclcpp_lifecycle::State & /* previous_state*/ ) {
465+ void CartesianController::updateCurrentState (bool initialize) {
496466 auto num_joints = params_.joints .size ();
497467 for (size_t i = 0 ; i < num_joints; i++) {
498- // TODO(placeholder): later it might be better to get this thing prepared in the
499- // configuration part (not in the control loop)
500468 auto joint_name = params_.joints [i];
501469 auto joint_id = model_.getJointId (joint_name); // pinocchio joind id might be different
502470 auto joint = model_.joints [joint_id];
503471
504472#if ROS2_VERSION_ABOVE_HUMBLE
505- q[i] = state_interfaces_[i].get_optional ().value_or (q[i]);
473+ double q_meas = state_interfaces_[i].get_optional ().value_or (q[i]);
474+ double dq_meas = state_interfaces_[num_joints + i].get_optional ().value_or (dq[i]);
506475#else
507- q[i] = state_interfaces_[i].get_value ();
476+ double q_meas = state_interfaces_[i].get_value ();
477+ double dq_meas = state_interfaces_[num_joints + i].get_value ();
508478#endif
509- if (joint.shortname () == " JointModelRZ" ) { // simple revolute joint case
510- q_pin[joint.idx_q ()] = q[i];
511- } else if (continous_joint_types.count (
512- joint.shortname ())) { // Then we are handling a continous
513- // joint that is SO(2)
479+
480+ q_ref[i] = initialize
481+ ? q_meas
482+ : exponential_moving_average (q_ref[i], q_target[i], params_.filter .q_ref );
483+
484+ q[i] = initialize
485+ ? q_meas
486+ : exponential_moving_average (q[i], q_meas, params_.filter .q );
487+
488+ if (continous_joint_types.count (joint.shortname ())) { // Then we are handling a continous
489+ // joint that is SO(2)
514490 q_pin[joint.idx_q ()] = std::cos (q[i]);
515491 q_pin[joint.idx_q () + 1 ] = std::sin (q[i]);
492+ } else { // simple revolute joint case
493+ q_pin[joint.idx_q ()] = q[i];
516494 }
517495
518- q_ref[i] = q[i];
519- q_target[i] = q[i];
496+ dq[i] = initialize
497+ ? dq_meas
498+ : exponential_moving_average (dq[i], dq_meas, params_.filter .dq );
520499
521- #if ROS2_VERSION_ABOVE_HUMBLE
522- dq[i] = state_interfaces_[num_joints + i].get_optional ().value_or (dq[i]);
523- dq_ref[i] = dq[i];
524- #else
525- dq[i] = state_interfaces_[num_joints + i].get_value ();
526- dq_ref[i] = state_interfaces_[num_joints + i].get_value ();
527- #endif
500+ q_target[i] = initialize ? q_meas : q_target[i];
528501 }
502+ }
503+
504+ CallbackReturn
505+ CartesianController::on_activate (const rclcpp_lifecycle::State & /* previous_state*/ ) {
506+
507+ // Update the current state with initial measurements (no EMA filtering)
508+ // to avoid large initial errors
509+ updateCurrentState (true );
529510
530511 pinocchio::forwardKinematics (model_, data_, q_pin, dq);
531512 pinocchio::updateFramePlacements (model_, data_);
0 commit comments