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