feat:add ibvs joint pos limit

This commit is contained in:
lgv 2026-02-27 16:37:25 +08:00
parent 539e07e5c7
commit 8c79471c6c
4 changed files with 77 additions and 0 deletions

View File

@ -229,6 +229,11 @@ private:
*/ */
bool computeInternal(const std::vector<double>& joints_angle, bool computeInternal(const std::vector<double>& joints_angle,
std::vector<double>& qdot_out); std::vector<double>& qdot_out);
/**
* @brief URDF
* @param q
*/
void clampJointCommandInPlace(std::vector<double>& q) const;
/** /**
* @brief 姿 tag * @brief 姿 tag
*/ */
@ -300,6 +305,12 @@ private:
// 速度 IK 求解器。 // 速度 IK 求解器。
std::unique_ptr<PinocchioDlsIKSolver> dls_solver_{nullptr}; std::unique_ptr<PinocchioDlsIKSolver> dls_solver_{nullptr};
// 是否成功读取到 URDF 关节限位。
bool has_joint_position_limits_{false};
// 本链关节位置下限rad
std::vector<double> q_lower_limits_;
// 本链关节位置上限rad
std::vector<double> q_upper_limits_;
// 最近一次用于控制的 tag id。 // 最近一次用于控制的 tag id。
int last_used_tag_id_{-1}; int last_used_tag_id_{-1};

View File

@ -82,6 +82,14 @@ bool IbvsController::init(const std::shared_ptr<device::AbstractCamera>& camera,
urdf_path, base_link, flange_link, camera_frame_name_, 100, 1e-6, 1e-6, mu_); urdf_path, base_link, flange_link, camera_frame_name_, 100, 1e-6, 1e-6, mu_);
initialized_ = dls_solver_->init(); initialized_ = dls_solver_->init();
if (initialized_) {
has_joint_position_limits_ =
dls_solver_->getJointPositionLimits(q_lower_limits_, q_upper_limits_);
} else {
has_joint_position_limits_ = false;
q_lower_limits_.clear();
q_upper_limits_.clear();
}
last_compute_status_ = initialized_ ? ComputeStatus::OK : ComputeStatus::NOT_READY; last_compute_status_ = initialized_ ? ComputeStatus::OK : ComputeStatus::NOT_READY;
return initialized_; return initialized_;
} }
@ -91,6 +99,7 @@ void IbvsController::reset(const std::vector<double>& q_init) {
q_cmd_.clear(); q_cmd_.clear();
} else { } else {
q_cmd_ = q_init; q_cmd_ = q_init;
clampJointCommandInPlace(q_cmd_);
} }
last_tag_detected_ = false; last_tag_detected_ = false;
last_used_tag_id_ = -1; last_used_tag_id_ = -1;
@ -316,6 +325,7 @@ bool IbvsController::compute(const std::vector<double>& joints_angle,
} }
if (q_cmd_.size() != joints_angle.size()) { if (q_cmd_.size() != joints_angle.size()) {
q_cmd_ = joints_angle; q_cmd_ = joints_angle;
clampJointCommandInPlace(q_cmd_);
} }
std::vector<double> qdot; std::vector<double> qdot;
@ -328,6 +338,7 @@ bool IbvsController::compute(const std::vector<double>& joints_angle,
// q_{k+1} = q_k + qdot * dt // q_{k+1} = q_k + qdot * dt
q_cmd_[i] += qdot[i] * dt; q_cmd_[i] += qdot[i] * dt;
} }
clampJointCommandInPlace(q_cmd_);
q_cmd_out = q_cmd_; q_cmd_out = q_cmd_;
return true; return true;
@ -338,6 +349,19 @@ bool IbvsController::compute(const std::vector<double>& joints_angle,
return computeInternal(joints_angle, qdot_out); return computeInternal(joints_angle, qdot_out);
} }
void IbvsController::clampJointCommandInPlace(std::vector<double>& q) const {
if (!has_joint_position_limits_) return;
if (q.size() != q_lower_limits_.size() || q.size() != q_upper_limits_.size()) return;
for (size_t i = 0; i < q.size(); ++i) {
const double lo = q_lower_limits_[i];
const double hi = q_upper_limits_[i];
if (!std::isfinite(lo) && !std::isfinite(hi)) continue;
if (lo > hi) continue;
q[i] = SupportFunctions::clamp(q[i], lo, hi);
}
}
void IbvsController::setLambda(double lambda) { void IbvsController::setLambda(double lambda) {
lambda_ = lambda; lambda_ = lambda;
initTask(); initTask();

View File

@ -78,6 +78,15 @@ public:
double damping = -1.0, double damping = -1.0,
double qdot_abs_max = std::numeric_limits<double>::infinity()); double qdot_abs_max = std::numeric_limits<double>::infinity());
/**
* @brief URDF
* @param lower size=chain_dof_
* @param upper size=chain_dof_
* @return `true`
*/
bool getJointPositionLimits(std::vector<double>& lower,
std::vector<double>& upper) const;
void setMaxIters(int iters) { max_iters_ = iters; } void setMaxIters(int iters) { max_iters_ = iters; }
void setDamping(double d) { damping_ = d; } void setDamping(double d) { damping_ = d; }
void setEps(double pos_eps, double rot_eps) { pos_eps_ = pos_eps; rot_eps_ = rot_eps; } void setEps(double pos_eps, double rot_eps) { pos_eps_ = pos_eps; rot_eps_ = rot_eps; }

View File

@ -161,6 +161,25 @@ bool PinocchioDlsIKSolver::init() {
<< "': q_start=" << chain_q_start_ << " q_dof=" << chain_dof_ << "': q_start=" << chain_q_start_ << " q_dof=" << chain_dof_
<< ", v_start=" << chain_v_start_ << " v_dof=" << chain_v_dof_ << ", v_start=" << chain_v_start_ << " v_dof=" << chain_v_dof_
<< ", nq=" << model_.nq << " nv=" << model_.nv << "\n"; << ", nq=" << model_.nq << " nv=" << model_.nv << "\n";
std::cout << "[PinocchioDlsIKSolver] Chain joint position limits (rad):\n";
for (const auto j : chain_joints) {
const int q_idx = model_.idx_qs[j];
const int nq = model_.nqs[j];
const std::string& jname = model_.names[j];
if (nq <= 0) continue;
for (int k = 0; k < nq; ++k) {
const int qi = q_idx - chain_q_start_ + k;
if (qi < 0 || qi >= chain_dof_) continue;
if (nq == 1) {
std::cout << " - " << jname
<< ": [" << q_lower_chain_[qi] << ", " << q_upper_chain_[qi] << "]\n";
} else {
std::cout << " - " << jname << "[" << k << "]"
<< ": [" << q_lower_chain_[qi] << ", " << q_upper_chain_[qi] << "]\n";
}
}
}
std::cout << "[PinocchioDlsIKSolver] base pose cached (constant)\n"; std::cout << "[PinocchioDlsIKSolver] base pose cached (constant)\n";
return true; return true;
} }
@ -361,6 +380,20 @@ bool PinocchioDlsIKSolver::velocityIk(const std::vector<double>& cur_angle,
return true; return true;
} }
bool PinocchioDlsIKSolver::getJointPositionLimits(std::vector<double>& lower,
std::vector<double>& upper) const {
if (!initialized_ || chain_dof_ <= 0) {
return false;
}
if (q_lower_chain_.size() != chain_dof_ || q_upper_chain_.size() != chain_dof_) {
return false;
}
lower.assign(q_lower_chain_.data(), q_lower_chain_.data() + q_lower_chain_.size());
upper.assign(q_upper_chain_.data(), q_upper_chain_.data() + q_upper_chain_.size());
return true;
}
#include <Eigen/SVD> #include <Eigen/SVD>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>