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