@@ -110,13 +110,15 @@ using namespace systems;
110
110
namespace turning_direction {
111
111
static const int kCcw = 1 ;
112
112
static const int kCw = -1 ;
113
+ static const int kBidirectional = 1 ;
113
114
} // namespace turning_direction
114
115
115
116
// / \brief Type of input command to motor.
116
117
enum class MotorType {
117
118
kVelocity ,
118
119
kPosition ,
119
- kForce
120
+ kForce ,
121
+ kForcePolynomial
120
122
};
121
123
122
124
class gz ::sim::systems::MulticopterMotorModelPrivate
@@ -218,6 +220,10 @@ class gz::sim::systems::MulticopterMotorModelPrivate
218
220
// / \brief Mutex to protect recvdActuatorsMsg.
219
221
public: std::mutex recvdActuatorsMsgMutex;
220
222
223
+ // / \brief Polynomial for RPM to Thrust conversion - admits 5 degrees.
224
+ public: std::vector<double > TorquePolynomial = {0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 };
225
+ public: std::vector<double > ThrustPolynomial = {0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 };
226
+
221
227
// / \brief Gazebo communication node.
222
228
public: transport::Node node;
223
229
};
@@ -308,8 +314,10 @@ void MulticopterMotorModel::Configure(const Entity &_entity,
308
314
this ->dataPtr ->turningDirection = turning_direction::kCw ;
309
315
else if (turningDirection == " ccw" )
310
316
this ->dataPtr ->turningDirection = turning_direction::kCcw ;
317
+ else if (turningDirection == " bidirectional" )
318
+ this ->dataPtr ->turningDirection = turning_direction::kBidirectional ;
311
319
else
312
- gzerr << " Please only use 'cw' or 'ccw ' as turningDirection.\n " ;
320
+ gzerr << " Please only use 'cw', 'ccw', or 'bidirectional ' as turningDirection.\n " ;
313
321
}
314
322
else
315
323
{
@@ -331,10 +339,58 @@ void MulticopterMotorModel::Configure(const Entity &_entity,
331
339
this ->dataPtr ->motorType = MotorType::kForce ;
332
340
gzerr << " motorType 'force' not supported" << std::endl;
333
341
}
342
+ else if (motorType == " force_polynomial" )
343
+ {
344
+ this ->dataPtr ->motorType = MotorType::kForcePolynomial ;
345
+
346
+ if (sdfClone->HasElement (" a0ThrustConstant" ) &&
347
+ sdfClone->HasElement (" a1ThrustConstant" ) &&
348
+ sdfClone->HasElement (" a2ThrustConstant" ) &&
349
+ sdfClone->HasElement (" a3ThrustConstant" ) &&
350
+ sdfClone->HasElement (" a0TorqueConstant" ) &&
351
+ sdfClone->HasElement (" a1TorqueConstant" ) &&
352
+ sdfClone->HasElement (" a2TorqueConstant" ) &&
353
+ sdfClone->HasElement (" a3TorqueConstant" ))
354
+ {
355
+ // Add polynomial coefficients
356
+ if (this ->dataPtr ->jointName != " " ) {
357
+ dataPtr->parentLinkName = _ecm.Component <components::ParentLinkName>(dataPtr->jointEntity )->Data ();
358
+ dataPtr->parentLinkEntity = dataPtr->model .LinkByName (_ecm, dataPtr->parentLinkName );
359
+ }
360
+
361
+ auto a0Thrust = sdfClone->Get <double >(" a0ThrustConstant" );
362
+ auto a1Thrust = sdfClone->Get <double >(" a1ThrustConstant" );
363
+ auto a2Thrust = sdfClone->Get <double >(" a2ThrustConstant" );
364
+ auto a3Thrust = sdfClone->Get <double >(" a3ThrustConstant" );
365
+
366
+ this ->dataPtr ->ThrustPolynomial = {a0Thrust, a1Thrust, a2Thrust, a3Thrust};
367
+
368
+ auto a0Torque = sdfClone->Get <double >(" a0TorqueConstant" );
369
+ auto a1Torque = sdfClone->Get <double >(" a1TorqueConstant" );
370
+ auto a2Torque = sdfClone->Get <double >(" a2TorqueConstant" );
371
+ auto a3Torque = sdfClone->Get <double >(" a3TorqueConstant" );
372
+
373
+ this ->dataPtr ->TorquePolynomial = {a0Torque, a1Torque, a2Torque, a3Torque};
374
+ }
375
+ else
376
+ {
377
+ gzerr << " Please specify the thrust and torque polynomial coefficients.\n " ;
378
+ }
379
+
380
+ // Check for optional higher order coefficients
381
+ if (auto a4Thrust = sdfClone->GetElement (" a4ThrustConstant" ))
382
+ this ->dataPtr ->ThrustPolynomial .push_back (a4Thrust->Get <double >());
383
+ if (auto a5Thrust = sdfClone->GetElement (" a5ThrustConstant" ))
384
+ this ->dataPtr ->ThrustPolynomial .push_back (a5Thrust->Get <double >());
385
+ if (auto a4Torque = sdfClone->GetElement (" a4TorqueConstant" ))
386
+ this ->dataPtr ->TorquePolynomial .push_back (a4Torque->Get <double >());
387
+ if (auto a5Torque = sdfClone->GetElement (" a5TorqueConstant" ))
388
+ this ->dataPtr ->TorquePolynomial .push_back (a5Torque->Get <double >());
389
+ }
334
390
else
335
391
{
336
- gzerr << " Please only use 'velocity', 'position' or "
337
- " 'force' as motorType.\n " ;
392
+ gzerr << " Please only use 'velocity', 'position', "
393
+ " 'force' or 'force_polynomial' as motorType.\n " ;
338
394
}
339
395
}
340
396
else
@@ -399,8 +455,8 @@ void MulticopterMotorModel::PreUpdate(const UpdateInfo &_info,
399
455
if (_info.dt < std::chrono::steady_clock::duration::zero ())
400
456
{
401
457
gzwarn << " Detected jump back in time ["
402
- << std::chrono::duration_cast<std::chrono::seconds >(_info.dt ).count ()
403
- << " s]. System may not work properly." << std::endl;
458
+ << std::chrono::duration< double >(_info.dt ).count ()
459
+ << " s]. System may not work properly." << std::endl;
404
460
}
405
461
406
462
// If the joint or links haven't been identified yet, look for them
@@ -411,7 +467,8 @@ void MulticopterMotorModel::PreUpdate(const UpdateInfo &_info,
411
467
412
468
const auto parentLinkName = _ecm.Component <components::ParentLinkName>(
413
469
this ->dataPtr ->jointEntity );
414
- this ->dataPtr ->parentLinkName = parentLinkName->Data ();
470
+ if (parentLinkName)
471
+ this ->dataPtr ->parentLinkName = parentLinkName->Data ();
415
472
}
416
473
417
474
if (this ->dataPtr ->linkEntity == kNullEntity )
@@ -523,15 +580,16 @@ void MulticopterMotorModelPrivate::UpdateForcesAndMoments(
523
580
524
581
if (msg.has_value ())
525
582
{
526
- if (this ->actuatorNumber > msg->velocity_size () - 1 )
583
+ if (this ->actuatorNumber > msg->velocity_size () - 1 ||
584
+ this ->actuatorNumber > msg->normalized_size () - 1 )
527
585
{
528
586
gzerr << " You tried to access index " << this ->actuatorNumber
529
- << " of the Actuator velocity array which is of size "
530
- << msg->velocity_size () << std::endl;
587
+ << " of the Actuator array which is of size "
588
+ << std::max ( msg->velocity_size (), msg-> normalized_size () ) << std::endl;
531
589
return ;
532
590
}
533
591
534
- if (this ->motorType == MotorType::kVelocity )
592
+ if (this ->motorType == MotorType::kVelocity || this -> motorType == MotorType:: kForcePolynomial )
535
593
{
536
594
this ->refMotorInput = std::min (
537
595
static_cast <double >(msg->velocity (this ->actuatorNumber )),
@@ -558,6 +616,32 @@ void MulticopterMotorModelPrivate::UpdateForcesAndMoments(
558
616
// joint_->SetForce(0, this->refMotorInput);
559
617
break ;
560
618
}
619
+ case (MotorType::kForcePolynomial ):
620
+ {
621
+ sim::Link link (this ->linkEntity );
622
+ const auto worldPose = link .WorldPose (_ecm);
623
+ using Vector3 = math::Vector3d;
624
+
625
+ // Compute thrust
626
+ double thrust = 0.0 ;
627
+ for (unsigned int i = 0 ; i < this ->ThrustPolynomial .size (); i++) {
628
+ thrust += this ->ThrustPolynomial [i] * std::pow (this ->refMotorInput , i);
629
+ }
630
+ link .AddWorldForce (_ecm, worldPose->Rot ().RotateVector (Vector3 (0 , 0 , thrust)));
631
+
632
+ // Compute torques
633
+ double torque = 0.0 ;
634
+ for (unsigned int i = 0 ; i < this ->TorquePolynomial .size (); i++) {
635
+ torque += this ->TorquePolynomial [i] * std::pow (this ->refMotorInput , i);
636
+ }
637
+ link .AddWorldForce (_ecm, worldPose->Rot ().RotateVector (Vector3 (0 , 0 , torque)));
638
+
639
+ // Set joint velocities
640
+ const auto jointVelCmd = _ecm.Component <components::JointVelocityCmd>(
641
+ this ->jointEntity );
642
+ *jointVelCmd = components::JointVelocityCmd ({this ->refMotorInput / this ->rotorVelocitySlowdownSim });
643
+ break ;
644
+ }
561
645
default : // MotorType::kVelocity
562
646
{
563
647
const auto jointVelocity = _ecm.Component <components::JointVelocity>(
@@ -698,7 +782,3 @@ GZ_ADD_PLUGIN(MulticopterMotorModel,
698
782
699
783
GZ_ADD_PLUGIN_ALIAS(MulticopterMotorModel,
700
784
" gz::sim::systems::MulticopterMotorModel" )
701
-
702
- // TODO(CH3): Deprecated, remove on version 8
703
- GZ_ADD_PLUGIN_ALIAS(MulticopterMotorModel,
704
- " ignition::gazebo::systems::MulticopterMotorModel" )
0 commit comments