EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Time.h
Go to the documentation of this file.
1#pragma once
2
8
9#include <chrono>
10#include <concepts>
11#include <type_traits>
12
13#include <Eigen/Core>
14
16
17namespace Emrys
18{
19
51
65template <typename Time>
67{};
68
72template <std::floating_point Time>
73struct TimeTraits<Time>
74{
76 template <typename Scalar>
77 [[nodiscard]] static Scalar
78 toScalar(Time t)
79 {
80 return Scalar(t);
81 }
82};
83
87template <typename Rep, typename Period>
88struct TimeTraits<std::chrono::duration<Rep, Period>>
89{
94 template <typename Scalar>
95 [[nodiscard]] static Scalar
96 toScalar(std::chrono::duration<Rep, Period> const & t)
97 {
98 // Through the scalar's literal type, the plain number an autodiff scalar is built from, so
99 // that the integer's conversion is explicit there too.
100 using Real = typename Eigen::NumTraits<Scalar>::Literal;
101 Scalar const count = Scalar(Real(t.count()));
102 Scalar const numerator = Scalar(Real(Period::num));
103 Scalar const denominator = Scalar(Real(Period::den));
104 if constexpr (Period::num == 1 && Period::den == 1)
105 {
106 return count;
107 }
108 else if constexpr (Period::num == 1)
109 {
110 return Scalar(count / denominator);
111 }
112 else if constexpr (Period::den == 1)
113 {
114 return Scalar(count * numerator);
115 }
116 else
117 {
118 return Scalar(Scalar(count * numerator) / denominator);
119 }
120 }
121};
122
127template <typename Time, typename Scalar>
128concept TimeStep = std::same_as<std::remove_cvref_t<Time>, Scalar> || requires(std::remove_cvref_t<Time> const & t) {
129 { TimeTraits<std::remove_cvref_t<Time>>::template toScalar<Scalar>(t) } -> std::same_as<Scalar>;
130};
131
135struct Steps
136{
137 Eigen::Index count;
138};
139
140namespace internal
141{
142
147template <typename Scalar, typename Time>
149[[nodiscard]] Scalar
150toScalarTime(Time const & t)
151{
152 Scalar const step = [&] {
153 if constexpr (std::same_as<Time, Scalar>)
154 {
155 return t;
156 }
157 else
158 {
159 return TimeTraits<Time>::template toScalar<Scalar>(t);
160 }
161 }();
162 EMRYS_FILTER_ASSERT(step >= Scalar(0) && "a time step must be nonnegative");
163 return step;
164}
165
169template <typename... Args>
170inline constexpr bool leadsWithSteps = false;
171
173template <typename First, typename... Rest>
174inline constexpr bool leadsWithSteps<First, Rest...> = std::same_as<std::remove_cvref_t<First>, Steps>;
175
182template <typename... Args>
183inline constexpr bool leadsWithTimeStep = false;
184
186template <typename First, typename... Rest>
187inline constexpr bool leadsWithTimeStep<First, Rest...> =
188 std::is_arithmetic_v<std::remove_cvref_t<First>> || TimeStep<First, double> || TimeStep<First, float>;
189
193template <typename... Inputs>
194consteval void
195rejectTimeStep()
196{
197 static_assert(
198 !leadsWithTimeStep<Inputs...>,
199 "a fixed-step filter takes its own step: call predict() for one step or predict(Steps{n}) for n, "
200 "and give an input by its tag, as sure<Tag>(value) or a distribution over the tag's space"
201 );
202}
203
204} // namespace internal
205
206} // namespace Emrys
The macros every header includes first.
A step of time that converts to Scalar: Scalar itself, or any type with a TimeTraits,...
Definition Time.h:128
A count of a fixed-step model's steps, for predict(Steps{n}).
Definition Time.h:136
Eigen::Index count
the number of steps, at least zero
Definition Time.h:137
static Scalar toScalar(Time t)
Definition Time.h:78
static Scalar toScalar(std::chrono::duration< Rep, Period > const &t)
Definition Time.h:96
How a time type converts to a scalar, as a static member template toScalar<Scalar>(t) returning Scala...
Definition Time.h:67