@@ -30,20 +30,18 @@ class GZ_SIM_VISIBLE DoorPlugin
3030 public ISystemPreUpdate
3131{
3232private:
33+ // TODO(luca) make this a parameter of the door manager
34+ static constexpr double PUBLISH_DT = 1.0 ;
3335 rclcpp::Node::SharedPtr _ros_node;
3436 rclcpp::Publisher<DoorState>::SharedPtr _door_state_pub;
3537 rclcpp::Subscription<DoorRequest>::SharedPtr _door_request_sub;
3638
37- std::unordered_set<Entity> _sent_states;
38- bool _send_all_states = false ;
39-
40- // Records which doors were just requested an action, they will respond by always
41- // reporting their latest state regardless of whether there was a change or not.
42- std::unordered_set<Entity> _queried_doors;
43-
4439 // Used to do open loop joint position control
4540 std::unordered_map<Entity, double > _last_cmd_vel;
4641
42+ // Saves the last timestamp a door state was sent
43+ std::unordered_map<Entity, double > _last_state_pub;
44+
4745 bool _first_iteration = true ;
4846
4947 Entity get_joint_entity (const EntityComponentManager& ecm,
@@ -144,12 +142,9 @@ class GZ_SIM_VISIBLE DoorPlugin
144142 }
145143 }
146144
147- void publish_state (const UpdateInfo& info , const std::string& name,
145+ void publish_state (const double t , const std::string& name,
148146 const DoorModeCmp& door_state)
149147 {
150- double t =
151- (std::chrono::duration_cast<std::chrono::nanoseconds>(info.simTime ).
152- count ()) * 1e-9 ;
153148 DoorState msg;
154149 msg.door_name = name;
155150 msg.door_time .sec = t;
@@ -186,22 +181,9 @@ class GZ_SIM_VISIBLE DoorPlugin
186181 " Loading DoorManager" );
187182
188183 // Subscribe to door requests, publish door states
189- auto pub_options = rclcpp::PublisherOptions ();
190- pub_options.event_callbacks .matched_callback =
191- [this ](rclcpp::MatchedInfo& s)
192- {
193- if (s.current_count_change > 0 )
194- {
195- // Trigger a status send for all doors
196- _send_all_states = true ;
197- _sent_states.clear ();
198- gzmsg << " Detected new door subscriber, triggering state publish" <<
199- std::endl;
200- }
201- };
202- const auto pub_qos = rclcpp::QoS (200 ).reliable ();
184+ const auto pub_qos = rclcpp::QoS (100 ).reliable ();
203185 _door_state_pub = _ros_node->create_publisher <DoorState>(
204- " door_states" , pub_qos, pub_options );
186+ " door_states" , pub_qos);
205187
206188 _door_request_sub = _ros_node->create_subscription <DoorRequest>(
207189 " door_requests" , rclcpp::SystemDefaultsQoS (),
@@ -223,7 +205,6 @@ class GZ_SIM_VISIBLE DoorPlugin
223205 DoorModeCmp::OPEN : DoorModeCmp::CLOSE;
224206 ecm.CreateComponent <components::DoorCmd>(entity,
225207 components::DoorCmd (door_command));
226- _queried_doors.insert (entity);
227208 }
228209 else
229210 {
@@ -250,20 +231,37 @@ class GZ_SIM_VISIBLE DoorPlugin
250231 });
251232 }
252233
234+ void initialize_pub_times (EntityComponentManager& ecm)
235+ {
236+ ecm.Each <components::Door>([&](const Entity& e,
237+ const components::Door* door_comp) -> bool
238+ {
239+ if (door_comp->Data ().ros_interface == false )
240+ return true ;
241+ _last_state_pub[e] = ((double ) std::rand ()) /
242+ ((double ) RAND_MAX/PUBLISH_DT);
243+ return true ;
244+ });
245+ }
246+
253247 void PreUpdate (const UpdateInfo& info, EntityComponentManager& ecm) override
254248 {
255249 rclcpp::spin_some (_ros_node);
256250 if (_first_iteration)
257251 {
258252 _first_iteration = false ;
259253 initialize_components (ecm);
254+ initialize_pub_times (ecm);
260255 return ;
261256 }
262257
263258 // Don't update if the simulation is paused
264259 if (info.paused )
265260 return ;
266261
262+ const double t =
263+ (std::chrono::duration_cast<std::chrono::nanoseconds>(info.simTime ).
264+ count ()) * 1e-9 ;
267265 std::unordered_set<Entity> finished_cmds;
268266 // Process commands
269267 ecm.Each <components::Door, components::DoorCmd,
@@ -283,14 +281,12 @@ class GZ_SIM_VISIBLE DoorPlugin
283281 command_door (entity, ecm, door, dt, door_cmd);
284282 // Publish state if there was a change
285283 const auto cur_mode = get_current_mode (entity, ecm, door);
286- if (cur_mode != door_state_comp->Data () ||
287- _queried_doors.find (entity) != _queried_doors.end ())
284+ if (cur_mode != door_state_comp->Data ())
288285 {
289286 last_mode = cur_mode;
290287 if (door_comp->Data ().ros_interface )
291288 {
292- publish_state (info, name, cur_mode);
293- _queried_doors.erase (entity);
289+ publish_state (t, name, cur_mode);
294290 }
295291 }
296292 if (door_cmd == cur_mode)
@@ -301,27 +297,22 @@ class GZ_SIM_VISIBLE DoorPlugin
301297 });
302298
303299 // Publish states
304- if (_send_all_states)
305- {
306- bool keep_sending = false ;
307- ecm.Each <components::Door, components::DoorStateComp,
308- components::Name>([&](const Entity& e,
309- const components::Door* door_comp,
310- const components::DoorStateComp* door_state_comp,
311- const components::Name* name_comp) -> bool
300+ ecm.Each <components::Door, components::DoorStateComp,
301+ components::Name>([&](const Entity& e,
302+ const components::Door* door_comp,
303+ const components::DoorStateComp* door_state_comp,
304+ const components::Name* name_comp) -> bool
305+ {
306+ if (door_comp->Data ().ros_interface == false )
307+ return true ;
308+ auto it = _last_state_pub.find (e);
309+ if (it != _last_state_pub.end () && t - it->second >= PUBLISH_DT)
312310 {
313- if (_sent_states.find (e) != _sent_states.end ())
314- return true ;
315- if (door_comp->Data ().ros_interface == false )
316- return true ;
317- publish_state (info, name_comp->Data (), door_state_comp->Data ());
318- _sent_states.insert (e);
319- // Mark to keep sending but stop doing so for now
320- keep_sending = true ;
321- return false ;
322- });
323- _send_all_states = keep_sending;
324- }
311+ it->second = t;
312+ publish_state (t, name_comp->Data (), door_state_comp->Data ());
313+ }
314+ return true ;
315+ });
325316
326317 for (const auto & entity: finished_cmds)
327318 {
@@ -337,4 +328,3 @@ GZ_ADD_PLUGIN(
337328 DoorPlugin::ISystemPreUpdate)
338329
339330GZ_ADD_PLUGIN_ALIAS(DoorPlugin, " door" )
340-
0 commit comments