pose_controller.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2013, Johannes Meyer, TU Darmstadt
3 // All rights reserved.
4 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Flight Systems and Automatic Control group,
13 // TU Darmstadt, nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
31 
33 
34 #include <geometry_msgs/PoseStamped.h>
35 #include <geometry_msgs/TwistStamped.h>
36 
37 #include <ros/subscriber.h>
38 #include <ros/callback_queue.h>
39 
41 
42 using namespace controller_interface;
43 
44 class PoseController : public controller_interface::Controller<QuadrotorInterface>
45 {
46 public:
48 
50 
51  bool init(QuadrotorInterface *interface, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
52  {
53  // get interface handles
54  pose_ = interface->getPose();
55  twist_ = interface->getTwist();
56 
57  pose_input_ = interface->addInput<PoseCommandHandle>("pose");
58  twist_input_ = interface->addInput<TwistCommandHandle>("pose/twist");
59  twist_limit_ = interface->addInput<TwistCommandHandle>("pose/twist_limit");
60  twist_output_ = interface->addOutput<TwistCommandHandle>("twist");
61 
62  node_handle_ = root_nh;
63 
64  // subscribe to commanded pose and velocity
65  pose_subscriber_ = node_handle_.subscribe<geometry_msgs::PoseStamped>("command/pose", 1, boost::bind(&PoseController::poseCommandCallback, this, _1));
66  twist_subscriber_ = node_handle_.subscribe<geometry_msgs::TwistStamped>("command/twist", 1, boost::bind(&PoseController::twistCommandCallback, this, _1));
67 
68  // initialize PID controllers
69  pid_.x.init(ros::NodeHandle(controller_nh, "xy"));
70  pid_.y.init(ros::NodeHandle(controller_nh, "xy"));
71  pid_.z.init(ros::NodeHandle(controller_nh, "z"));
72  pid_.yaw.init(ros::NodeHandle(controller_nh, "yaw"));
73 
74  return true;
75  }
76 
77  void reset()
78  {
79  pid_.x.reset();
80  pid_.y.reset();
81  pid_.z.reset();
82  pid_.yaw.reset();
83  }
84 
85  void poseCommandCallback(const geometry_msgs::PoseStampedConstPtr& command)
86  {
87  pose_command_ = *command;
88  if (!(pose_input_->connected())) *pose_input_ = &(pose_command_.pose);
89  pose_input_->start();
90 
91  ros::Time start_time = command->header.stamp;
92  if (start_time.isZero()) start_time = ros::Time::now();
93  if (!isRunning()) this->startRequest(start_time);
94  }
95 
96  void twistCommandCallback(const geometry_msgs::TwistStampedConstPtr& command)
97  {
98  twist_command_ = *command;
99  if (!(twist_input_->connected())) *twist_input_ = &(twist_command_.twist);
100  twist_input_->start();
101 
102  ros::Time start_time = command->header.stamp;
103  if (start_time.isZero()) start_time = ros::Time::now();
104  if (!isRunning()) this->startRequest(start_time);
105  }
106 
107  void starting(const ros::Time &time)
108  {
109  reset();
110  twist_output_->start();
111  }
112 
113  void stopping(const ros::Time &time)
114  {
115  twist_output_->stop();
116  }
117 
118  void update(const ros::Time& time, const ros::Duration& period)
119  {
120  Twist output;
121 
122  // check command timeout
123  // TODO
124 
125  // return if no pose command is available
126  if (pose_input_->enabled()) {
127  // control horizontal position
128  double error_n, error_w;
129  HorizontalPositionCommandHandle(*pose_input_).getError(*pose_, error_n, error_w);
130  output.linear.x = pid_.x.update(error_n, twist_->twist().linear.x, period);
131  output.linear.y = pid_.y.update(error_w, twist_->twist().linear.y, period);
132 
133  // control height
134  output.linear.z = pid_.z.update(HeightCommandHandle(*pose_input_).getError(*pose_), twist_->twist().linear.z, period);
135 
136  // control yaw angle
137  output.angular.z = pid_.yaw.update(HeadingCommandHandle(*pose_input_).getError(*pose_), twist_->twist().angular.z, period);
138  }
139 
140  // add twist command if available
141  if (twist_input_->enabled())
142  {
143  output.linear.x += twist_input_->getCommand().linear.x;
144  output.linear.y += twist_input_->getCommand().linear.y;
145  output.linear.z += twist_input_->getCommand().linear.z;
146  output.angular.x += twist_input_->getCommand().angular.x;
147  output.angular.y += twist_input_->getCommand().angular.y;
148  output.angular.z += twist_input_->getCommand().angular.z;
149  }
150 
151  // limit twist
152  if (twist_limit_->enabled())
153  {
154  double linear_xy = sqrt(output.linear.x*output.linear.x + output.linear.y*output.linear.y);
155  double limit_linear_xy = std::max(twist_limit_->get()->linear.x, twist_limit_->get()->linear.y);
156  if (limit_linear_xy > 0.0 && linear_xy > limit_linear_xy) {
157  output.linear.x *= limit_linear_xy / linear_xy;
158  output.linear.y *= limit_linear_xy / linear_xy;
159  }
160  if (twist_limit_->get()->linear.z > 0.0 && fabs(output.linear.z) > twist_limit_->get()->linear.z) {
161  output.linear.z *= twist_limit_->get()->linear.z / fabs(output.linear.z);
162  }
163  double angular_xy = sqrt(output.angular.x*output.angular.x + output.angular.y*output.angular.y);
164  double limit_angular_xy = std::max(twist_limit_->get()->angular.x, twist_limit_->get()->angular.y);
165  if (limit_angular_xy > 0.0 && angular_xy > limit_angular_xy) {
166  output.angular.x *= limit_angular_xy / angular_xy;
167  output.angular.y *= limit_angular_xy / angular_xy;
168  }
169  if (twist_limit_->get()->angular.z > 0.0 && fabs(output.angular.z) > twist_limit_->get()->angular.z) {
170  output.angular.z *= twist_limit_->get()->angular.z / fabs(output.angular.z);
171  }
172  }
173 
174  // set twist output
175  twist_output_->setCommand(output);
176  }
177 
178 private:
185 
186  geometry_msgs::PoseStamped pose_command_;
187  geometry_msgs::TwistStamped twist_command_;
188 
192 
193  struct {
198  } pid_;
199 };
200 
201 } // namespace hector_quadrotor_controller
202 
boost::shared_ptr< HandleType > addOutput(const std::string &name)
bool init(QuadrotorInterface *interface, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
boost::shared_ptr< HandleType > addInput(const std::string &name)
void poseCommandCallback(const geometry_msgs::PoseStampedConstPtr &command)
void update(const ros::Time &time, const ros::Duration &period)
void twistCommandCallback(const geometry_msgs::TwistStampedConstPtr &command)
double getError(const PoseHandle &pose) const
double getError(const PoseHandle &pose) const
static Time now()
void getError(const PoseHandle &pose, double &x, double &y) const


hector_quadrotor_controller
Author(s): Johannes Meyer
autogenerated on Sun Jul 10 2016 04:30:48