quadrotor_aerodynamics.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2012-2016, Institute of Flight Systems and Automatic Control,
3 // Technische Universität Darmstadt.
4 // All rights reserved.
5 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of hector_quadrotor nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without 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 
32 #include <ros/node_handle.h>
33 #include <boost/array.hpp>
34 
35 //extern "C" {
36 // #include "quadrotorDrag/quadrotorDrag.h"
37 // #include "quadrotorDrag/quadrotorDrag_initialize.h"
38 //}
39 
40 #include <boost/array.hpp>
41 #include <Eigen/Geometry>
42 
43 #include "matlab_helpers.h"
44 
45 namespace hector_quadrotor_model {
46 
48 {
53 
55  : C_wxy(0.0)
56  , C_wz(0.0)
57  , C_mxy(0.0)
58  , C_mz(0.0)
59  {}
60 };
61 
62 // extern void quadrotorDrag(const real_T uin[6], const DragParameters parameter, real_T dt, real_T y[6]);
65  boost::array<real_T,6> u;
66  boost::array<real_T,6> y;
67 };
68 
70 {
71  // initialize drag model
72  // quadrotorDrag_initialize();
73  drag_model_ = new DragModel;
74 }
75 
77 {
78  delete drag_model_;
79 }
80 
81 /*
82  * quadrotorDrag.c
83  *
84  * Code generation for function 'quadrotorDrag'
85  *
86  * C source code generated on: Sun Nov 3 13:34:38 2013
87  *
88  */
89 
90 /* Include files */
91 //#include "rt_nonfinite.h"
92 //#include "quadrotorDrag.h"
93 
94 /* Type Definitions */
95 
96 /* Named Constants */
97 
98 /* Variable Declarations */
99 
100 /* Variable Definitions */
101 
102 /* Function Definitions */
103 void quadrotorDrag(const real_T uin[6], const DragParameters parameter, real_T
104  dt, real_T y[6])
105 {
106  int32_T i;
107  real_T absoluteVelocity;
108  real_T absoluteAngularVelocity;
109 
110  /* initialize vectors */
111  for (i = 0; i < 6; i++) {
112  y[i] = 0.0;
113  }
114 
115  /* Input variables */
116  /* Constants */
117  /* temporarily used vector */
118  absoluteVelocity = sqrt((rt_powd_snf(uin[0], 2.0) + rt_powd_snf(uin[1], 2.0))
119  + rt_powd_snf(uin[2], 2.0));
120  absoluteAngularVelocity = sqrt((rt_powd_snf(uin[3], 2.0) + rt_powd_snf(uin[4],
121  2.0)) + rt_powd_snf(uin[5], 2.0));
122 
123  /* system outputs */
124  /* calculate drag force */
125  y[0] = parameter.C_wxy * absoluteVelocity * uin[0];
126  y[1] = parameter.C_wxy * absoluteVelocity * uin[1];
127  y[2] = parameter.C_wz * absoluteVelocity * uin[2];
128 
129  /* calculate draq torque */
130  y[3] = parameter.C_mxy * absoluteAngularVelocity * uin[3];
131  y[4] = parameter.C_mxy * absoluteAngularVelocity * uin[4];
132  y[5] = parameter.C_mz * absoluteAngularVelocity * uin[5];
133 }
134 
135 /* End of code generation (quadrotorDrag.c) */
136 
137 inline void QuadrotorAerodynamics::f(const double uin[10], double dt, double y[14]) const
138 {
139  quadrotorDrag(uin, drag_model_->parameters_, dt, y);
140 }
141 
143 {
144  // get model parameters
145  if (!param.getParam("C_wxy", drag_model_->parameters_.C_wxy)) return false;
146  if (!param.getParam("C_wz", drag_model_->parameters_.C_wz)) return false;
147  if (!param.getParam("C_mxy", drag_model_->parameters_.C_mxy)) return false;
148  if (!param.getParam("C_mz", drag_model_->parameters_.C_mz)) return false;
149 
150 #ifndef NDEBUG
151  std::cout << "Loaded the following quadrotor drag model parameters from namespace " << param.getNamespace() << ":" << std::endl;
152  std::cout << "C_wxy = " << drag_model_->parameters_.C_wxy << std::endl;
153  std::cout << "C_wz = " << drag_model_->parameters_.C_wz << std::endl;
154  std::cout << "C_mxy = " << drag_model_->parameters_.C_mxy << std::endl;
155  std::cout << "C_mz = " << drag_model_->parameters_.C_mz << std::endl;
156 #endif
157 
158  reset();
159  return true;
160 }
161 
163 {
164  boost::mutex::scoped_lock lock(mutex_);
165  drag_model_->u.assign(0.0);
166  drag_model_->y.assign(0.0);
167 
168  twist_ = geometry_msgs::Twist();
169  wind_ = geometry_msgs::Vector3();
170  wrench_ = geometry_msgs::Wrench();
171 }
172 
173 void QuadrotorAerodynamics::setOrientation(const geometry_msgs::Quaternion& orientation)
174 {
175  boost::mutex::scoped_lock lock(mutex_);
176  orientation_ = orientation;
177 }
178 
179 void QuadrotorAerodynamics::setTwist(const geometry_msgs::Twist& twist)
180 {
181  boost::mutex::scoped_lock lock(mutex_);
182  twist_ = twist;
183 }
184 
185 void QuadrotorAerodynamics::setBodyTwist(const geometry_msgs::Twist& body_twist)
186 {
187  boost::mutex::scoped_lock lock(mutex_);
188  Eigen::Quaterniond orientation(orientation_.w, orientation_.x, orientation_.y, orientation_.z);
189  Eigen::Matrix<double,3,3> inverse_rotation_matrix(orientation.inverse().toRotationMatrix());
190 
191  Eigen::Vector3d body_linear(body_twist.linear.x, body_twist.linear.y, body_twist.linear.z);
192  Eigen::Vector3d world_linear(inverse_rotation_matrix * body_linear);
193  twist_.linear.x = world_linear.x();
194  twist_.linear.y = world_linear.y();
195  twist_.linear.z = world_linear.z();
196 
197  Eigen::Vector3d body_angular(body_twist.angular.x, body_twist.angular.y, body_twist.angular.z);
198  Eigen::Vector3d world_angular(inverse_rotation_matrix * body_angular);
199  twist_.angular.x = world_angular.x();
200  twist_.angular.y = world_angular.y();
201  twist_.angular.z = world_angular.z();
202 }
203 
204 void QuadrotorAerodynamics::setWind(const geometry_msgs::Vector3& wind)
205 {
206  boost::mutex::scoped_lock lock(mutex_);
207  wind_ = wind;
208 }
209 
211 {
212  if (dt <= 0.0) return;
213  boost::mutex::scoped_lock lock(mutex_);
214 
215  // fill input vector u for drag model
216  drag_model_->u[0] = (twist_.linear.x - wind_.x);
217  drag_model_->u[1] = -(twist_.linear.y - wind_.y);
218  drag_model_->u[2] = -(twist_.linear.z - wind_.z);
219  drag_model_->u[3] = twist_.angular.x;
220  drag_model_->u[4] = -twist_.angular.y;
221  drag_model_->u[5] = -twist_.angular.z;
222 
223  // We limit the input velocities to +-100. Required for numeric stability in case of collisions,
224  // where velocities returned by Gazebo can be very high.
225  limit(drag_model_->u, -100.0, 100.0);
226 
227  // convert input to body coordinates
228  Eigen::Quaterniond orientation(orientation_.w, orientation_.x, orientation_.y, orientation_.z);
229  Eigen::Matrix<double,3,3> rotation_matrix(orientation.toRotationMatrix());
230  Eigen::Map<Eigen::Vector3d> linear(&(drag_model_->u[0]));
231  Eigen::Map<Eigen::Vector3d> angular(&(drag_model_->u[3]));
232  linear = rotation_matrix * linear;
233  angular = rotation_matrix * angular;
234 
235  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.twist: " << PrintVector<double>(drag_model_->u.begin(), drag_model_->u.begin() + 6));
236  checknan(drag_model_->u, "drag model input");
237 
238  // update drag model
239  f(drag_model_->u.data(), dt, drag_model_->y.data());
240 
241  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.force: " << PrintVector<double>(drag_model_->y.begin() + 0, drag_model_->y.begin() + 3));
242  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.torque: " << PrintVector<double>(drag_model_->y.begin() + 3, drag_model_->y.begin() + 6));
243  checknan(drag_model_->y, "drag model output");
244 
245  // drag_model_ gives us inverted vectors!
246  wrench_.force.x = -( drag_model_->y[0]);
247  wrench_.force.y = -(-drag_model_->y[1]);
248  wrench_.force.z = -(-drag_model_->y[2]);
249  wrench_.torque.x = -( drag_model_->y[3]);
250  wrench_.torque.y = -(-drag_model_->y[4]);
251  wrench_.torque.z = -(-drag_model_->y[5]);
252 }
253 
254 } // namespace hector_quadrotor_model
#define ROS_DEBUG_STREAM_NAMED(name, args)
void setWind(const geometry_msgs::Vector3 &wind)
f
void f(const double uin[6], double dt, double y[6]) const
void quadrotorDrag(const real_T uin[6], const DragParameters parameter, real_T dt, real_T y[6])
void setOrientation(const geometry_msgs::Quaternion &orientation)
void setTwist(const geometry_msgs::Twist &twist)
uint32_t int32_T
double real_T
static real_T rt_powd_snf(real_T u0, real_T u1)
bool configure(const ros::NodeHandle &param=ros::NodeHandle("~"))
const std::string & getNamespace() const
void limit(T &value, const T &min, const T &max)
Definition: helpers.h:70
static void checknan(T &value, const std::string &text="")
Definition: helpers.h:85
bool getParam(const std::string &key, std::string &s) const
void setBodyTwist(const geometry_msgs::Twist &twist)


hector_quadrotor_model
Author(s): Johannes Meyer , Alexander Sendobry
autogenerated on Mon Jun 10 2019 13:36:56