robot_env_evaluator 1.0.1
Loading...
Searching...
No Matches
robot_env_evaluator.cpp
Go to the documentation of this file.
1
21
22#include <pinocchio/algorithm/frames.hpp>
23#include <pinocchio/algorithm/jacobian.hpp>
24#include <pinocchio/collision/collision.hpp>
25
26namespace robot_env_evaluator
27{
28 RobotEnvEvaluator::RobotEnvEvaluator(const pinocchio::Model& model,
29 const std::string& ee_name,
30 const std::vector<std::string>& joint_names,
31 const pinocchio::GeometryModel& collision_model,
32 const pinocchio::GeometryModel& visual_model)
33 : model_(model), data_(model), collision_model_(collision_model), visual_model_(visual_model)
34 {
35 // Constructor implementation
36 if (model_.existFrame(ee_name)){
37 ee_index_ = model_.getFrameId(ee_name);
38 }
39 else{
40 throw std::invalid_argument("The targeted end-effector frame [" + ee_name + "] does not exist in the model.");
41 }
42
43 // Check if the joint names are valid
44 joint_indices_.clear();
45 for (const auto& joint_name : joint_names)
46 {
47 if(model.existFrame(joint_name)){
48 joint_indices_.push_back(model.getFrameId(joint_name));
49 }
50 else{
51 throw std::invalid_argument("The joint name [" + joint_name + "] does not exist in the model.");
52 }
53 }
54 }
55
56 void RobotEnvEvaluator::forwardKinematics(const Eigen::VectorXd& q,
57 Eigen::Matrix4d& T,
58 const int joint_index /* = -1 */)
59 {
61 if (joint_index == -1) {
62 T = data_.oMf[ee_index_].toHomogeneousMatrix();
63 } else if (joint_index == 0) {
64 T = data_.oMf[0].toHomogeneousMatrix();
65 } else {
66 if (joint_index < 0 || joint_index > joint_indices_.size()) {
67 throw std::out_of_range("joint_index [" + std::to_string(joint_index) + "] is out of range [0, " + std::to_string(joint_indices_.size()) + "]");
68 }
69 T = data_.oMf[joint_indices_[joint_index - 1]].toHomogeneousMatrix();
70 }
71 }
72
74 Eigen::Matrix4d& T,
75 const std::string& frame_name)
76 {
78 if (model_.existFrame(frame_name)) {
79 int frame_index = model_.getFrameId(frame_name);
80 T = data_.oMf[frame_index].toHomogeneousMatrix();
81 } else {
82 throw std::invalid_argument("forwardKinematicsByFrameName: The frame name [" + frame_name + "] does not exist in the model.");
83 }
84 }
85
86 void RobotEnvEvaluator::jacobian(const Eigen::VectorXd& q,
87 Eigen::MatrixXd& J,
88 const int joint_index /* = -1 */)
89 {
90 if (joint_index == -1) {
92 } else if (joint_index == 0) {
93 jacobianFrame(q, 0, J);
94 } else {
95 if (joint_index < 0 || joint_index > joint_indices_.size()) {
96 throw std::out_of_range("joint_index" + std::to_string(joint_index) + " is out of range [0, " + std::to_string(joint_indices_.size()) + "]");
97 }
98 jacobianFrame(q, joint_indices_[joint_index - 1], J);
99 }
100 }
101
102 void RobotEnvEvaluator::jacobianByFrameName(const Eigen::VectorXd& q,
103 Eigen::MatrixXd& J,
104 const std::string& frame_name)
105 {
107 if (model_.existFrame(frame_name)) {
108 int frame_index = model_.getFrameId(frame_name);
109 jacobianFrame(q, frame_index, J);
110 } else {
111 throw std::invalid_argument("The frame name [" + frame_name + "] does not exist in the model.");
112 }
113 }
114
115 void RobotEnvEvaluator::jacobianFrame(const Eigen::VectorXd& q,
116 const double frame_index,
117 Eigen::MatrixXd& J)
118 {
120 J = pinocchio::getFrameJacobian(model_, data_, frame_index, pinocchio::LOCAL_WORLD_ALIGNED);
121 }
122
123 void RobotEnvEvaluator::computeDistances(const Eigen::VectorXd& q,
124 const std::vector<obstacleInput>& obstacles,
125 std::vector<distanceResult>& distances)
126 {
128 distances.clear();
129
130 // 1. create a GeometryModel from the collision model. Disable all collision pairs if necessary.
131 pinocchio::GeometryModel geom_model(collision_model_);
132 int robot_geom_num = geom_model.ngeoms;
133 if(calculate_self_collision_ == false){
134 geom_model.removeAllCollisionPairs();
135 }
136
137 // 2. add the obstacles and add collision pairs for obstacles
138 int i_obstacle = 0;
139 for (const auto& obstacle : obstacles)
140 {
141 // 2.1 Construct the collision geometry
142 pinocchio::GeometryObject::CollisionGeometryPtr collision_geometry;
143 std::string mesh_path = "";
144 Eigen::Vector3d mesh_scale = Eigen::Vector3d::Ones();
145
146 std::visit([&collision_geometry, &mesh_path, &mesh_scale](auto&& arg) {
147 using T = std::decay_t<decltype(arg)>;
148 if constexpr (std::is_same_v<T, coal::Sphere>) {
149 collision_geometry = std::make_shared<coal::Sphere>(arg);
150 mesh_path = "SPHERE";
151 mesh_scale = Eigen::Vector3d::Ones() * arg.radius;
152 }
153 }, obstacle.obstacle);
154
155 pinocchio::GeometryObject geom_object(
156 "Obstacle_" + std::to_string(i_obstacle),
157 0,
158 pinocchio::SE3(obstacle.obstacle_pose),
159 collision_geometry,
160 mesh_path,
161 mesh_scale,
162 false,
163 Eigen::Vector4d(0.5, 0.5, 0.5, 1.0)
164 );
165
166 // 2.2 Add the obstacle to the geometry model
167 geom_model.addGeometryObject(geom_object);
168
169 // 2.3 Add collision pairs between the robot and the obstacle
170 // for collision pairs, we always put the robot higher index body as the second one.
171 // This will help with the distance computation.
172 for(int i = 0; i < robot_geom_num; i++){
173 if(geom_model.geometryObjects[i].disableCollision == false){
174 geom_model.addCollisionPair(pinocchio::CollisionPair(robot_geom_num + i_obstacle, i));
175 }
176 }
177
178 i_obstacle++;
179 }
180
181 // 3. create GeometryData from the GeometryModel
182 pinocchio::GeometryData geom_data(geom_model);
183
184 // 4. calculate distances between the robot and obstacles
185 pinocchio::updateGeometryPlacements(model_, data_, geom_model, geom_data);
186 pinocchio::computeDistances(geom_model, geom_data);
187
188 // 5. output the distances into the output structure
189 for (int i = 0; i < geom_data.distanceResults.size(); i++)
190 {
191 const auto& distance = geom_data.distanceResults[i];
192 const auto& robot_geom = geom_model.geometryObjects[geom_model.collisionPairs[i].second];
193 Eigen::Vector3d seperation_vector = (distance.nearest_points[1] - distance.nearest_points[0]).normalized();
194 Eigen::MatrixXd jacobian_matrix;
195 this->jacobianFrame(q, robot_geom.parentFrame, jacobian_matrix);
196 Eigen::VectorXd projector_control_to_dist = seperation_vector.transpose() * jacobian_matrix.topRows(3);
197 Eigen::VectorXd projector_dist_to_control;
200 projector_dist_to_control = (1.0 / projector_control_to_dist.norm() / projector_control_to_dist.norm()) * projector_control_to_dist.transpose();
201 } else {
202 // Compute the damped Jacobian pseudo-inverse using Jᵀ(JJᵀ + λ²I)⁻¹
203 Eigen::VectorXd seperation_twist = Eigen::VectorXd::Zero(6);
204 seperation_twist.head(3) = seperation_vector;
205 Eigen::MatrixXd JJt = jacobian_matrix * jacobian_matrix.transpose();
206 Eigen::MatrixXd damped_identity = robust_pinv_lambda_ * robust_pinv_lambda_ * Eigen::MatrixXd::Identity(JJt.rows(), JJt.cols());
207
208 projector_dist_to_control = jacobian_matrix.transpose() * (JJt + damped_identity).ldlt().solve(seperation_twist);
209 projector_control_to_dist = (1.0 / projector_dist_to_control.norm() * projector_dist_to_control.norm()) * projector_dist_to_control.transpose();
210 }
211 }
212
213 distances.push_back(distanceResult{
214 i,
215 distance.min_distance,
216 seperation_vector,
217 distance.nearest_points[1],
218 distance.nearest_points[0],
219 robot_geom.name,
220 projector_control_to_dist,
221 projector_dist_to_control
222 });
223 }
224 }
225
226 void RobotEnvEvaluator::computeModelData(const Eigen::VectorXd& q)
227 {
228 if (buffered_q_.size() == 0 || q != buffered_q_)
229 {
230 // Compute the model data
231 pinocchio::forwardKinematics(model_, data_, q);
232 pinocchio::computeJointJacobians(model_, data_, q);
233 pinocchio::updateFramePlacements(model_, data_);
234
235 // Update the buffered joint configuration
236 buffered_q_ = q;
237 }
238 }
239} // namespace robot_env_evaluator
void forwardKinematics(const Eigen::VectorXd &q, Eigen::Matrix4d &T, const int joint_index=-1)
The forward kinematics function for a specific joint, specified by the index.
pinocchio::Data data_
The robot data, initialized from the model.
void jacobianFrame(const Eigen::VectorXd &q, const double frame_index, Eigen::MatrixXd &J)
Get the Jacobian of specific frame.
bool calculate_self_collision_
Whether to calculate self-collision in distance computation.
Eigen::VectorXd buffered_q_
The buffered joint configuration. This is used to avoid unnecessary computation.
void forwardKinematicsByFrameName(const Eigen::VectorXd &q, Eigen::Matrix4d &T, const std::string &frame_name)
The forward kinematics function for a specific frame, specified by the name.
void computeModelData(const Eigen::VectorXd &q)
Compute the model data from the joint configuration.
double robust_pinv_lambda_
The lambda value for the robust pseudo-inverse projector.
bool projector_dist_to_control_with_zero_orientation_
Whether to use the full Jacobian and set the orientation to zero when calculating the projector.
bool projector_dist_to_control_enable_
Whether to calculate the projector from distance to control space.
RobotEnvEvaluator(const pinocchio::Model &model, const std::string &ee_name, const std::vector< std::string > &joint_names, const pinocchio::GeometryModel &collision_model, const pinocchio::GeometryModel &visual_model=pinocchio::GeometryModel())
Construct a new Robot Env Evaluator object.
void jacobianByFrameName(const Eigen::VectorXd &q, Eigen::MatrixXd &J, const std::string &frame_name)
Get the jacobian of specific frame, specified by the name.
int ee_index_
The internal index for end-effector.frame.
std::vector< double > joint_indices_
The joint indices for the robot model.
void computeDistances(const Eigen::VectorXd &q, const std::vector< obstacleInput > &obstacles, std::vector< distanceResult > &distances)
The distance computation function between the robot and obstacles.
pinocchio::GeometryModel collision_model_
The collision model.
void jacobian(const Eigen::VectorXd &q, Eigen::MatrixXd &J, const int joint_index=-1)
The jacobian function for a specific joint, specified by the index.
pinocchio::Model model_
The robot model.
Header file for the RobotEnvEvaluator class, which provides functionalities for evaluating robot envi...
Store the distance result between objects.