codac 2.0.0
Loading...
Searching...
No Matches
codac2_SampledTraj.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <map>
13#include "codac2_TrajBase.h"
16
17namespace codac2
18{
19 template<typename T>
20 class SampledTraj : public TrajBase<T>, public std::map<double,T>
21 {
22 public:
23
24 SampledTraj()
25 : TrajBase<T>(), std::map<double,T>()
26 { }
27
28 SampledTraj(const std::list<double>& l_t, const std::list<T>& l_x)
29 : SampledTraj()
30 {
31 assert_release(l_t.size() == l_x.size());
32 auto it_t = l_t.begin(); auto it_x = l_x.begin();
33 while(it_t != l_t.end())
34 {
35 this->set(*it_t,*it_x);
36 it_t++; it_x++;
37 }
38 }
39
40 SampledTraj(const std::map<double,T>& m)
41 : TrajBase<T>(), std::map<double,T>(m)
42 { }
43
44 // size is not the std::map<double,T>::size() !
45 virtual Index size() const
46 {
47 if constexpr(std::is_same_v<typename ValueType<T>::Type,ScalarType>)
48 return 1;
49
50 else
51 {
52 if(this->empty())
53 return 0;
54 else
55 return this->begin()->second.size();
56 }
57 }
58
59 virtual std::pair<Index,Index> shape() const
60 {
61 if constexpr(std::is_same_v<typename ValueType<T>::Type,ScalarType>)
62 return {1,1};
63 else
64 {
65 if(this->empty())
66 return {0,0};
67 else
68 return {this->begin()->second.rows(),this->begin()->second.cols()};
69 }
70 }
71
72 size_t nb_samples() const
73 {
74 return std::map<double,T>::size();
75 }
76
77 virtual bool is_empty() const
78 {
79 return std::map<double,T>::empty();
80 }
81
82 virtual Interval tdomain() const
83 {
84 if(this->empty())
85 return Interval::empty();
86 else
87 return { this->begin()->first, this->rbegin()->first };
88 }
89
90 virtual void truncate_tdomain(const Interval& new_tdomain)
91 {
92 assert_release(this->tdomain().is_superset(new_tdomain));
93
94 // Interpolation on the limits of the new tdomain
95 T y_lb = (*this)(new_tdomain.lb());
96 T y_ub = (*this)(new_tdomain.ub());
97
98 auto it = this->begin();
99 while(it != this->end())
100 {
101 if(!new_tdomain.contains(it->first))
102 it = this->erase(it);
103 else
104 ++it;
105 }
106
107 this->set(new_tdomain.lb(), y_lb); // clean truncation
108 this->set(new_tdomain.ub(), y_ub);
109 }
110
111 virtual typename Wrapper<T>::Domain codomain() const
112 {
113 typename Wrapper<T>::Domain hull(this->begin()->second);
114 for(const auto& [t,v] : *this)
115 hull |= v;
116 return hull;
117 }
118
119 virtual T operator()(double t) const
120 {
121 if(!this->tdomain().contains(t))
122 return this->nan_value();
123
124 auto it_lower = this->lower_bound(t);
125 if(it_lower->first == t)
126 return it_lower->second;
127
128 auto it_upper = it_lower;
129 it_lower--;
130
131 // Linear interpolation
132 return it_lower->second +
133 (t - it_lower->first) * (it_upper->second - it_lower->second) /
134 (it_upper->first - it_lower->first);
135 }
136
137 virtual typename Wrapper<T>::Domain operator()(const Interval& t) const
138 {
139 // We obtain the output dimension by an evalution...
140 typename Wrapper<T>::Domain hull(this->begin()->second);
141
142 if(!this->tdomain().is_superset(t))
143 return hull.init(Interval(-oo,oo));
144
145 else
146 {
147 hull = (*this)(t.lb());
148 for(auto it = this->lower_bound(t.lb()) ; it != this->upper_bound(t.ub()) ; it++)
149 hull |= it->second;
150 hull |= (*this)(t.ub());
151 return hull;
152 }
153 }
154
155 void set(double t, const T& x)
156 {
157 assert(this->empty() || size_of(x) == this->size());
158 std::map<double,T>::operator[](t) = x;
159 }
160
161 virtual SampledTraj<T> sampled(double dt) const
162 {
163 return sampled(dt, true);
164 }
165
166 SampledTraj<T> sampled(double dt, bool keep_original_values) const
167 {
168 assert(dt > 0.);
169 assert(!is_empty());
170
171 auto straj = TrajBase<T>::sampled(dt);
172
173 if(keep_original_values)
174 {
175 // Appending values from the initial map:
176 for(const auto& [ti,xi] : *this)
177 straj.set(ti, xi);
178 }
179
180 return straj;
181 }
182
183 template<typename Q>
184 SampledTraj<T> sampled_as(const SampledTraj<Q>& x) const
185 {
186 return TrajBase<T>::sampled_as(x);
187 }
188
189 template<typename Q>
190 SampledTraj<T> sampled_as(const SampledTraj<Q>& x, bool keep_original_values) const
191 {
192 SampledTraj<T> straj = TrajBase<T>::sampled_as(x);
193 if(keep_original_values)
194 for(const auto& [ti,xi] : *this)
195 straj.set(ti, xi);
196 return straj;
197 }
198
199 SampledTraj<T>& shift_tdomain(double shift)
200 {
201 std::map<double,T> save = *this;
202 this->clear();
203 for(const auto& [ti,xi] : save)
204 this->std::map<double,T>::operator[](ti+shift) = xi;
205 return *this;
206 }
207
208 SampledTraj<T>& stretch_tdomain(const Interval& tdomain)
209 {
210 Interval a = this->tdomain(), b = tdomain;
211 std::map<double,T> save = *this;
212 this->clear();
213 for(const auto& [ti,xi] : save)
214 this->std::map<double,T>::operator[]([&]() {
215 if(ti == a.ub())
216 return b.ub(); // due to floating point possible error
217 else
218 return ((ti-a.lb())*b.diam()/a.diam())+b.lb();
219 }()
220 ) = xi;
221 assert(this->tdomain() == tdomain);
222 return *this;
223 }
224
225 template<typename T_=T>
226 requires std::is_same_v<T_,Vector>
227 SampledTraj<double> operator[](Index i) const
228 {
229 assert_release(i >= 0 && i < size());
230 std::map<double,double> m;
231 for(const auto& [t,y] : *this)
232 {
233 assert(i < y.size());
234 m[t] = y[i];
235 }
236
237 return { m };
238 }
239
240 template<typename T_=T>
241 requires std::is_same_v<T_,Vector>
242 SampledTraj<Vector> subvector(Index i, Index j) const
243 {
244 assert_release(i >= 0 && i <= j && j < size());
245 std::map<double,Vector> m;
246 for(const auto& [t,y] : *this)
247 {
248 assert(j < y.size());
249 m[t] = y.subvector(i,j);
250 }
251
252 return { m };
253 }
254 };
255
256 template<typename T>
257 inline std::ostream& operator<<(std::ostream& os, const SampledTraj<T>& x)
258 {
259 os << "SampledTraj. " << x.tdomain() << "↦" << x.codomain() << ", " << x.nb_samples() << " pts";
260 return os;
261 }
262
263 inline SampledTraj<double> continuous_traj(const SampledTraj<double>& x)
264 {
265 SampledTraj<double> x_continuous;
266 const Interval periodicity = x.codomain();
267
268 double prev_xi = 0., value_mod = 0.;
269
270 for(const auto& [ti,xi] : x)
271 {
272 if(!x_continuous.empty())
273 {
274 if(prev_xi - xi > periodicity.diam()*0.9)
275 value_mod += periodicity.diam();
276 else if(prev_xi - xi < -periodicity.diam()*0.9)
277 value_mod -= periodicity.diam();
278 }
279
280 prev_xi = xi;
281 x_continuous.set(ti, xi+value_mod);
282 }
283
284 return x_continuous;
285 }
286}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62
static Interval empty()
Provides an empty interval.
Definition codac2_Interval_impl.h:535
std::ostream & operator<<(std::ostream &os, const BoolInterval &x)
Streams out a BoolInterval.
Definition codac2_BoolInterval.h:45