signal-time-dependent.h 5.49 KB
Newer Older
Thomas Moulard's avatar
Thomas Moulard committed
1
2
3
4
5
6
// -*- mode: c++ -*-
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.
//

#ifndef DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H
Bergé's avatar
Bergé committed
7
8
9
10
#define DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H
#include <dynamic-graph/signal.h>
#include <dynamic-graph/time-dependency.h>

11
12
13
14
15
namespace dynamicgraph {
/*!  \brief A type of signal that enforces a time dependency between other
  signals,
  making sure its inputs are up to date on access, using a incrementing time
  tick as reference.
16
17

  It works this way. For a given SignalTimeDependent S,
Olivier Stasse's avatar
Olivier Stasse committed
18
19
20
21
22
23
24
  - the user manually adds dependent signals through the use of the
  SignalTimeDependent::addDependency function.
  - On access (calling the signal S SignalTimeDependent::operator()(const Time&)
  or SignalTimeDependent::access(const Time&) function), if the dependent
  signals are not up-to-date, i.e. if their [last update] time is less than the
  current time, their value will be SignalTimeDependent::access ()'ed to bring
  them up-to-date.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

  Thus, the value of dependent signals can be accessed \b quickly and
  \b repeatedly through the Signal::accessCopy () function.

  An example:
  \code
  class MyEntity : public Entity {
  public:
  // Some signal dependencies
  SignalPtr<T,int> dep1, dep2;
  SignalTimeDependent<T,int> signal;

  MyEntity (const std::string& name)
    : Entity (name)
    , signal (
        // Set the function that computes the signal value
41
42
        boost::bind (&Entity::computeSignal, this, boost::placeholders::_1,
  boost::placeholders::_2),
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
        // Declare the dependencies
        dep1 << dep2,
        "signalname")
  {}

   T& computeSignal (T& res, int time)
   {
     // The accesses below update the signal if necessary.
     dep1(time);
     dep1.access(time);
     dep1.recompute(time);
     // If dep1 and dep2 are already up-to-date, for a faster access, use
     dep1.accessCopy();
     dep2.accessCopy();

     // Compute res
     return res;
   }
  \endcode
62
63
64
65
66
67
68
69
70
71
72
73
74
75
*/
template <class T, class Time>
class SignalTimeDependent : public virtual Signal<T, Time>,
                            public TimeDependency<Time> {
  // TimeDependency<Time> timeDependency;

public:
  SignalTimeDependent(std::string name = "");
  SignalTimeDependent(const SignalArray_const<Time> &arr,
                      std::string name = "");
  SignalTimeDependent(boost::function2<T &, T &, Time> t,
                      const SignalArray_const<Time> &sig,
                      std::string name = "");

Bergé's avatar
Bergé committed
76
77
  virtual ~SignalTimeDependent() {}

78
79
  inline const T &operator()(const Time &t1) { return access(t1); }
  const T &access(const Time &t1);
Bergé's avatar
Bergé committed
80

81
82
  virtual void addDependency(const SignalBase<Time> &signal);
  virtual void removeDependency(const SignalBase<Time> &signal);
Bergé's avatar
Bergé committed
83
84
  virtual void clearDependencies();

85
  std::ostream &writeGraph(std::ostream &os) const { return os; }
Bergé's avatar
Bergé committed
86

87
88
89
90
91
92
93
  std::ostream &displayDependencies(std::ostream &os, const int depth = -1,
                                    std::string space = "",
                                    std::string next1 = "",
                                    std::string next2 = "") const {
    return TimeDependency<Time>::displayDependencies(os, depth, space, next1,
                                                     next2);
  }
Bergé's avatar
Bergé committed
94

95
96
  virtual bool needUpdate(const Time &t) const;
  virtual void setPeriodTime(const Time &p);
Bergé's avatar
Bergé committed
97
98
99
100
101
102
  virtual Time getPeriodTime() const;
};

/* -------------------------------------------- */

template <class T, class Time>
103
SignalTimeDependent<T, Time>::SignalTimeDependent(std::string name)
Bergé's avatar
Bergé committed
104
105
106
    : Signal<T, Time>(name), TimeDependency<Time>(this) {}

template <class T, class Time>
107
108
SignalTimeDependent<T, Time>::SignalTimeDependent(
    const SignalArray_const<Time> &arr, std::string name)
Bergé's avatar
Bergé committed
109
110
111
    : Signal<T, Time>(name), TimeDependency<Time>(this, arr) {}

template <class T, class Time>
112
113
114
115
SignalTimeDependent<T, Time>::SignalTimeDependent(
    boost::function2<T &, T &, Time> t, const SignalArray_const<Time> &sig,
    std::string name)
    : Signal<T, Time>(name), TimeDependency<Time>(this, sig) {
Bergé's avatar
Bergé committed
116
117
118
119
  this->setFunction(t);
}

template <class T, class Time>
120
const T &SignalTimeDependent<T, Time>::access(const Time &t1) {
Bergé's avatar
Bergé committed
121
122
123
124
  const bool up = TimeDependency<Time>::needUpdate(t1);
  // SignalBase<Time>::setReady(false);

  /*       std::cout << "Time before: "<< signalTime << " -- "   */
125
  /*            << t1<< "  -> Up: "<<up <<std::endl ;   */
126
127
128
129
130
131
132
133
  if (up) {
    TimeDependency<Time>::lastAskForUpdate = false;
    const T &Tres = Signal<T, Time>::access(t1);
    SignalBase<Time>::setReady(false);
    return Tres;
  } else {
    return Signal<T, Time>::accessCopy();
  }
Bergé's avatar
Bergé committed
134
135
136
}

template <class T, class Time>
137
138
void SignalTimeDependent<T, Time>::addDependency(
    const SignalBase<Time> &signal) {
Bergé's avatar
Bergé committed
139
140
141
142
  TimeDependency<Time>::addDependency(signal);
}

template <class T, class Time>
143
144
void SignalTimeDependent<T, Time>::removeDependency(
    const SignalBase<Time> &signal) {
Bergé's avatar
Bergé committed
145
146
147
148
  TimeDependency<Time>::removeDependency(signal);
}

template <class T, class Time>
149
void SignalTimeDependent<T, Time>::clearDependencies() {
Bergé's avatar
Bergé committed
150
151
152
153
  TimeDependency<Time>::clearDependency();
}

template <class T, class Time>
154
bool SignalTimeDependent<T, Time>::needUpdate(const Time &t) const {
Bergé's avatar
Bergé committed
155
156
157
158
  return TimeDependency<Time>::needUpdate(t);
}

template <class T, class Time>
159
void SignalTimeDependent<T, Time>::setPeriodTime(const Time &p) {
Bergé's avatar
Bergé committed
160
161
162
  TimeDependency<Time>::setPeriodTime(p);
}
template <class T, class Time>
163
Time SignalTimeDependent<T, Time>::getPeriodTime() const {
Bergé's avatar
Bergé committed
164
165
166
  return TimeDependency<Time>::getPeriodTime();
}

167
} // end of namespace dynamicgraph
Bergé's avatar
Bergé committed
168

169
#endif //! DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H