From bbbed27023d7205683637e75770d23416aed4fe3 Mon Sep 17 00:00:00 2001
From: Florent Lamiraux <florent@laas.fr>
Date: Mon, 27 Jun 2022 15:47:35 +0000
Subject: [PATCH] [Event] Allow to periodically broadcast event when input
 remains to true.

  This enables us to rebroadcast some events that are not captured.
---
 include/sot/core/event.hh | 22 ++++++++++++++--------
 src/tools/event.cpp       | 21 +++++++++++++++------
 2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/include/sot/core/event.hh b/include/sot/core/event.hh
index 0acb429a..64633611 100644
--- a/include/sot/core/event.hh
+++ b/include/sot/core/event.hh
@@ -45,7 +45,8 @@ class SOT_CORE_DLLAPI Event : public dynamicgraph::Entity {
   Event(const std::string &name)
       : Entity(name), checkSOUT("Event(" + name + ")::output(bool)::check"),
         conditionSIN(NULL, "Event(" + name + ")::input(bool)::condition"),
-        lastVal_(2) // lastVal_ should be different true and false.
+        lastVal_(2), // lastVal_ should be different true and false.
+    timeSinceUp_(0), repeatAfterNIterations_(0)
   {
     checkSOUT.setFunction(boost::bind(&Event::check, this, _1, _2));
     signalRegistration(conditionSIN);
@@ -63,10 +64,12 @@ class SOT_CORE_DLLAPI Event : public dynamicgraph::Entity {
                            *this, &Event::getSignalsByName, docstring));
 
     docstring =
-        "\n"
-        "    Triggers an event only when condition goes from False to True\n";
-    addCommand("setOnlyUp", new command::Setter<Event, bool>(
-                                *this, &Event::setOnlyUp, docstring));
+      "\n"
+      "    Repease event if input signal remains True for a while\n"
+      "      Input: number of iterations before repeating output\n."
+      "        0 for no repetition";
+    addCommand("repeat", new command::Setter<Event, int>(*this, &Event::repeat,
+                                                         docstring));
   }
 
   ~Event() {}
@@ -94,8 +97,10 @@ class SOT_CORE_DLLAPI Event : public dynamicgraph::Entity {
     return oss.str();
   }
 
-  void setOnlyUp(const bool &up) { onlyUp_ = up; }
-
+  void repeat(const int& nbIterations)
+  {
+    repeatAfterNIterations_ = nbIterations;
+  }
 private:
   typedef SignalBase<int> *Trigger_t;
   typedef std::vector<Trigger_t> Triggers_t;
@@ -107,7 +112,8 @@ private:
   Triggers_t triggers;
   SignalPtr<bool, int> conditionSIN;
 
-  bool lastVal_, onlyUp_;
+  bool lastVal_;
+  int timeSinceUp_, repeatAfterNIterations_;
 };
 } // namespace sot
 } // namespace dynamicgraph
diff --git a/src/tools/event.cpp b/src/tools/event.cpp
index c62aa3d1..9fa7295d 100644
--- a/src/tools/event.cpp
+++ b/src/tools/event.cpp
@@ -11,14 +11,23 @@ namespace sot {
 bool &Event::check(bool &ret, const int &time) {
   const bool &val = conditionSIN(time);
   ret = (val != lastVal_);
-  bool trigger = onlyUp_ ? (!lastVal_ && val) : ret;
+  bool up = (!lastVal_ && val);
+  if (up) {
+    timeSinceUp_ = 0;
+  } else if (val) {
+    ++timeSinceUp_;
+  }
+  // If repetition is activated, trigger again after given number of iterations
+  bool trigger = up || (repeatAfterNIterations_ > 0 &&
+                        timeSinceUp_ >= repeatAfterNIterations_);
   if (ret) {
     lastVal_ = val;
-    if (trigger) {
-      for (Triggers_t::const_iterator _s = triggers.begin();
-           _s != triggers.end(); ++_s)
-        (*_s)->recompute(time);
-    }
+  }
+  if (trigger) {
+    for (Triggers_t::const_iterator _s = triggers.begin();
+         _s != triggers.end(); ++_s)
+      (*_s)->recompute(time);
+    timeSinceUp_ = 0;
   }
   return ret;
 }
-- 
GitLab