47 template class ChassisBase<rm_control::RobotStateInterface, hardware_interface::EffortJointInterface>;
51 template <
typename... T>
55 if (!controller_nh.
getParam(
"publish_rate", publish_rate_) || !controller_nh.
getParam(
"timeout", timeout_) ||
56 !controller_nh.
getParam(
"power/vel_coeff", velocity_coeff_) ||
57 !controller_nh.
getParam(
"power/effort_coeff", effort_coeff_) ||
58 !controller_nh.
getParam(
"power/power_offset", power_offset_))
63 wheel_radius_ =
getParam(controller_nh,
"wheel_radius", 0.02);
64 twist_angular_ =
getParam(controller_nh,
"twist_angular", M_PI / 6);
65 max_odom_vel_ =
getParam(controller_nh,
"max_odom_vel", 0);
66 enable_odom_tf_ =
getParam(controller_nh,
"enable_odom_tf",
true);
67 publish_odom_tf_ =
getParam(controller_nh,
"publish_odom_tf",
false);
71 controller_nh.
getParam(
"twist_covariance_diagonal", twist_cov_list);
74 for (
int i = 0; i < twist_cov_list.
size(); ++i)
82 odom_pub_->msg_.header.frame_id =
"odom";
83 odom_pub_->msg_.child_frame_id =
"base_link";
84 odom_pub_->msg_.twist.covariance = {
static_cast<double>(twist_cov_list[0]), 0., 0., 0., 0., 0., 0.,
85 static_cast<double>(twist_cov_list[1]), 0., 0., 0., 0., 0., 0.,
86 static_cast<double>(twist_cov_list[2]), 0., 0., 0., 0., 0., 0.,
87 static_cast<double>(twist_cov_list[3]), 0., 0., 0., 0., 0., 0.,
88 static_cast<double>(twist_cov_list[4]), 0., 0., 0., 0., 0., 0.,
89 static_cast<double>(twist_cov_list[5]) };
98 odom2base_.header.frame_id =
"odom";
100 odom2base_.child_frame_id =
"base_link";
101 odom2base_.transform.rotation.w = 1;
102 tf_broadcaster_.init(root_nh);
103 tf_broadcaster_.sendTransform(odom2base_);
113 if (controller_nh.
hasParam(
"pid_follow"))
120 template <
typename... T>
123 rm_msgs::ChassisCmd cmd_chassis = cmd_rt_buffer_.readFromRT()->cmd_chassis_;
124 geometry_msgs::Twist cmd_vel = cmd_rt_buffer_.readFromRT()->cmd_vel_;
126 if ((time - cmd_rt_buffer_.readFromRT()->stamp_).toSec() > timeout_)
134 ramp_x_->setAcc(cmd_chassis.accel.linear.x);
135 ramp_y_->setAcc(cmd_chassis.accel.linear.y);
136 ramp_x_->input(cmd_vel.linear.x);
137 ramp_y_->input(cmd_vel.linear.y);
138 vel_cmd_.x = ramp_x_->output();
139 vel_cmd_.y = ramp_y_->output();
140 vel_cmd_.z = cmd_vel.angular.z;
143 if (cmd_rt_buffer_.readFromRT()->cmd_chassis_.follow_source_frame.empty())
144 follow_source_frame_ =
"yaw";
146 follow_source_frame_ = cmd_rt_buffer_.readFromRT()->cmd_chassis_.follow_source_frame;
147 if (cmd_rt_buffer_.readFromRT()->cmd_chassis_.command_source_frame.empty())
148 command_source_frame_ =
"yaw";
150 command_source_frame_ = cmd_rt_buffer_.readFromRT()->cmd_chassis_.command_source_frame;
152 if (state_ != cmd_chassis.mode)
154 state_ = cmd_chassis.mode;
155 state_changed_ =
true;
158 updateOdom(time, period);
166 follow(time, period);
173 ramp_w_->setAcc(cmd_chassis.accel.angular.z);
174 ramp_w_->input(vel_cmd_.z);
175 vel_cmd_.z = ramp_w_->output();
177 moveJoint(time, period);
181 template <
typename... T>
186 state_changed_ =
false;
193 tfVelToBase(command_source_frame_);
196 double roll{}, pitch{}, yaw{};
197 quatToRPY(robot_state_handle_.lookupTransform(
"base_link", follow_source_frame_,
ros::Time(0)).transform.rotation,
200 pid_follow_.computeCommand(-follow_error, period);
201 vel_cmd_.z = pid_follow_.getCurrentCmd() + cmd_rt_buffer_.readFromRT()->cmd_chassis_.follow_vel_des;
209 template <
typename... T>
214 state_changed_ =
false;
220 tfVelToBase(command_source_frame_);
223 double roll{}, pitch{}, yaw{};
224 quatToRPY(robot_state_handle_.lookupTransform(
"base_link", command_source_frame_,
ros::Time(0)).transform.rotation,
227 double angle[4] = { -0.785, 0.785, 2.355, -2.355 };
228 double off_set = 0.0;
229 for (
double i : angle)
237 double follow_error =
240 pid_follow_.computeCommand(-follow_error, period);
241 vel_cmd_.z = pid_follow_.getCurrentCmd();
249 template <
typename... T>
254 state_changed_ =
false;
259 tfVelToBase(command_source_frame_);
262 template <
typename... T>
265 geometry_msgs::Twist vel_base = odometry();
268 geometry_msgs::Vector3 linear_vel_odom, angular_vel_odom;
271 odom2base_ = robot_state_handle_.lookupTransform(
"odom",
"base_link",
ros::Time(0));
275 tf_broadcaster_.sendTransform(odom2base_);
279 odom2base_.header.stamp = time;
284 std::sqrt(std::pow(linear_vel_odom.x, 2) + std::pow(linear_vel_odom.y, 2) + std::pow(linear_vel_odom.z, 2));
285 if (length < max_odom_vel_)
288 odom2base_.transform.translation.x += linear_vel_odom.x * period.
toSec();
289 odom2base_.transform.translation.y += linear_vel_odom.y * period.
toSec();
290 odom2base_.transform.translation.z += linear_vel_odom.z * period.
toSec();
293 std::sqrt(std::pow(angular_vel_odom.x, 2) + std::pow(angular_vel_odom.y, 2) + std::pow(angular_vel_odom.z, 2));
297 tf2::fromMsg(odom2base_.transform.rotation, odom2base_quat);
299 angular_vel_odom.z /
length),
301 odom2base_quat = trans_quat * odom2base_quat;
303 odom2base_.transform.rotation =
tf2::toMsg(odom2base_quat);
309 auto* odom_msg = odom_buffer_.readFromRT();
313 tf2::Vector3(odom_msg->pose.pose.position.x, odom_msg->pose.pose.position.y, odom_msg->pose.pose.position.z));
315 odom_msg->pose.pose.orientation.z, odom_msg->pose.pose.orientation.w));
322 geometry_msgs::TransformStamped tf_msg =
323 robot_state_handle_.lookupTransform(
"odom",
"livox_frame", odom_msg->header.stamp);
331 world2odom_ = world2sensor * odom2sensor.
inverse();
336 geometry_msgs::TransformStamped tf_msg =
337 robot_state_handle_.lookupTransform(
"base_link",
"livox_frame", odom_msg->header.stamp);
346 odom2base_.transform.translation.x = odom2base.
getOrigin().x();
347 odom2base_.transform.translation.y = odom2base.
getOrigin().y();
348 odom2base_.transform.translation.z = odom2base.
getOrigin().z();
349 topic_update_ =
false;
352 robot_state_handle_.setTransform(odom2base_,
"rm_chassis_controllers");
354 if (publish_rate_ > 0.0 && last_publish_time_ +
ros::Duration(1.0 / publish_rate_) < time)
356 if (odom_pub_->trylock())
358 odom_pub_->msg_.header.stamp = time;
359 odom_pub_->msg_.twist.twist.linear.x = vel_base.linear.x;
360 odom_pub_->msg_.twist.twist.linear.y = vel_base.linear.y;
361 odom_pub_->msg_.twist.twist.angular.z = vel_base.angular.z;
362 odom_pub_->unlockAndPublish();
364 if (enable_odom_tf_ && publish_odom_tf_)
365 tf_broadcaster_.sendTransform(odom2base_);
366 last_publish_time_ = time;
370 template <
typename... T>
373 ramp_x_->clear(vel_cmd_.x);
374 ramp_y_->clear(vel_cmd_.y);
375 ramp_w_->clear(vel_cmd_.z);
378 template <
typename... T>
381 double power_limit = cmd_rt_buffer_.readFromRT()->cmd_chassis_.power_limit;
383 double a = 0., b = 0., c = 0.;
384 for (
const auto& joint : joint_handles_)
386 double cmd_effort = joint.getCommand();
387 double real_vel = joint.getVelocity();
388 if (joint.getName().find(
"wheel") != std::string::npos)
391 b += std::abs(cmd_effort * real_vel);
396 c = c * velocity_coeff_ - power_offset_ - power_limit;
398 double zoom_coeff = (
square(b) - 4 * a * c) > 0 ? ((-b + sqrt(
square(b) - 4 * a * c)) / (2 * a)) : 0.;
399 for (
auto joint : joint_handles_)
400 if (joint.getName().find(
"wheel") != std::string::npos)
402 joint.setCommand(zoom_coeff > 1 ? joint.getCommand() : joint.getCommand() * zoom_coeff);
406 template <
typename... T>
419 template <
typename... T>
422 cmd_struct_.cmd_chassis_ = *
msg;
423 cmd_rt_buffer_.writeFromNonRT(cmd_struct_);
426 template <
typename... T>
429 cmd_struct_.cmd_vel_ = *
msg;
431 cmd_rt_buffer_.writeFromNonRT(cmd_struct_);
434 template <
typename... T>
437 odom_buffer_.writeFromNonRT(*msg);
438 topic_update_ =
true;