176 num_joints_ = num_joints;
177 robot_model_ = robot_model;
178 cur_acceleration_ = Eigen::VectorXd::Zero(num_joints);
181 auto param_listener = online_signal_smoothing::ParamListener(node_);
182 params_ = param_listener.get_params();
185 auto joint_model_group = robot_model_->getJointModelGroup(params_.planning_group_name);
186 auto joint_bounds = joint_model_group->getActiveJointModelsBounds();
187 min_acceleration_limits_ = Eigen::VectorXd::Zero(num_joints);
188 max_acceleration_limits_ = Eigen::VectorXd::Zero(num_joints);
190 for (
const auto& joint_bound : joint_bounds)
192 for (
const auto& variable_bound : *joint_bound)
194 if (variable_bound.acceleration_bounded_)
196 min_acceleration_limits_[ind] = variable_bound.min_acceleration_;
197 max_acceleration_limits_[ind] = variable_bound.max_acceleration_;
201 RCLCPP_ERROR(
getLogger(),
"The robot must have acceleration joint limits specified for all joints to "
202 "use AccelerationLimitedPlugin.");
210 Eigen::SparseMatrix<double> objective_sparse(1, 1);
211 objective_sparse.insert(0, 0) = 1.0;
212 size_t num_constraints = num_joints + 1;
213 constraints_sparse_ = Eigen::SparseMatrix<double>(num_constraints, 1);
214 for (
size_t i = 0; i < num_constraints - 1; ++i)
216 constraints_sparse_.insert(i, 0) = 0;
218 constraints_sparse_.insert(num_constraints - 1, 0) = 0;
219 osqp_set_default_settings(&osqp_settings_);
222 osqp_settings_.warm_starting = 0;
224 osqp_settings_.warm_start = 0;
226 osqp_settings_.verbose = 0;
227 osqp_data_ = std::make_shared<OSQPDataWrapper>(objective_sparse, constraints_sparse_);
228 osqp_data_->q[0] = 0;
232 if (osqp_setup(&osqp_solver_, &osqp_data_->P.csc_sparse_matrix, osqp_data_->q.data(), &osqp_data_->A.csc_sparse_matrix,
233 osqp_data_->l.data(), osqp_data_->u.data(),
static_cast<OSQPInt>(osqp_data_->A.csc_sparse_matrix.m),
234 static_cast<OSQPInt>(osqp_data_->P.csc_sparse_matrix.n), &osqp_settings_) != 0)
236 osqp_settings_.verbose = 1;
238 osqp_setup(&osqp_solver_, &osqp_data_->P.csc_sparse_matrix, osqp_data_->q.data(), &osqp_data_->A.csc_sparse_matrix,
239 osqp_data_->l.data(), osqp_data_->u.data(),
static_cast<OSQPInt>(osqp_data_->A.csc_sparse_matrix.m),
240 static_cast<OSQPInt>(osqp_data_->P.csc_sparse_matrix.n), &osqp_settings_);
241 RCLCPP_ERROR(
getLogger(),
"Failed to initialize osqp problem.");
245 if (osqp_setup(&osqp_solver_, &osqp_data_->data, &osqp_settings_) != 0)
247 osqp_settings_.verbose = 1;
249 osqp_setup(&osqp_solver_, &osqp_data_->data, &osqp_settings_);
250 RCLCPP_ERROR(
getLogger(),
"Failed to initialize osqp problem.");
261 double min_scaling_factor = 1.0;
265 for (
const auto& joint_bound : joint_bounds)
267 for (
const auto& variable_bound : *joint_bound)
269 const auto& target_accel = accelerations(idx);
270 if (variable_bound.acceleration_bounded_ && target_accel != 0.0)
273 const auto bounded_vel =
274 std::clamp(target_accel, variable_bound.min_acceleration_, variable_bound.max_acceleration_);
275 double joint_scaling_factor = bounded_vel / target_accel;
276 min_scaling_factor = std::min(min_scaling_factor, joint_scaling_factor);
282 return min_scaling_factor;
290inline bool updateData(
const OSQPDataWrapperPtr& data, OSQPWorkspace* solver,
291 Eigen::SparseMatrix<double>& constraints_sparse,
const Eigen::VectorXd& lower_bound,
292 const Eigen::VectorXd& upper_bound)
295 data->updateA(solver, constraints_sparse);
296 size_t num_constraints = constraints_sparse.rows();
297 data->u.block(0, 0, num_constraints - 1, 1) = upper_bound;
298 data->l.block(0, 0, num_constraints - 1, 1) = lower_bound;
303 return 0 == osqp_update_data_vec(solver,
nullptr, data->l.data(), data->u.data());
305 return 0 == osqp_update_bounds(solver, data->l.data(), data->u.data());
312 const size_t num_positions = velocities.size();
313 if (num_positions != num_joints_)
315 RCLCPP_ERROR_THROTTLE(
317 "The length of the joint positions parameter is not equal to the number of joints, expected %zu got %zu.",
318 num_joints_, num_positions);
321 else if (last_positions_.size() != positions.size())
323 RCLCPP_ERROR_THROTTLE(
getLogger(), *node_->get_clock(), 1000,
324 "The length of the last joint positions not equal to the current, expected %zu got %zu. Make "
325 "sure the reset was called.",
326 last_positions_.size(), positions.size());
348 double& update_period = params_.update_period;
349 size_t num_constraints = num_joints_ + 1;
350 positions_offset_ = last_positions_ - positions;
351 velocities_offset_ = last_velocities_ - velocities;
352 for (
size_t i = 0; i < num_constraints - 1; ++i)
354 constraints_sparse_.coeffRef(i, 0) = positions_offset_[i];
356 constraints_sparse_.coeffRef(num_constraints - 1, 0) = 1;
357 Eigen::VectorXd vel_point = last_positions_ + last_velocities_ * update_period;
358 Eigen::VectorXd upper_bound = vel_point - positions + max_acceleration_limits_ * (update_period * update_period);
359 Eigen::VectorXd lower_bound = vel_point - positions + min_acceleration_limits_ * (update_period * update_period);
360 if (!
updateData(osqp_data_, osqp_solver_, constraints_sparse_, lower_bound, upper_bound))
362 RCLCPP_ERROR_THROTTLE(
getLogger(), *node_->get_clock(), 1000,
363 "failed to set osqp constraint bounds. Make sure the robot's acceleration limits are valid");
370 positions = last_positions_;
371 velocities = last_velocities_;
373 else if (osqp_solve(osqp_solver_) == 0 &&
377 double alpha = osqp_solver_->solution->x[0];
378 positions = alpha * last_positions_ + (1.0 - alpha) * positions.eval();
379 velocities = (positions - last_positions_) / update_period;
383 auto joint_model_group = robot_model_->getJointModelGroup(params_.planning_group_name);
384 auto joint_bounds = joint_model_group->getActiveJointModelsBounds();
385 cur_acceleration_ = -(last_velocities_) / update_period;
387 velocities = last_velocities_ + cur_acceleration_ * update_period;
388 positions = last_positions_ + velocities * update_period;
391 last_velocities_ = velocities;
392 last_positions_ = positions;