Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <algorithm>
00019 #include <string>
00020
00021 #include "gazebo/common/Assert.hh"
00022 #include "gazebo/physics/physics.hh"
00023 #include "gazebo/sensors/SensorManager.hh"
00024 #include "gazebo/transport/transport.hh"
00025 #include "gazebo/msgs/msgs.hh"
00026 #include "liftdrag_plugin/liftdrag_plugin.h"
00027
00028 using namespace gazebo;
00029
00030 GZ_REGISTER_MODEL_PLUGIN(LiftDragPlugin)
00031
00032
00033 LiftDragPlugin::LiftDragPlugin() : cla(1.0), cda(0.01), cma(0.01), rho(1.2041)
00034 {
00035 this->cp = ignition::math::Vector3d (0, 0, 0);
00036 this->forward = ignition::math::Vector3d (1, 0, 0);
00037 this->upward = ignition::math::Vector3d (0, 0, 1);
00038 this->area = 1.0;
00039 this->alpha0 = 0.0;
00040 this->alpha = 0.0;
00041 this->sweep = 0.0;
00042 this->velocityStall = 0.0;
00043
00044
00045 this->alphaStall = 0.5*M_PI;
00046 this->claStall = 0.0;
00047
00048 this->radialSymmetry = false;
00049
00051 this->cdaStall = 1.0;
00052 this->cmaStall = 0.0;
00053
00055 this->controlJointRadToCL = 4.0;
00056 }
00057
00059 LiftDragPlugin::~LiftDragPlugin()
00060 {
00061 }
00062
00064 void LiftDragPlugin::Load(physics::ModelPtr _model,
00065 sdf::ElementPtr _sdf)
00066 {
00067 GZ_ASSERT(_model, "LiftDragPlugin _model pointer is NULL");
00068 GZ_ASSERT(_sdf, "LiftDragPlugin _sdf pointer is NULL");
00069 this->model = _model;
00070 this->sdf = _sdf;
00071
00072 this->world = this->model->GetWorld();
00073 GZ_ASSERT(this->world, "LiftDragPlugin world pointer is NULL");
00074
00075 this->physics = this->world->Physics();
00076 GZ_ASSERT(this->physics, "LiftDragPlugin physics pointer is NULL");
00077
00078 GZ_ASSERT(_sdf, "LiftDragPlugin _sdf pointer is NULL");
00079
00080 if (_sdf->HasElement("radial_symmetry"))
00081 this->radialSymmetry = _sdf->Get<bool>("radial_symmetry");
00082
00083 if (_sdf->HasElement("a0"))
00084 this->alpha0 = _sdf->Get<double>("a0");
00085
00086 if (_sdf->HasElement("cla"))
00087 this->cla = _sdf->Get<double>("cla");
00088
00089 if (_sdf->HasElement("cda"))
00090 this->cda = _sdf->Get<double>("cda");
00091
00092 if (_sdf->HasElement("cma"))
00093 this->cma = _sdf->Get<double>("cma");
00094
00095 if (_sdf->HasElement("alpha_stall"))
00096 this->alphaStall = _sdf->Get<double>("alpha_stall");
00097
00098 if (_sdf->HasElement("cla_stall"))
00099 this->claStall = _sdf->Get<double>("cla_stall");
00100
00101 if (_sdf->HasElement("cda_stall"))
00102 this->cdaStall = _sdf->Get<double>("cda_stall");
00103
00104 if (_sdf->HasElement("cma_stall"))
00105 this->cmaStall = _sdf->Get<double>("cma_stall");
00106
00107 if (_sdf->HasElement("cp"))
00108 this->cp = _sdf->Get<ignition::math::Vector3d >("cp");
00109
00110
00111 if (_sdf->HasElement("forward"))
00112 this->forward = _sdf->Get<ignition::math::Vector3d >("forward");
00113 this->forward.Normalize();
00114
00115
00116 if (_sdf->HasElement("upward"))
00117 this->upward = _sdf->Get<ignition::math::Vector3d >("upward");
00118 this->upward.Normalize();
00119
00120 if (_sdf->HasElement("area"))
00121 this->area = _sdf->Get<double>("area");
00122
00123 if (_sdf->HasElement("air_density"))
00124 this->rho = _sdf->Get<double>("air_density");
00125
00126 if (_sdf->HasElement("link_name"))
00127 {
00128 sdf::ElementPtr elem = _sdf->GetElement("link_name");
00129
00130 std::string linkName = elem->Get<std::string>();
00131 this->link = this->model->GetLink(linkName);
00132
00133
00134 if (!this->link)
00135 {
00136 gzerr << "Link with name[" << linkName << "] not found. "
00137 << "The LiftDragPlugin will not generate forces\n";
00138 }
00139 else
00140 {
00141 this->updateConnection = event::Events::ConnectWorldUpdateBegin(
00142 boost::bind(&LiftDragPlugin::OnUpdate, this));
00143 }
00144 }
00145
00146 if (_sdf->HasElement("control_joint_name"))
00147 {
00148 std::string controlJointName = _sdf->Get<std::string>("control_joint_name");
00149 this->controlJoint = this->model->GetJoint(controlJointName);
00150 if (!this->controlJoint)
00151 {
00152 gzerr << "Joint with name[" << controlJointName << "] does not exist.\n";
00153 }
00154 }
00155
00156 if (_sdf->HasElement("control_joint_rad_to_cl"))
00157 this->controlJointRadToCL = _sdf->Get<double>("control_joint_rad_to_cl");
00158 }
00159
00161 void LiftDragPlugin::OnUpdate()
00162 {
00163 GZ_ASSERT(this->link, "Link was NULL");
00164
00165 ignition::math::Vector3d vel = this->link->WorldLinearVel(this->cp);
00166 ignition::math::Vector3d velI = vel;
00167 velI.Normalize();
00168
00169
00170
00171
00172
00173
00174 if (vel.Length() <= 0.01)
00175 return;
00176
00177
00178 ignition::math::Pose3d pose = this->link->WorldPose();
00179
00180
00181 ignition::math::Vector3d forwardI = pose.Rot().RotateVector(this->forward);
00182
00183 ignition::math::Vector3d upwardI;
00184 if (this->radialSymmetry)
00185 {
00186
00187
00188 ignition::math::Vector3d tmp = forwardI.Cross(velI);
00189 upwardI = forwardI.Cross(tmp).Normalize();
00190 }
00191 else
00192 {
00193 upwardI = pose.Rot().RotateVector(this->upward);
00194 }
00195
00196
00197 ignition::math::Vector3d spanwiseI = forwardI.Cross(upwardI).Normalize();
00198
00199 const double minRatio = -1.0;
00200 const double maxRatio = 1.0;
00201
00202 double sinSweepAngle = ignition::math::clamp(
00203 spanwiseI.Dot(velI), minRatio, maxRatio);
00204
00205
00206 double cosSweepAngle = 1.0 - sinSweepAngle * sinSweepAngle;
00207 this->sweep = asin(sinSweepAngle);
00208
00209
00210 while (fabs(this->sweep) > 0.5 * M_PI)
00211 this->sweep = this->sweep > 0 ? this->sweep - M_PI
00212 : this->sweep + M_PI;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 ignition::math::Vector3d velInLDPlane = vel - vel.Dot(spanwiseI)*velI;
00224
00225
00226 ignition::math::Vector3d dragDirection = -velInLDPlane;
00227 dragDirection.Normalize();
00228
00229
00230 ignition::math::Vector3d liftI = spanwiseI.Cross(velInLDPlane);
00231 liftI.Normalize();
00232
00233
00234 ignition::math::Vector3d momentDirection = spanwiseI;
00235
00236
00237
00238
00239
00240
00241 double cosAlpha = ignition::math::clamp(liftI.Dot(upwardI), minRatio, maxRatio);
00242
00243
00244
00245
00246
00247 if (liftI.Dot(forwardI) >= 0.0)
00248 this->alpha = this->alpha0 + acos(cosAlpha);
00249 else
00250 this->alpha = this->alpha0 - acos(cosAlpha);
00251
00252
00253 while (fabs(this->alpha) > 0.5 * M_PI)
00254 this->alpha = this->alpha > 0 ? this->alpha - M_PI
00255 : this->alpha + M_PI;
00256
00257
00258 double speedInLDPlane = velInLDPlane.Length();
00259 double q = 0.5 * this->rho * speedInLDPlane * speedInLDPlane;
00260
00261
00262 double cl;
00263 if (this->alpha > this->alphaStall)
00264 {
00265 cl = (this->cla * this->alphaStall +
00266 this->claStall * (this->alpha - this->alphaStall))
00267 * cosSweepAngle;
00268
00269 cl = std::max(0.0, cl);
00270 }
00271 else if (this->alpha < -this->alphaStall)
00272 {
00273 cl = (-this->cla * this->alphaStall +
00274 this->claStall * (this->alpha + this->alphaStall))
00275 * cosSweepAngle;
00276
00277 cl = std::min(0.0, cl);
00278 }
00279 else
00280 cl = this->cla * this->alpha * cosSweepAngle;
00281
00282
00283 if (this->controlJoint)
00284 {
00285 double controlAngle = this->controlJoint->Position(0);
00286 cl = cl + this->controlJointRadToCL * controlAngle;
00288 }
00289
00290
00291 ignition::math::Vector3d lift = cl * q * this->area * liftI;
00292
00293
00294 double cd;
00295 if (this->alpha > this->alphaStall)
00296 {
00297 cd = (this->cda * this->alphaStall +
00298 this->cdaStall * (this->alpha - this->alphaStall))
00299 * cosSweepAngle;
00300 }
00301 else if (this->alpha < -this->alphaStall)
00302 {
00303 cd = (-this->cda * this->alphaStall +
00304 this->cdaStall * (this->alpha + this->alphaStall))
00305 * cosSweepAngle;
00306 }
00307 else
00308 cd = (this->cda * this->alpha) * cosSweepAngle;
00309
00310
00311 cd = fabs(cd);
00312
00313
00314 ignition::math::Vector3d drag = cd * q * this->area * dragDirection;
00315
00316
00317 double cm;
00318 if (this->alpha > this->alphaStall)
00319 {
00320 cm = (this->cma * this->alphaStall +
00321 this->cmaStall * (this->alpha - this->alphaStall))
00322 * cosSweepAngle;
00323
00324 cm = std::max(0.0, cm);
00325 }
00326 else if (this->alpha < -this->alphaStall)
00327 {
00328 cm = (-this->cma * this->alphaStall +
00329 this->cmaStall * (this->alpha + this->alphaStall))
00330 * cosSweepAngle;
00331
00332 cm = std::min(0.0, cm);
00333 }
00334 else
00335 cm = this->cma * this->alpha * cosSweepAngle;
00336
00339 cm = 0.0;
00340
00341
00342 ignition::math::Vector3d moment = cm * q * this->area * momentDirection;
00343
00344
00345 ignition::math::Vector3d momentArm = pose.Rot().RotateVector(
00346 this->cp - this->link->GetInertial()->CoG());
00347
00348
00349
00350 ignition::math::Vector3d force = lift + drag;
00351
00352
00353 ignition::math::Vector3d torque = moment;
00354
00355
00356
00357
00358
00359
00360
00361
00362 if (0)
00363 {
00364 gzdbg << "=============================\n";
00365 gzdbg << "sensor: [" << this->GetHandle() << "]\n";
00366 gzdbg << "Link: [" << this->link->GetName()
00367 << "] pose: [" << pose
00368 << "] dynamic pressure: [" << q << "]\n";
00369 gzdbg << "spd: [" << vel.Length()
00370 << "] vel: [" << vel << "]\n";
00371 gzdbg << "LD plane spd: [" << velInLDPlane.Length()
00372 << "] vel : [" << velInLDPlane << "]\n";
00373 gzdbg << "forward (inertial): " << forwardI << "\n";
00374 gzdbg << "upward (inertial): " << upwardI << "\n";
00375 gzdbg << "lift dir (inertial): " << liftI << "\n";
00376 gzdbg << "Span direction (normal to LD plane): " << spanwiseI << "\n";
00377 gzdbg << "sweep: " << this->sweep << "\n";
00378 gzdbg << "alpha: " << this->alpha << "\n";
00379 gzdbg << "lift: " << lift << "\n";
00380 gzdbg << "drag: " << drag << " cd: "
00381 << cd << " cda: " << this->cda << "\n";
00382 gzdbg << "moment: " << moment << "\n";
00383 gzdbg << "cp momentArm: " << momentArm << "\n";
00384 gzdbg << "force: " << force << "\n";
00385 gzdbg << "torque: " << torque << "\n";
00386 }
00387
00388
00389 force.Correct();
00390 this->cp.Correct();
00391 torque.Correct();
00392
00393
00394 this->link->AddForceAtRelativePosition(force, this->cp);
00395 this->link->AddTorque(torque);
00396 }
rotors_gazebo_plugins
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Thu Apr 18 2019 02:43:43