1 |
|
|
// -*- mode: c++ -*- |
2 |
|
|
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse, |
3 |
|
|
// JRL, CNRS/AIST. |
4 |
|
|
// |
5 |
|
|
|
6 |
|
|
#ifndef DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H |
7 |
|
|
#define DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H |
8 |
|
|
#include <dynamic-graph/signal.h> |
9 |
|
|
#include <dynamic-graph/time-dependency.h> |
10 |
|
|
|
11 |
|
|
namespace dynamicgraph { |
12 |
|
|
/*! \brief A type of signal that enforces a time dependency between other |
13 |
|
|
signals, |
14 |
|
|
making sure its inputs are up to date on access, using a incrementing time |
15 |
|
|
tick as reference. |
16 |
|
|
|
17 |
|
|
It works this way. For a given SignalTimeDependent S, |
18 |
|
|
- the user manually adds dependent signals through the use of the |
19 |
|
|
SignalTimeDependent::addDependency function. |
20 |
|
|
- On access (calling the signal S SignalTimeDependent::operator()(const Time&) |
21 |
|
|
or SignalTimeDependent::access(const Time&) function), if the dependent |
22 |
|
|
signals are not up-to-date, i.e. if their [last update] time is less than the |
23 |
|
|
current time, their value will be SignalTimeDependent::access ()'ed to bring |
24 |
|
|
them up-to-date. |
25 |
|
|
|
26 |
|
|
Thus, the value of dependent signals can be accessed \b quickly and |
27 |
|
|
\b repeatedly through the Signal::accessCopy () function. |
28 |
|
|
|
29 |
|
|
An example: |
30 |
|
|
\code |
31 |
|
|
class MyEntity : public Entity { |
32 |
|
|
public: |
33 |
|
|
// Some signal dependencies |
34 |
|
|
SignalPtr<T,int> dep1, dep2; |
35 |
|
|
SignalTimeDependent<T,int> signal; |
36 |
|
|
|
37 |
|
|
MyEntity (const std::string& name) |
38 |
|
|
: Entity (name) |
39 |
|
|
, signal ( |
40 |
|
|
// Set the function that computes the signal value |
41 |
|
|
boost::bind (&Entity::computeSignal, this, _1, _2), |
42 |
|
|
// Declare the dependencies |
43 |
|
|
dep1 << dep2, |
44 |
|
|
"signalname") |
45 |
|
|
{} |
46 |
|
|
|
47 |
|
|
T& computeSignal (T& res, int time) |
48 |
|
|
{ |
49 |
|
|
// The accesses below update the signal if necessary. |
50 |
|
|
dep1(time); |
51 |
|
|
dep1.access(time); |
52 |
|
|
dep1.recompute(time); |
53 |
|
|
// If dep1 and dep2 are already up-to-date, for a faster access, use |
54 |
|
|
dep1.accessCopy(); |
55 |
|
|
dep2.accessCopy(); |
56 |
|
|
|
57 |
|
|
// Compute res |
58 |
|
|
return res; |
59 |
|
|
} |
60 |
|
|
\endcode |
61 |
|
|
*/ |
62 |
|
|
template <class T, class Time> |
63 |
|
|
class SignalTimeDependent : public virtual Signal<T, Time>, |
64 |
|
|
public TimeDependency<Time> { |
65 |
|
|
// TimeDependency<Time> timeDependency; |
66 |
|
|
|
67 |
|
|
public: |
68 |
|
|
SignalTimeDependent(std::string name = ""); |
69 |
|
|
SignalTimeDependent(const SignalArray_const<Time> &arr, |
70 |
|
|
std::string name = ""); |
71 |
|
|
SignalTimeDependent(boost::function2<T &, T &, Time> t, |
72 |
|
|
const SignalArray_const<Time> &sig, |
73 |
|
|
std::string name = ""); |
74 |
|
|
|
75 |
|
16 |
virtual ~SignalTimeDependent() {} |
76 |
|
|
|
77 |
|
2 |
inline const T &operator()(const Time &t1) { return access(t1); } |
78 |
|
|
const T &access(const Time &t1); |
79 |
|
|
|
80 |
|
|
virtual void addDependency(const SignalBase<Time> &signal); |
81 |
|
|
virtual void removeDependency(const SignalBase<Time> &signal); |
82 |
|
|
virtual void clearDependencies(); |
83 |
|
|
|
84 |
|
3 |
std::ostream &writeGraph(std::ostream &os) const { return os; } |
85 |
|
|
|
86 |
|
160 |
std::ostream &displayDependencies(std::ostream &os, const int depth = -1, |
87 |
|
|
std::string space = "", |
88 |
|
|
std::string next1 = "", |
89 |
|
|
std::string next2 = "") const { |
90 |
✓✗✓✗ ✓✗ |
320 |
return TimeDependency<Time>::displayDependencies(os, depth, space, next1, |
91 |
|
320 |
next2); |
92 |
|
|
} |
93 |
|
|
|
94 |
|
|
virtual bool needUpdate(const Time &t) const; |
95 |
|
|
virtual void setPeriodTime(const Time &p); |
96 |
|
|
virtual Time getPeriodTime() const; |
97 |
|
|
}; |
98 |
|
|
|
99 |
|
|
/* -------------------------------------------- */ |
100 |
|
|
|
101 |
|
|
template <class T, class Time> |
102 |
|
6 |
SignalTimeDependent<T, Time>::SignalTimeDependent(std::string name) |
103 |
✓✗ |
6 |
: Signal<T, Time>(name), TimeDependency<Time>(this) {} |
104 |
|
|
|
105 |
|
|
template <class T, class Time> |
106 |
|
6 |
SignalTimeDependent<T, Time>::SignalTimeDependent( |
107 |
|
|
const SignalArray_const<Time> &arr, std::string name) |
108 |
✓✗✓✗
|
6 |
: Signal<T, Time>(name), TimeDependency<Time>(this, arr) {} |
109 |
|
|
|
110 |
|
|
template <class T, class Time> |
111 |
|
14 |
SignalTimeDependent<T, Time>::SignalTimeDependent( |
112 |
|
|
boost::function2<T &, T &, Time> t, const SignalArray_const<Time> &sig, |
113 |
|
|
std::string name) |
114 |
✓✗✓✗
|
14 |
: Signal<T, Time>(name), TimeDependency<Time>(this, sig) { |
115 |
✓✗✓✗
|
14 |
this->setFunction(t); |
116 |
|
14 |
} |
117 |
|
|
|
118 |
|
|
template <class T, class Time> |
119 |
|
4068 |
const T &SignalTimeDependent<T, Time>::access(const Time &t1) { |
120 |
|
4068 |
const bool up = TimeDependency<Time>::needUpdate(t1); |
121 |
|
|
// SignalBase<Time>::setReady(false); |
122 |
|
|
|
123 |
|
|
/* std::cout << "Time before: "<< signalTime << " -- " */ |
124 |
|
|
/* << t1<< " -> Up: "<<up <<std::endl ; */ |
125 |
✓✓ |
4068 |
if (up) { |
126 |
|
4038 |
TimeDependency<Time>::lastAskForUpdate = false; |
127 |
|
4038 |
const T &Tres = Signal<T, Time>::access(t1); |
128 |
|
4038 |
SignalBase<Time>::setReady(false); |
129 |
|
4038 |
return Tres; |
130 |
|
|
} else { |
131 |
|
30 |
return Signal<T, Time>::accessCopy(); |
132 |
|
|
} |
133 |
|
|
} |
134 |
|
|
|
135 |
|
|
template <class T, class Time> |
136 |
|
4 |
void SignalTimeDependent<T, Time>::addDependency( |
137 |
|
|
const SignalBase<Time> &signal) { |
138 |
|
4 |
TimeDependency<Time>::addDependency(signal); |
139 |
|
4 |
} |
140 |
|
|
|
141 |
|
|
template <class T, class Time> |
142 |
|
2 |
void SignalTimeDependent<T, Time>::removeDependency( |
143 |
|
|
const SignalBase<Time> &signal) { |
144 |
|
2 |
TimeDependency<Time>::removeDependency(signal); |
145 |
|
|
} |
146 |
|
|
|
147 |
|
|
template <class T, class Time> |
148 |
|
2 |
void SignalTimeDependent<T, Time>::clearDependencies() { |
149 |
|
2 |
TimeDependency<Time>::clearDependency(); |
150 |
|
2 |
} |
151 |
|
|
|
152 |
|
|
template <class T, class Time> |
153 |
|
26 |
bool SignalTimeDependent<T, Time>::needUpdate(const Time &t) const { |
154 |
|
26 |
return TimeDependency<Time>::needUpdate(t); |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
template <class T, class Time> |
158 |
|
2 |
void SignalTimeDependent<T, Time>::setPeriodTime(const Time &p) { |
159 |
|
2 |
TimeDependency<Time>::setPeriodTime(p); |
160 |
|
|
} |
161 |
|
|
template <class T, class Time> |
162 |
|
1 |
Time SignalTimeDependent<T, Time>::getPeriodTime() const { |
163 |
|
1 |
return TimeDependency<Time>::getPeriodTime(); |
164 |
|
|
} |
165 |
|
|
|
166 |
|
|
} // end of namespace dynamicgraph |
167 |
|
|
|
168 |
|
|
#endif //! DYNAMIC_GRAPH_SIGNAL_TIME_DEPENDENT_H |