3939#include < sdf/Root.hh>
4040#include < sdf/World.hh>
4141
42+ #include " ignition/gazebo/components/BatteryPowerLoad.hh"
4243#include " ignition/gazebo/components/BatterySoC.hh"
4344#include " ignition/gazebo/components/Joint.hh"
4445#include " ignition/gazebo/components/JointForceCmd.hh"
@@ -78,9 +79,21 @@ class ignition::gazebo::systems::LinearBatteryPluginPrivate
7879 const char *_data, const size_t _size,
7980 const ignition::transport::MessageInfo &_info);
8081
82+ // / \brief Callback connected to additional topics that can stop battery
83+ // / draining.
84+ // / \param[in] _data Message data.
85+ // / \param[in] _size Message data size.
86+ // / \param[in] _info Information about the message.
87+ public: void OnBatteryStopDrainingMsg (
88+ const char *_data, const size_t _size,
89+ const ignition::transport::MessageInfo &_info);
90+
8191 // / \brief Name of model, only used for printing warning when battery drains.
8292 public: std::string modelName;
8393
94+ // / \brief Name that identifies a battery.
95+ public: std::string batteryName;
96+
8497 // / \brief Pointer to battery contained in link.
8598 public: common::BatteryPtr battery;
8699
@@ -145,7 +158,7 @@ class ignition::gazebo::systems::LinearBatteryPluginPrivate
145158 public: std::chrono::steady_clock::duration stepSize;
146159
147160 // / \brief Flag on whether the battery should start draining
148- public: bool startDraining = true ;
161+ public: bool startDraining = false ;
149162
150163 // / \brief The start time when battery starts draining in seconds
151164 public: int drainStartTime = -1 ;
@@ -163,8 +176,8 @@ class ignition::gazebo::systems::LinearBatteryPluginPrivate
163176 // / \brief Battery state of charge message publisher
164177 public: transport::Node::Publisher statePub;
165178
166- // / \brief Whether a topic has received any battery-draining command.
167- public: bool startDrainingFromTopics = false ;
179+ // / \brief Initial power load set trough config
180+ public: double initialPowerLoad = 0.0 ;
168181};
169182
170183// ///////////////////////////////////////////////
@@ -262,21 +275,18 @@ void LinearBatteryPlugin::Configure(const Entity &_entity,
262275
263276 if (_sdf->HasElement (" battery_name" ) && _sdf->HasElement (" voltage" ))
264277 {
265- auto batteryName = _sdf->Get <std::string>(" battery_name" );
278+ this -> dataPtr -> batteryName = _sdf->Get <std::string>(" battery_name" );
266279 auto initVoltage = _sdf->Get <double >(" voltage" );
267280
268- // Create battery entity and component
281+ // Create battery entity and some components
269282 this ->dataPtr ->batteryEntity = _ecm.CreateEntity ();
270- // Initialize with initial voltage
271- _ecm.CreateComponent (this ->dataPtr ->batteryEntity ,
272- components::BatterySoC (this ->dataPtr ->soc ));
273283 _ecm.CreateComponent (this ->dataPtr ->batteryEntity , components::Name (
274- batteryName));
284+ this -> dataPtr -> batteryName ));
275285 _ecm.SetParentEntity (this ->dataPtr ->batteryEntity , _entity);
276286
277287 // Create actual battery and assign update function
278- this ->dataPtr ->battery = std::make_shared<common::Battery>(batteryName,
279- initVoltage);
288+ this ->dataPtr ->battery = std::make_shared<common::Battery>(
289+ this -> dataPtr -> batteryName , initVoltage);
280290 this ->dataPtr ->battery ->Init ();
281291 this ->dataPtr ->battery ->SetUpdateFunc (
282292 std::bind (&LinearBatteryPlugin::OnUpdateVoltage, this ,
@@ -339,10 +349,10 @@ void LinearBatteryPlugin::Configure(const Entity &_entity,
339349 // Consumer-specific
340350 if (_sdf->HasElement (" power_load" ))
341351 {
342- auto powerLoad = _sdf->Get <double >(" power_load" );
352+ this -> dataPtr -> initialPowerLoad = _sdf->Get <double >(" power_load" );
343353 this ->dataPtr ->consumerId = this ->dataPtr ->battery ->AddConsumer ();
344354 bool success = this ->dataPtr ->battery ->SetPowerLoad (
345- this ->dataPtr ->consumerId , powerLoad );
355+ this ->dataPtr ->consumerId , this -> dataPtr -> initialPowerLoad );
346356 if (!success)
347357 ignerr << " Failed to set consumer power load." << std::endl;
348358 }
@@ -352,6 +362,9 @@ void LinearBatteryPlugin::Configure(const Entity &_entity,
352362 << " in LinearBatteryPlugin SDF" << std::endl;
353363 }
354364
365+ if (_sdf->HasElement (" start_draining" ))
366+ this ->dataPtr ->startDraining = _sdf->Get <bool >(" start_draining" );
367+
355368 // Subscribe to power draining topics, if any.
356369 if (_sdf->HasElement (" power_draining_topic" ))
357370 {
@@ -369,12 +382,33 @@ void LinearBatteryPlugin::Configure(const Entity &_entity,
369382 }
370383 }
371384
385+ // Subscribe to stop power draining topics, if any.
386+ if (_sdf->HasElement (" stop_power_draining_topic" ))
387+ {
388+ sdf::ElementConstPtr sdfElem =
389+ _sdf->FindElement (" stop_power_draining_topic" );
390+ while (sdfElem)
391+ {
392+ const auto &topic = sdfElem->Get <std::string>();
393+ this ->dataPtr ->node .SubscribeRaw (topic,
394+ std::bind (&LinearBatteryPluginPrivate::OnBatteryStopDrainingMsg,
395+ this ->dataPtr .get (), std::placeholders::_1, std::placeholders::_2,
396+ std::placeholders::_3));
397+ ignmsg << " LinearBatteryPlugin subscribes to stop power draining topic ["
398+ << topic << " ]." << std::endl;
399+ sdfElem = sdfElem->GetNextElement (" power_draining_topic" );
400+ }
401+ }
402+
372403 ignmsg << " LinearBatteryPlugin configured. Battery name: "
373404 << this ->dataPtr ->battery ->Name () << std::endl;
374405 igndbg << " Battery initial voltage: " << this ->dataPtr ->battery ->InitVoltage ()
375406 << std::endl;
376407
377408 this ->dataPtr ->soc = this ->dataPtr ->q / this ->dataPtr ->c ;
409+ // Initialize battery with initial calculated state of charge
410+ _ecm.CreateComponent (this ->dataPtr ->batteryEntity ,
411+ components::BatterySoC (this ->dataPtr ->soc ));
378412
379413 // Setup battery state topic
380414 std::string stateTopic{" /model/" + this ->dataPtr ->model .Name (_ecm) +
@@ -400,7 +434,7 @@ void LinearBatteryPluginPrivate::Reset()
400434 this ->iraw = 0.0 ;
401435 this ->ismooth = 0.0 ;
402436 this ->q = this ->q0 ;
403- this ->startDrainingFromTopics = false ;
437+ this ->startDraining = false ;
404438}
405439
406440// ///////////////////////////////////////////////
@@ -429,7 +463,14 @@ void LinearBatteryPluginPrivate::OnDisableRecharge(
429463void LinearBatteryPluginPrivate::OnBatteryDrainingMsg (
430464 const char *, const size_t , const ignition::transport::MessageInfo &)
431465{
432- this ->startDrainingFromTopics = true ;
466+ this ->startDraining = true ;
467+ }
468+
469+ // ////////////////////////////////////////////////
470+ void LinearBatteryPluginPrivate::OnBatteryStopDrainingMsg (
471+ const char *, const size_t , const ignition::transport::MessageInfo &)
472+ {
473+ this ->startDraining = false ;
433474}
434475
435476// ////////////////////////////////////////////////
@@ -439,10 +480,26 @@ void LinearBatteryPlugin::PreUpdate(
439480{
440481 IGN_PROFILE (" LinearBatteryPlugin::PreUpdate" );
441482
442- // \todo(anyone) Add in the ability to stop the battery from draining
443- // after it has been started by a topic. See this comment:
444- // https://github.com/ignitionrobotics/ign-gazebo/pull/1255#discussion_r770223092
445- this ->dataPtr ->startDraining = this ->dataPtr ->startDrainingFromTopics ;
483+ // Recalculate the total power load among consumers
484+ double total_power_load = this ->dataPtr ->initialPowerLoad ;
485+ _ecm.Each <components::BatteryPowerLoad>(
486+ [&](const Entity & /* _entity*/ ,
487+ const components::BatteryPowerLoad *_batteryPowerLoadInfo)->bool
488+ {
489+ if (_batteryPowerLoadInfo->Data ().batteryId ==
490+ this ->dataPtr ->batteryEntity )
491+ {
492+ total_power_load = total_power_load +
493+ _batteryPowerLoadInfo->Data ().batteryPowerLoad ;
494+ }
495+ return true ;
496+ });
497+
498+ bool success = this ->dataPtr ->battery ->SetPowerLoad (
499+ this ->dataPtr ->consumerId , total_power_load);
500+ if (!success)
501+ ignerr << " Failed to set consumer power load." << std::endl;
502+
446503 // Start draining the battery if the robot has started moving
447504 if (!this ->dataPtr ->startDraining )
448505 {
0 commit comments