cmvr-es/include/utils/controller/cartesian_controller.h

119 lines
4.9 KiB
C
Raw Normal View History

2025-08-21 13:56:39 +08:00
//
// Created by xtkuang on 2025/7/21.
//
#ifndef CMVR_ES_CARTESIAN_CONTROLLER_H
#define CMVR_ES_CARTESIAN_CONTROLLER_H
#pragma once
#include <Eigen/Core>
#include <Eigen/Dense>
#include <vector>
#include <string>
#include <memory>
#include <cmath>
#include <fcl/fcl.h>
#include <optional>
#include <unordered_map>
#include "utils/math/se3.h"
#include "utils/math/qp_solver.h"
#include "utils/dynamics/robot.h"
namespace cmvr::ctrl{
using cmvr::math::SE3;
// -----------------------------------------------------------------------------
// Task & collision descriptions
// -----------------------------------------------------------------------------
struct PoseTarget {
std::string link_name; //!< link to be controlled
Eigen::Matrix4d T_target; //!< desired pose w.r.t *base_link*
double w_posrot = 0.5; // [0→pure pos, 1→pure rot]
double weight = 1.0; // task weight (01 soft, 1 hard)
};
struct CollisionPair { std::string link_A, link_B; };
// -----------------------------------------------------------------------------
// CartesianController declaration (implementation in .cpp)
// -----------------------------------------------------------------------------
template<int DOF>
class CartesianController {
public:
using RobotT = cmvr::dyn::Robot<DOF>;
using VecD = Eigen::Vector<double, DOF>;
using Mat6D = Eigen::Matrix<double, 6, DOF>;
enum class Mode { Position, Velocity, Torque };
CartesianController(std::shared_ptr<RobotT> robot, double dsafe = 0.05, double lambda = 1e-2);
/* ------------------------- configuration ----------------------------- */
void setCollisionPairs(const std::vector<CollisionPair>& pairs);
// Joint limits (size = DOF). Any value = std::nullopt → no limit.
void setPositionLimits(const std::vector<std::optional<double>>& q_min, const std::vector<std::optional<double>>& q_max);
void setVelocityLimits(const std::vector<std::optional<double>>& qd_max);
void setAccelerationLimits(const std::vector<std::optional<double>>& qdd_max);
/* --------------------------- main API -------------------------------- */
/**
* Compute joint command given Cartesian objectives.
* @param state current (mutable) robot state
* @param base reference frame (string)
* @param targets list of PoseTarget
* @param dt controller step [s]
* @param mode desired output type
* @param out_cmd filled with q / / τ
* @return true if IK converged (position) or soft OK (others)
*/
bool compute(
std::shared_ptr<cmvr::dyn::State<DOF>>& state,
const std::string& base_link,
const std::vector<PoseTarget>& targets,
double dt,
Mode mode,
VecD& out_cmd,
int max_iters = 60,
double tol = 1e-3,
double alpha_h = 10.0);
private:
/* -------- internal helpers (implemented in .cpp) --------------------- */
bool solveIK(std::shared_ptr<cmvr::dyn::State<DOF>>& state, const std::string& base, const std::vector<PoseTarget>& targets,
const VecD& q_init, VecD& q_out, int max_iters, double tol, double alpha_h) const;
bool distanceConstraint(const CollisionPair& cp, std::shared_ptr<cmvr::dyn::State<DOF>>& state,
const std::vector<std::shared_ptr<fcl::CollisionObjectd>>& objs,
double& h_out, Eigen::RowVectorXd& J_out) const;
inline void clampVec(VecD& v, const std::vector<std::optional<double>>& lo, const std::vector<std::optional<double>>& hi) const;
/* -------------------------- data ------------------------------------ */
std::shared_ptr<RobotT> robot_;
std::vector<CollisionPair> pairs_;
double d_safe_ = 0.05;
double lambda_ = 1e-2;
mutable math::QPSolver solver_;
// joint limits (optional)
std::vector<std::optional<double>> q_min_ = std::vector<std::optional<double>>(DOF);
std::vector<std::optional<double>> q_max_ = std::vector<std::optional<double>>(DOF);
std::vector<std::optional<double>> qd_max_ = std::vector<std::optional<double>>(DOF);
std::vector<std::optional<double>> qdd_max_= std::vector<std::optional<double>>(DOF);
// FCL reusable buffers
mutable fcl::DistanceRequestd dist_req_{};
mutable fcl::DistanceResultd dist_res_{};
};
}
// ------------------------------ explicit instantiation -----------------------
extern template class cmvr::ctrl::CartesianController<7>;
extern template class cmvr::ctrl::CartesianController<14>;
extern template class cmvr::ctrl::CartesianController<20>;
#endif //CMVR_ES_CARTESIAN_CONTROLLER_H