00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 #include <hector_quadrotor_model/quadrotor_aerodynamics.h>
00030 #include <hector_quadrotor_model/helpers.h>
00031 
00032 #include <ros/node_handle.h>
00033 #include <boost/array.hpp>
00034 
00035 
00036 
00037 
00038 
00039 
00040 #include <boost/array.hpp>
00041 #include <Eigen/Geometry>
00042 
00043 #include "matlab_helpers.h"
00044 
00045 namespace hector_quadrotor_model {
00046 
00047 struct DragParameters
00048 {
00049     real_T C_wxy;
00050     real_T C_wz;
00051     real_T C_mxy;
00052     real_T C_mz;
00053 
00054     DragParameters()
00055       : C_wxy(0.0)
00056       , C_wz(0.0)
00057       , C_mxy(0.0)
00058       , C_mz(0.0)
00059     {}
00060 };
00061 
00062 
00063 struct QuadrotorAerodynamics::DragModel {
00064   DragParameters parameters_;
00065   boost::array<real_T,6> u;
00066   boost::array<real_T,6> y;
00067 };
00068 
00069 QuadrotorAerodynamics::QuadrotorAerodynamics()
00070 {
00071   
00072   
00073   drag_model_ = new DragModel;
00074 }
00075 
00076 QuadrotorAerodynamics::~QuadrotorAerodynamics()
00077 {
00078   delete drag_model_;
00079 }
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 void quadrotorDrag(const real_T uin[6], const DragParameters parameter, real_T
00104                    dt, real_T y[6])
00105 {
00106   int32_T i;
00107   real_T absoluteVelocity;
00108   real_T absoluteAngularVelocity;
00109 
00110   
00111   for (i = 0; i < 6; i++) {
00112     y[i] = 0.0;
00113   }
00114 
00115   
00116   
00117   
00118   absoluteVelocity = sqrt((rt_powd_snf(uin[0], 2.0) + rt_powd_snf(uin[1], 2.0))
00119     + rt_powd_snf(uin[2], 2.0));
00120   absoluteAngularVelocity = sqrt((rt_powd_snf(uin[3], 2.0) + rt_powd_snf(uin[4],
00121     2.0)) + rt_powd_snf(uin[5], 2.0));
00122 
00123   
00124   
00125   y[0] = parameter.C_wxy * absoluteVelocity * uin[0];
00126   y[1] = parameter.C_wxy * absoluteVelocity * uin[1];
00127   y[2] = parameter.C_wz * absoluteVelocity * uin[2];
00128 
00129   
00130   y[3] = parameter.C_mxy * absoluteAngularVelocity * uin[3];
00131   y[4] = parameter.C_mxy * absoluteAngularVelocity * uin[4];
00132   y[5] = parameter.C_mz * absoluteAngularVelocity * uin[5];
00133 }
00134 
00135 
00136 
00137 inline void QuadrotorAerodynamics::f(const double uin[10], double dt, double y[14]) const
00138 {
00139   quadrotorDrag(uin, drag_model_->parameters_, dt, y);
00140 }
00141 
00142 bool QuadrotorAerodynamics::configure(const ros::NodeHandle ¶m)
00143 {
00144   
00145   if (!param.getParam("C_wxy", drag_model_->parameters_.C_wxy)) return false;
00146   if (!param.getParam("C_wz",  drag_model_->parameters_.C_wz)) return false;
00147   if (!param.getParam("C_mxy", drag_model_->parameters_.C_mxy)) return false;
00148   if (!param.getParam("C_mz",  drag_model_->parameters_.C_mz)) return false;
00149 
00150 #ifndef NDEBUG
00151   std::cout << "Loaded the following quadrotor drag model parameters from namespace " << param.getNamespace() << ":" << std::endl;
00152   std::cout << "C_wxy = " << drag_model_->parameters_.C_wxy << std::endl;
00153   std::cout << "C_wz = "  << drag_model_->parameters_.C_wz << std::endl;
00154   std::cout << "C_mxy = " << drag_model_->parameters_.C_mxy << std::endl;
00155   std::cout << "C_mz = "  << drag_model_->parameters_.C_mz << std::endl;
00156 #endif
00157 
00158   reset();
00159   return true;
00160 }
00161 
00162 void QuadrotorAerodynamics::reset()
00163 {
00164   boost::mutex::scoped_lock lock(mutex_);
00165   drag_model_->u.assign(0.0);
00166   drag_model_->y.assign(0.0);
00167 
00168   twist_ = geometry_msgs::Twist();
00169   wind_ = geometry_msgs::Vector3();
00170   wrench_ = geometry_msgs::Wrench();
00171 }
00172 
00173 void QuadrotorAerodynamics::setOrientation(const geometry_msgs::Quaternion& orientation)
00174 {
00175   boost::mutex::scoped_lock lock(mutex_);
00176   orientation_ = orientation;
00177 }
00178 
00179 void QuadrotorAerodynamics::setTwist(const geometry_msgs::Twist& twist)
00180 {
00181   boost::mutex::scoped_lock lock(mutex_);
00182   twist_ = twist;
00183 }
00184 
00185 void QuadrotorAerodynamics::setBodyTwist(const geometry_msgs::Twist& body_twist)
00186 {
00187   boost::mutex::scoped_lock lock(mutex_);
00188   Eigen::Quaterniond orientation(orientation_.w, orientation_.x, orientation_.y, orientation_.z);
00189   Eigen::Matrix<double,3,3> inverse_rotation_matrix(orientation.inverse().toRotationMatrix());
00190 
00191   Eigen::Vector3d body_linear(body_twist.linear.x, body_twist.linear.y, body_twist.linear.z);
00192   Eigen::Vector3d world_linear(inverse_rotation_matrix * body_linear);
00193   twist_.linear.x = world_linear.x();
00194   twist_.linear.y = world_linear.y();
00195   twist_.linear.z = world_linear.z();
00196 
00197   Eigen::Vector3d body_angular(body_twist.angular.x, body_twist.angular.y, body_twist.angular.z);
00198   Eigen::Vector3d world_angular(inverse_rotation_matrix * body_angular);
00199   twist_.angular.x = world_angular.x();
00200   twist_.angular.y = world_angular.y();
00201   twist_.angular.z = world_angular.z();
00202 }
00203 
00204 void QuadrotorAerodynamics::setWind(const geometry_msgs::Vector3& wind)
00205 {
00206   boost::mutex::scoped_lock lock(mutex_);
00207   wind_ = wind;
00208 }
00209 
00210 void QuadrotorAerodynamics::update(double dt)
00211 {
00212   if (dt <= 0.0) return;
00213   boost::mutex::scoped_lock lock(mutex_);
00214 
00215   
00216   drag_model_->u[0] =  (twist_.linear.x - wind_.x);
00217   drag_model_->u[1] = -(twist_.linear.y - wind_.y);
00218   drag_model_->u[2] = -(twist_.linear.z - wind_.z);
00219   drag_model_->u[3] =  twist_.angular.x;
00220   drag_model_->u[4] = -twist_.angular.y;
00221   drag_model_->u[5] = -twist_.angular.z;
00222 
00223   
00224   
00225   limit(drag_model_->u, -100.0, 100.0);
00226 
00227   
00228   Eigen::Quaterniond orientation(orientation_.w, orientation_.x, orientation_.y, orientation_.z);
00229   Eigen::Matrix<double,3,3> rotation_matrix(orientation.toRotationMatrix());
00230   Eigen::Map<Eigen::Vector3d> linear(&(drag_model_->u[0]));
00231   Eigen::Map<Eigen::Vector3d> angular(&(drag_model_->u[3]));
00232   linear  = rotation_matrix * linear;
00233   angular = rotation_matrix * angular;
00234 
00235   ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.twist:  " << PrintVector<double>(drag_model_->u.begin(), drag_model_->u.begin() + 6));
00236   checknan(drag_model_->u, "drag model input");
00237 
00238   
00239   f(drag_model_->u.data(), dt, drag_model_->y.data());
00240 
00241   ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.force:  " << PrintVector<double>(drag_model_->y.begin() + 0, drag_model_->y.begin() + 3));
00242   ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.torque: " << PrintVector<double>(drag_model_->y.begin() + 3, drag_model_->y.begin() + 6));
00243   checknan(drag_model_->y, "drag model output");
00244 
00245   
00246   wrench_.force.x  = -( drag_model_->y[0]);
00247   wrench_.force.y  = -(-drag_model_->y[1]);
00248   wrench_.force.z  = -(-drag_model_->y[2]);
00249   wrench_.torque.x = -( drag_model_->y[3]);
00250   wrench_.torque.y = -(-drag_model_->y[4]);
00251   wrench_.torque.z = -(-drag_model_->y[5]);
00252 }
00253 
00254 }