31 #include <geometry_msgs/TwistStamped.h> 36 #include <boost/thread/mutex.hpp> 37 #include <geometry_msgs/PoseStamped.h> 38 #include <geometry_msgs/Twist.h> 43 #include <visualization_msgs/Marker.h> 58 : pose_command_valid_(false), twist_limit_valid_(false)
64 pose_subscriber_.shutdown();
65 twist_limit_subscriber_.shutdown();
77 root_nh.
param<std::string>(
"base_link_frame", base_link_frame_,
"base_link");
78 root_nh.
param<std::string>(
"world_frame", world_frame_,
"/world");
79 root_nh.
param<std::string>(
"base_stabilized_frame", base_stabilized_frame_,
"base_stabilized");
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_);
93 position_limiter_.init(controller_nh);
97 marker_publisher_ = root_nh.
advertise<visualization_msgs::Marker>(
"command/pose_marker", 1);
106 pose_subscriber_ = root_nh.
subscribe<geometry_msgs::PoseStamped>(
"command/pose", 1, boost::bind(
108 twist_limit_subscriber_ = root_nh.
subscribe<geometry_msgs::Twist>(
"command/twist_limit", 1, boost::bind(
122 updatePoseCommand(pose_->pose());
123 pose_command_valid_ =
false;
133 twist_output_->stop();
134 pose_command_valid_ =
false;
140 boost::mutex::scoped_lock lock(command_mutex_);
142 ros::Time start_time = command->header.stamp;
144 if (!isRunning()) this->startRequest(start_time);
146 updatePoseCommand(*command);
151 boost::mutex::scoped_lock lock(command_mutex_);
153 twist_limit_ = *limit;
154 twist_limit_valid_ =
true;
159 boost::mutex::scoped_lock lock(command_mutex_);
163 if (pose_input_->connected() && pose_input_->enabled())
165 updatePoseCommand(pose_input_->getCommand());
169 if (twist_limit_input_->connected() && twist_limit_input_->enabled())
171 twist_limit_ = twist_limit_input_->getCommand();
172 twist_limit_valid_ =
true;
179 if (twist_output_->preempted()) {
180 if (pose_command_valid_) {
181 ROS_INFO_NAMED(
"position_controller",
"Position control preempted!");
183 pose_command_valid_ =
false;
187 if (motor_status_->motorStatus().running ==
false) {
188 if (pose_command_valid_) {
189 ROS_INFO_NAMED(
"position_controller",
"Disabled position control while motors are not running.");
191 pose_command_valid_ =
false;
195 if (!pose_command_valid_) {
197 twist_output_->stop();
200 twist_output_->start();
203 Pose pose = pose_->pose();
214 double yaw = pose_->getYaw();
216 pose_command_.position = position_limiter_(pose_command_.position);
218 output.linear.x = pid_.x.computeCommand(pose_command_.position.x - pose.position.x, period);
219 output.linear.y = pid_.y.computeCommand(pose_command_.position.y - pose.position.y, period);
220 output.linear.z = pid_.z.computeCommand(pose_command_.position.z - pose.position.z, period);
222 double yaw_error = yaw_command - yaw;
224 if (yaw_error > M_PI)
226 yaw_error -= 2 * M_PI;
228 else if (yaw_error < -M_PI)
230 yaw_error += 2 * M_PI;
232 output.angular.z = pid_.yaw.computeCommand(yaw_error, period);
235 if (twist_input_->connected() && twist_input_->enabled())
237 output.linear.x += twist_input_->getCommand().linear.x;
238 output.linear.y += twist_input_->getCommand().linear.y;
239 output.linear.z += twist_input_->getCommand().linear.z;
240 output.angular.x += twist_input_->getCommand().angular.x;
241 output.angular.y += twist_input_->getCommand().angular.y;
242 output.angular.z += twist_input_->getCommand().angular.z;
246 if (twist_limit_valid_)
248 double linear_xy =
sqrt(output.linear.x*output.linear.x + output.linear.y*output.linear.y);
249 double limit_linear_xy = std::max(twist_limit_.linear.x, twist_limit_.linear.y);
250 if (limit_linear_xy > 0.0 && linear_xy > limit_linear_xy) {
251 output.linear.x *= limit_linear_xy / linear_xy;
252 output.linear.y *= limit_linear_xy / linear_xy;
254 if (twist_limit_.linear.z > 0.0 && fabs(output.linear.z) > twist_limit_.linear.z) {
255 output.linear.z *= twist_limit_.linear.z / fabs(output.linear.z);
257 double angular_xy =
sqrt(output.angular.x*output.angular.x + output.angular.y*output.angular.y);
258 double limit_angular_xy = std::max(twist_limit_.angular.x, twist_limit_.angular.y);
259 if (limit_angular_xy > 0.0 && angular_xy > limit_angular_xy) {
260 output.angular.x *= limit_angular_xy / angular_xy;
261 output.angular.y *= limit_angular_xy / angular_xy;
263 if (twist_limit_.angular.z > 0.0 && fabs(output.angular.z) > twist_limit_.angular.z) {
264 output.angular.z *= twist_limit_.angular.z / fabs(output.angular.z);
269 twist_output_->setCommand(output);
276 if (new_pose.header.frame_id != world_frame_) {
281 updatePoseCommand(new_pose.pose);
288 pose_command_.position = new_pose.position;
291 double roll, pitch, yaw;
296 pose_command_valid_ =
true;
298 pose_marker_.pose = pose_command_;
299 marker_publisher_.publish(pose_marker_);
304 pose_marker_.header.frame_id = world_frame_;
305 pose_marker_.ns = name;
307 pose_marker_.type = visualization_msgs::Marker::ARROW;
308 pose_marker_.scale.x = 0.15;
309 pose_marker_.scale.y = pose_marker_.scale.z = 0.03;
310 pose_marker_.color.r = 0.5;
311 pose_marker_.color.g = 0.5;
312 pose_marker_.color.r = 0.5;
313 pose_marker_.color.a = 1.0;
PoseCommandHandlePtr pose_input_
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
void twistLimitCallback(const geometry_msgs::TwistConstPtr &limit)
void getRPY(tf2Scalar &roll, tf2Scalar &pitch, tf2Scalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO_NAMED(name,...)
std::string getPrefixParam(ros::NodeHandle &nh)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
virtual void starting(const ros::Time &time)
hector_quadrotor_interface::PointLimiter position_limiter_
MotorStatusHandlePtr motor_status_
boost::shared_ptr< HandleType > addInput(const std::string &name)
TwistCommandHandlePtr twist_output_
void initMarker(std::string name)
void poseCommandCallback(const geometry_msgs::PoseStampedConstPtr &command)
ros::Subscriber twist_limit_subscriber_
TFSIMD_FORCE_INLINE const tfScalar & y() const
std::string resolve(const std::string &prefix, const std::string &frame_name)
TwistCommandHandlePtr twist_input_
virtual void stopping(const ros::Time &time)
virtual ~PositionController()
void updatePoseCommand(const geometry_msgs::Pose &new_pose)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
#define ROS_WARN_STREAM_THROTTLE_NAMED(rate, name, args)
void fromMsg(const A &, B &b)
const std::string & getNamespace() const
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::shared_ptr< HandleType > addOutput(const std::string &name)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
visualization_msgs::Marker pose_marker_
boost::mutex command_mutex_
virtual void update(const ros::Time &time, const ros::Duration &period)
geometry_msgs::Twist twist_limit_
ros::Publisher marker_publisher_
geometry_msgs::Pose pose_command_
TwistCommandHandlePtr twist_limit_input_
MotorStatusHandlePtr getMotorStatus()
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
virtual bool init(QuadrotorInterface *interface, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
void updatePoseCommand(const geometry_msgs::PoseStamped &new_pose)
TwistHandlePtr getTwist()