signal-time-dependent.h 5.45 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
        boost::bind (&Entity::computeSignal, this, _1, _2),
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        // 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
*/
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
75
76
  virtual ~SignalTimeDependent() {}

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

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

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

86
87
88
89
90
91
92
  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
93

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

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

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

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

template <class T, class Time>
111
112
113
114
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
115
116
117
118
  this->setFunction(t);
}

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

  /*       std::cout << "Time before: "<< signalTime << " -- "   */
124
  /*            << t1<< "  -> Up: "<<up <<std::endl ;   */
125
126
127
128
129
130
131
132
  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
133
134
135
}

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

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

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

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

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

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

168
#endif //! DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H