35 #include <geometry_msgs/TwistStamped.h> 36 #include <geometry_msgs/WrenchStamped.h> 44 #include <boost/thread/mutex.hpp> 61 twist_subscriber_.shutdown();
62 cmd_vel_subscriber_.shutdown();
75 root_nh.
param<std::string>(
"base_link_frame", base_link_frame_,
"base_link");
76 root_nh.
param<std::string>(
"world_frame", world_frame_,
"/world");
77 root_nh.
param<std::string>(
"base_stabilized_frame", base_stabilized_frame_,
"base_stabilized");
78 controller_nh.
param(
"limits/load_factor", load_factor_limit_, 1.5);
83 world_frame_ =
tf::resolve(tf_prefix_, world_frame_);
84 base_link_frame_ =
tf::resolve(tf_prefix_, base_link_frame_);
85 base_stabilized_frame_ =
tf::resolve(tf_prefix_, base_stabilized_frame_);
92 twist_limiter_.linear.init(controller_nh);
93 twist_limiter_.angular.init(controller_nh,
"yawrate");
102 twist_subscriber_ = root_nh.
subscribe<geometry_msgs::TwistStamped>(
"command/twist", 1, boost::bind(
104 cmd_vel_subscriber_ = root_nh.
subscribe<geometry_msgs::Twist>(
"cmd_vel", 1, boost::bind(
117 twist_command_ = TwistStamped();
127 attitude_output_->stop();
128 yawrate_output_->stop();
129 thrust_output_->stop();
134 boost::mutex::scoped_lock lock(command_mutex_);
137 if (!isRunning()) this->startRequest(command->header.stamp);
139 std::string frame_id =
tf::resolve(tf_prefix_, command->header.frame_id);
140 if (frame_id != base_stabilized_frame_ && frame_id != world_frame_) {
142 << base_stabilized_frame_ <<
" or the " 143 << world_frame_ <<
" frame, ignoring command");
147 twist_command_ = *command;
148 twist_command_.header.frame_id = frame_id;
151 if ((twist_command_.twist.linear.x != 0.0) ||
152 (twist_command_.twist.linear.y != 0.0) ||
153 (twist_command_.twist.linear.z != 0.0) ||
154 (twist_command_.twist.angular.x != 0.0) ||
155 (twist_command_.twist.angular.y != 0.0) ||
156 (twist_command_.twist.angular.z != 0.0)) {
157 twist_input_->preempt();
163 boost::mutex::scoped_lock lock(command_mutex_);
167 if (!isRunning()) this->startRequest(now);
169 twist_command_.twist = *command;
170 twist_command_.header.stamp = now;
171 twist_command_.header.frame_id = base_stabilized_frame_;
174 if ((twist_command_.twist.linear.x != 0.0) ||
175 (twist_command_.twist.linear.y != 0.0) ||
176 (twist_command_.twist.linear.z != 0.0) ||
177 (twist_command_.twist.angular.x != 0.0) ||
178 (twist_command_.twist.angular.y != 0.0) ||
179 (twist_command_.twist.angular.z != 0.0)) {
180 twist_input_->preempt();
186 boost::mutex::scoped_lock lock(command_mutex_);
189 if (twist_input_->connected() && twist_input_->enabled())
191 twist_command_.twist = twist_input_->getCommand();
192 twist_command_.header.stamp = time;
193 twist_command_.header.frame_id = world_frame_;
197 if (motor_status_->motorStatus().running ==
false) {
202 attitude_output_->start();
203 yawrate_output_->start();
204 thrust_output_->start();
207 Twist
command = twist_limiter_(twist_command_.twist);
210 double yaw = pose_->getYaw(), sin_yaw, cos_yaw;
211 sincos(yaw, &sin_yaw, &cos_yaw);
212 Twist twist = twist_->twist(), twist_body;
213 twist_body.linear = pose_->toBody(twist.linear);
214 twist_body.angular = pose_->toBody(twist.angular);
218 if (twist_command_.header.frame_id == base_stabilized_frame_) {
219 Twist transformed = command;
220 transformed.linear.x = cos_yaw * command.linear.x - sin_yaw * command.linear.y;
221 transformed.linear.y = sin_yaw * command.linear.x + cos_yaw * command.linear.y;
222 transformed.angular.x = cos_yaw * command.angular.x - sin_yaw * command.angular.y;
223 transformed.angular.y = sin_yaw * command.angular.x + cos_yaw * command.angular.y;
224 command = transformed;
228 const double gravity = 9.8065;
229 double load_factor = 1. / ( pose_->pose().orientation.w * pose_->pose().orientation.w
230 - pose_->pose().orientation.x * pose_->pose().orientation.x
231 - pose_->pose().orientation.y * pose_->pose().orientation.y
232 + pose_->pose().orientation.z * pose_->pose().orientation.z );
234 if (load_factor_limit_ > 0.0 && !(load_factor < load_factor_limit_)) load_factor = load_factor_limit_;
238 acceleration_command.x = pid_.x.computeCommand(command.linear.x - twist.linear.x, period);
239 acceleration_command.y = pid_.y.computeCommand(command.linear.y - twist.linear.y, period);
240 acceleration_command.z = pid_.z.computeCommand(command.linear.z - twist.linear.z, period) + gravity;
243 Vector3 acceleration_command_base_stabilized;
244 acceleration_command_base_stabilized.x = cos_yaw * acceleration_command.x + sin_yaw * acceleration_command.y;
245 acceleration_command_base_stabilized.y = -sin_yaw * acceleration_command.x + cos_yaw * acceleration_command.y;
246 acceleration_command_base_stabilized.z = acceleration_command.z;
248 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"twist.linear: [" << twist.linear.x <<
" " << twist.linear.y <<
" " << twist.linear.z <<
"]");
249 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"twist_body.angular: [" << twist_body.angular.x <<
" " << twist_body.angular.y <<
" " << twist_body.angular.z <<
"]");
250 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"twist_command.linear: [" << command.linear.x <<
" " << command.linear.y <<
" " << command.linear.z <<
"]");
251 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"twist_command.angular: [" << command.angular.x <<
" " << command.angular.y <<
" " << command.angular.z <<
"]");
253 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"acceleration_command_world: [" << acceleration_command.x <<
" " << acceleration_command.y <<
" " << acceleration_command.z <<
"]");
254 ROS_DEBUG_STREAM_NAMED(
"velocity_controller",
"acceleration_command_body: [" << acceleration_command_base_stabilized.x <<
" " << acceleration_command_base_stabilized.y <<
" " << acceleration_command_base_stabilized.z <<
"]");
256 hector_uav_msgs::AttitudeCommand attitude_control;
257 hector_uav_msgs::YawrateCommand yawrate_control;
258 hector_uav_msgs::ThrustCommand thrust_control;
259 attitude_control.roll = -
asin(std::min(std::max(acceleration_command_base_stabilized.y / gravity, -1.0), 1.0));
260 attitude_control.pitch =
asin(std::min(std::max(acceleration_command_base_stabilized.x / gravity, -1.0), 1.0));
261 yawrate_control.turnrate = command.angular.z;
262 thrust_control.thrust = mass_ * ((acceleration_command.z - gravity) * load_factor + gravity);
265 attitude_control.header.stamp = twist_command_.header.stamp;
266 yawrate_control.header.stamp = twist_command_.header.stamp;
267 thrust_control.header.stamp = twist_command_.header.stamp;
270 attitude_output_->setCommand(attitude_control);
271 yawrate_output_->setCommand(yawrate_control);
272 thrust_output_->setCommand(thrust_control);
virtual void update(const ros::Time &time, const ros::Duration &period)
void cmd_velCommandCallback(const geometry_msgs::TwistConstPtr &command)
virtual void stopping(const ros::Time &time)
#define ROS_DEBUG_STREAM_NAMED(name, args)
std::string getPrefixParam(ros::NodeHandle &nh)
AttitudeCommandHandlePtr attitude_output_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Subscriber cmd_vel_subscriber_
double load_factor_limit_
geometry_msgs::TwistStamped twist_command_
virtual ~VelocityController()
boost::shared_ptr< HandleType > addInput(const std::string &name)
virtual void starting(const ros::Time &time)
TFSIMD_FORCE_INLINE const tfScalar & y() const
YawrateCommandHandlePtr yawrate_output_
std::string resolve(const std::string &prefix, const std::string &frame_name)
void twistCommandCallback(const geometry_msgs::TwistStampedConstPtr &command)
ros::Subscriber twist_subscriber_
ROSLIB_DECL std::string command(const std::string &cmd)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
TFSIMD_FORCE_INLINE Vector3()
INLINE Rall1d< T, V, S > asin(const Rall1d< T, V, S > &x)
#define ROS_WARN_STREAM_THROTTLE_NAMED(rate, name, args)
virtual bool init(hector_quadrotor_interface::QuadrotorInterface *interface, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::shared_ptr< HandleType > addOutput(const std::string &name)
TwistCommandHandlePtr twist_input_
hector_quadrotor_interface::TwistLimiter twist_limiter_
MotorStatusHandlePtr motor_status_
bool getMassAndInertia(const ros::NodeHandle &nh, double &mass, double inertia[3])
ThrustCommandHandlePtr thrust_output_
MotorStatusHandlePtr getMotorStatus()
boost::mutex command_mutex_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
TwistHandlePtr getTwist()