52 bool enable_feedforward;
53 enable_feedforward = controller_nh.
getParam(
"feedforward", xml_rpc_value);
54 if (enable_feedforward)
60 mass_origin_.x = enable_feedforward ? (double)xml_rpc_value[
"mass_origin"][0] : 0.;
61 mass_origin_.z = enable_feedforward ? (double)xml_rpc_value[
"mass_origin"][2] : 0.;
62 gravity_ = enable_feedforward ? (double)xml_rpc_value[
"gravity"] : 0.;
66 chassis_vel_ = std::make_shared<ChassisVel>(chassis_vel_nh);
71 .pitch_k_v_ =
getParam(controller_nh,
"controllers/pitch/k_v", 0.),
72 .chassis_comp_a_ =
getParam(controller_nh,
"controllers/yaw/chassis_comp_a", 0.),
73 .chassis_comp_b_ =
getParam(controller_nh,
"controllers/yaw/chassis_comp_b", 0.),
74 .chassis_comp_c_ =
getParam(controller_nh,
"controllers/yaw/chassis_comp_c", 0.),
75 .chassis_comp_d_ =
getParam(controller_nh,
"controllers/yaw/chassis_comp_d", 0.),
76 .accel_pitch_ =
getParam(controller_nh,
"controllers/pitch/accel", 99.),
77 .accel_yaw_ =
getParam(controller_nh,
"controllers/yaw/accel", 99.) };
79 d_srv_ =
new dynamic_reconfigure::Server<rm_gimbal_controllers::GimbalBaseConfig>(controller_nh);
80 dynamic_reconfigure::Server<rm_gimbal_controllers::GimbalBaseConfig>::CallbackType cb =
81 [
this](
auto&& PH1,
auto&& PH2) {
reconfigCB(PH1, PH2); };
86 if (controller_nh.
getParam(
"controllers", xml_rpc_value))
88 for (
const auto& it : xml_rpc_value)
96 if (!
urdf.initParamWithNodeHandle(
"robot_description", controller_nh))
101 auto joint_urdf =
urdf.getJoint(
getParam(nh,
"joint", std::string()));
104 ROS_ERROR(
"Could not find joint in urdf");
109 axis = (joint_urdf->axis.x == 1) * 0 + (joint_urdf->axis.y == 1) * 1 + (joint_urdf->axis.z == 1) * 2;
113 ctrls_.insert(std::make_pair(axis, std::make_unique<effort_controllers::JointVelocityController>()));
114 pid_pos_.insert(std::make_pair(axis, std::make_unique<control_toolbox::Pid>()));
119 if (!
ctrls_.at(axis)->init(effort_joint_interface, nh) || !
pid_pos_.at(axis)->init(nh_pid_pos))
125 if (!controller_nh.
hasParam(
"imu_name"))
129 imu_name_ =
getParam(controller_nh,
"imu_name",
static_cast<std::string
>(
"gimbal_imu"));
136 ROS_INFO(
"Param imu_name has not set, use motors' data instead of imu.");
208 odom2gimbal_des.
setRPY(0, pitch_des, yaw_des);
233 double roll{}, pitch{}, yaw{};
246 double roll_real, pitch_real, yaw_real;
248 double yaw_compute = yaw_real;
249 double pitch_compute = -pitch_real;
250 geometry_msgs::Point target_pos =
data_track_.position;
251 geometry_msgs::Vector3 target_vel{};
258 geometry_msgs::TransformStamped transform =
273 target_pos.x += target_vel.x * (time -
data_track_.header.stamp).toSec() -
odom2gimbal_.transform.translation.x;
274 target_pos.y += target_vel.y * (time -
data_track_.header.stamp).toSec() -
odom2gimbal_.transform.translation.y;
275 target_pos.z += target_vel.z * (time -
data_track_.header.stamp).toSec() -
odom2gimbal_.transform.translation.z;
293 error_pub_->msg_.error = solve_success ? error : 1.0;
316 geometry_msgs::Point aim_point_odom =
cmd_gimbal_.target_pos.point;
319 if (!
cmd_gimbal_.target_pos.header.frame_id.empty())
328 double yaw = std::atan2(aim_point_odom.y -
odom2gimbal_.transform.translation.y,
329 aim_point_odom.x -
odom2gimbal_.transform.translation.x);
330 double pitch = -std::atan2(aim_point_odom.z -
odom2gimbal_.transform.translation.z,
331 std::sqrt(std::pow(aim_point_odom.x -
odom2gimbal_.transform.translation.x, 2) +
332 std::pow(aim_point_odom.y -
odom2gimbal_.transform.translation.y, 2)));
343 double traj[3]{ 0. };
348 geometry_msgs::TransformStamped odom2traj =
370 double base2gimbal_current_des[3];
371 quatToRPY(
toMsg(base2gimbal_des), base2gimbal_current_des[0], base2gimbal_current_des[1], base2gimbal_current_des[2]);
372 double upper_limit = joint_urdf->limits ? joint_urdf->limits->upper : 1e16;
373 double lower_limit = joint_urdf->limits ? joint_urdf->limits->lower : -1e16;
374 int index = (joint_urdf->axis.x == 1) * 0 + (joint_urdf->axis.y == 1) * 1 + (joint_urdf->axis.z == 1) * 2;
375 if ((base2gimbal_current_des[index] <= upper_limit && base2gimbal_current_des[index] >= lower_limit) ||
379 base2new_des = base2gimbal_des;
384 base2gimbal_current_des[index] =
389 base2new_des.
setRPY(base2gimbal_current_des[0], base2gimbal_current_des[1], base2gimbal_current_des[2]);
396 geometry_msgs::Vector3 gyro, angular_vel;
417 angular_vel.x =
ctrls_.at(0)->joint_.getVelocity();
419 angular_vel.y =
ctrls_.at(1)->joint_.getVelocity();
421 angular_vel.z =
ctrls_.at(2)->joint_.getVelocity();
423 double pos_real[3]{ 0. }, pos_des[3]{ 0. }, vel_des[3]{ 0. }, angle_error[3]{ 0. };
426 for (
int i = 0; i < 3; i++)
435 geometry_msgs::Point target_pos;
436 geometry_msgs::Vector3 target_vel;
443 tf2::Vector3 target_pos_tf, target_vel_tf;
446 geometry_msgs::TransformStamped transform;
455 vel_des[2] = target_pos_tf.cross(target_vel_tf).z() / std::pow((target_pos_tf.length()), 2);
465 vel_des[1] = target_pos_tf.cross(target_vel_tf).y() / std::pow((target_pos_tf.length()), 2);
474 if (!in_limit.second)
475 vel_des[in_limit.first] = 0.;
479 pid_pos_.at(1)->computeCommand(angle_error[1], period);
481 ctrls_.at(1)->joint_.getVelocity() - angular_vel.y);
482 ctrls_.at(1)->update(time, period);
487 pid_pos_.at(2)->computeCommand(angle_error[2], period);
491 ctrls_.at(2)->update(time, period);
499 if (pub.second && pub.second->trylock())
501 pub.second->msg_.header.stamp = time;
502 pub.second->msg_.set_point = pos_des[pub.first];
503 pub.second->msg_.set_point_dot = vel_des[pub.first];
504 pub.second->msg_.process_value = pos_real[pub.first];
505 pub.second->msg_.error = angle_error[pub.first];
506 pub.second->msg_.command =
pid_pos_[pub.first]->getCurrentCmd();
507 pub.second->unlockAndPublish();
518 Eigen::Vector3d gravity(0, 0, -
gravity_);
522 double feedforward = -mass_origin.cross(gravity).y();
525 Eigen::Vector3d gravity_compensation(0, 0,
gravity_);
529 feedforward -= mass_origin.cross(gravity_compensation).y();
542 double last_angular_position_x, last_angular_position_y, last_angular_position_z, angular_position_x,
543 angular_position_y, angular_position_z;
544 quatToRPY(
odom2base_.transform.rotation, angular_position_x, angular_position_y, angular_position_z);
546 last_angular_position_z);
550 double linear_vel[3]{ linear_x, linear_y, linear_z };
551 double angular_vel[3]{ angular_x, angular_y, angular_z };
552 chassis_vel_->update(linear_vel, angular_vel, tf_period);
558 if (joint_urdfs.find(1) != joint_urdfs.end())
559 return joint_urdfs.at(1)->child_link_name.c_str();
560 if (joint_urdfs.find(0) != joint_urdfs.end())
561 return joint_urdfs.at(0)->child_link_name.c_str();
562 if (joint_urdfs.find(2) != joint_urdfs.end())
563 return joint_urdfs.at(2)->child_link_name.c_str();
564 return std::string();
569 if (joint_urdfs.find(2) != joint_urdfs.end())
570 return joint_urdfs.at(2)->parent_link_name.c_str();
571 if (joint_urdfs.find(0) != joint_urdfs.end())
572 return joint_urdfs.at(0)->parent_link_name.c_str();
573 if (joint_urdfs.find(1) != joint_urdfs.end())
574 return joint_urdfs.at(1)->parent_link_name.c_str();
575 return std::string();
600 ROS_INFO(
"[Gimbal Base] Dynamic params change");
604 config.yaw_k_v_ = init_config.
yaw_k_v_;
615 .pitch_k_v_ = config.pitch_k_v_,
616 .chassis_comp_a_ = config.chassis_comp_a_,
617 .chassis_comp_b_ = config.chassis_comp_b_,
618 .chassis_comp_c_ = config.chassis_comp_c_,
619 .chassis_comp_d_ = config.chassis_comp_d_,
620 .accel_pitch_ = config.accel_pitch_,
621 .accel_yaw_ = config.accel_yaw_ };