Skip to content

cartesian controller can work in base_frame#10

Merged
danielsanjosepro merged 3 commits into
learnsyslab:mainfrom
AlexD15216:base_frame
Oct 18, 2025
Merged

cartesian controller can work in base_frame#10
danielsanjosepro merged 3 commits into
learnsyslab:mainfrom
AlexD15216:base_frame

Conversation

@AlexD15216

Copy link
Copy Markdown
Contributor

This fixes a frame inconsistency in cartesian controller where target_pose are supposed to expressed in the base_frame (defined in config), but the end_effector_pose were retrieved (via Pinocchio) and used for error computing only in the world frame defined in the URDF.
This is related to Issue #9.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Fix frame inconsistency so the Cartesian controller computes errors and Jacobians in the configured base_frame instead of the URDF world frame.

  • Compute end-effector pose in base frame and use it for error calculation
  • Map Jacobians into base frame (from LOCAL or WORLD) via adjoint transforms
  • Initialize and use base_frame_id; initialize target pose in base frame on activate

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/cartesian_controller.cpp Transforms end-effector pose and Jacobian into base_frame; updates error computation to base frame; initializes target pose in base frame on activation
include/crisp_controllers/cartesian_controller.hpp Adds end_effector_pose_b and base_frame_id members to support base_frame computations

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +119 to +131
if (params_.use_local_jacobian) {
Eigen::MatrixXd J_local(6, model_.nv);
pinocchio::computeFrameJacobian(model_, data_, q_pin, end_effector_frame_id,
pinocchio::ReferenceFrame::LOCAL, J_local);
const Eigen::Matrix<double,6,6> Ad_be = end_effector_pose_b.toActionMatrix();
J.noalias() = Ad_be * J_local;
} else {
Eigen::MatrixXd J_world(6, model_.nv);
pinocchio::computeFrameJacobian(model_, data_, q_pin, end_effector_frame_id,
pinocchio::ReferenceFrame::WORLD, J_world);
const Eigen::Matrix<double,6,6> Ad_bw = base_frame_pose.inverse().toActionMatrix();
J.noalias() = Ad_bw * J_world;
}

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J_local and J_world are dynamically allocated on every update cycle, which introduces unnecessary heap allocations in the control loop. Consider preallocating scratch matrices as members (resized in on_configure/on_activate) and reusing them, or reuse J as a temporary buffer (dropping noalias if aliasing occurs) to avoid per-iteration allocations.

Copilot uses AI. Check for mistakes.
Comment thread src/cartesian_controller.cpp Outdated
Comment on lines +101 to +104

end_effector_pose_b = base_frame_pose.inverse() * end_effector_pose;
// target_pose_b = base_frame_pose.inverse() * target_pose_;
// pinocchio::SE3 new_target_pose_b = base_frame_pose.inverse() * new_target_pose;

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base_frame_pose.inverse() is computed twice in the same update; compute it once and reuse to avoid duplicate SE3 inversions. For example: const auto T_bw = base_frame_pose.inverse(); end_effector_pose_b = T_bw * end_effector_pose; and const auto Ad_bw = T_bw.toActionMatrix();

Suggested change
end_effector_pose_b = base_frame_pose.inverse() * end_effector_pose;
// target_pose_b = base_frame_pose.inverse() * target_pose_;
// pinocchio::SE3 new_target_pose_b = base_frame_pose.inverse() * new_target_pose;
const pinocchio::SE3 T_bw = base_frame_pose.inverse();
end_effector_pose_b = T_bw * end_effector_pose;
// target_pose_b = T_bw * target_pose_;
// pinocchio::SE3 new_target_pose_b = T_bw * new_target_pose;

Copilot uses AI. Check for mistakes.
Eigen::MatrixXd J_world(6, model_.nv);
pinocchio::computeFrameJacobian(model_, data_, q_pin, end_effector_frame_id,
pinocchio::ReferenceFrame::WORLD, J_world);
const Eigen::Matrix<double,6,6> Ad_bw = base_frame_pose.inverse().toActionMatrix();

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base_frame_pose.inverse() is computed twice in the same update; compute it once and reuse to avoid duplicate SE3 inversions. For example: const auto T_bw = base_frame_pose.inverse(); end_effector_pose_b = T_bw * end_effector_pose; and const auto Ad_bw = T_bw.toActionMatrix();

Suggested change
const Eigen::Matrix<double,6,6> Ad_bw = base_frame_pose.inverse().toActionMatrix();
const auto T_bw = base_frame_pose.inverse();
const Eigen::Matrix<double,6,6> Ad_bw = T_bw.toActionMatrix();

Copilot uses AI. Check for mistakes.
Comment thread src/cartesian_controller.cpp Outdated
Comment on lines +103 to +104
// target_pose_b = base_frame_pose.inverse() * target_pose_;
// pinocchio::SE3 new_target_pose_b = base_frame_pose.inverse() * new_target_pose;

Copilot AI Oct 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Remove commented-out code to keep the control loop clear. If needed for future reference, capture this in a design note or a dedicated helper function.

Copilot uses AI. Check for mistakes.
Comment thread include/crisp_controllers/cartesian_controller.hpp
@danielsanjosepro

Copy link
Copy Markdown
Collaborator

Thanks for the PR! I already tested the updated controller and it seems to work fine. I will take a look at the code but otherwise it looks fine! :)

danielsanjosepro and others added 2 commits October 18, 2025 08:34
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

@danielsanjosepro danielsanjosepro left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexD15216 I removed a few old comments and added a short description for the new attributes but all in all it is good. Thanks for contributing!

@danielsanjosepro danielsanjosepro merged commit da805ab into learnsyslab:main Oct 18, 2025
4 checks passed
danielsanjosepro added a commit that referenced this pull request Oct 21, 2025
…se_frame indicated in the parameters and not just world frame (#10)"

This reverts commit da805ab.
yizhongzhang1989 pushed a commit to yizhongzhang1989/crisp_controllers that referenced this pull request Mar 17, 2026
… indicated in the parameters and not just world frame (learnsyslab#10)

* now the cartesian controller can handle the desired pose in base_frame instead of world frame defined in urdf

* Include description of new attributes

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Removing a few old comments

---------

Co-authored-by: yibo <yibo.di@iis.fraunhofer.de>
Co-authored-by: Daniel San José Pro <42489409+danielsanjosepro@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants