$darkmode
noise_data.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
22 #pragma once
23 
24 #include <memory> // for shared_ptr<>
25 #include <random> // for default_random_engine, normal_distribution<>
26 #include <string> // for string
27 #include <utility> // for move
28 
29 #include <cloe/component.hpp> // for Component, ComponentFactory, ...
30 #include <cloe/core.hpp> // for Confable, Schema
31 #include <cloe/entity.hpp> // for Entity
32 #include <cloe/simulator.hpp> // for ModelError
33 #include <fable/schema/factory.hpp> // for Factory
34 
35 namespace cloe {
36 namespace component {
37 
38 using Generator = std::default_random_engine;
39 
40 template <typename T>
41 class Distribution : public Confable, public Entity {
42  public:
43  using Entity::Entity;
44  virtual ~Distribution() noexcept = default;
45 
46  virtual T get(Generator&) const = 0;
47 
48  void to_json(Json& j) const override {
49  j = Json{
50  {"binding", name()},
51  };
52  }
53 
54  virtual void reset() {}
55 
56  CONFABLE_FRIENDS(Distribution)
57 };
58 
59 template <typename T>
60 class NormalDistribution : public Distribution<T> {
61  public:
62  NormalDistribution() : Distribution<T>("normal") {}
63  virtual ~NormalDistribution() noexcept = default;
64 
65  T get(Generator& g) const override { return distribution(g); }
66 
67  void reset() override { distribution = std::normal_distribution<T>{mean, std_deviation}; }
68 
69  void to_json(Json& j) const override {
71  j["mean"] = mean;
72  j["std_deviation"] = std_deviation;
73  }
74 
75  void from_conf(const Conf& c) override {
77  reset();
78  }
79 
80  protected:
81  Schema schema_impl() override {
82  // clang-format off
83  return Schema{
84  {"mean", make_schema(&mean, "mean value of normal distribution")},
85  {"std_deviation", make_schema(&std_deviation, "standard deviation of normal distribution")},
86  };
87  // clang-format on
88  }
89 
90  private:
91  // Configuration
92  double mean = 0.0;
93  double std_deviation = 0.1;
94 
95  // State
96  mutable std::normal_distribution<double> distribution{mean, std_deviation};
97 };
98 
99 using DistributionPtr = std::shared_ptr<Distribution<double>>;
100 
101 template <typename T>
102 class Random {
103  public:
104  Random(const unsigned long& seed, DistributionPtr dist) : engine_(seed), d(dist) {}
105 
106  virtual ~Random() noexcept = default;
107 
108  T get() const { return d->get(engine_); }
109 
110  void reset(const unsigned long& seed) { engine_ = std::default_random_engine(seed); }
111 
112  void reset(DistributionPtr dist) {
113  if (dist) {
114  d = dist;
115  } else {
116  throw cloe::ModelError("noisy_sensor: empty distribution assignment.");
117  }
118  }
119 
120  private:
121  mutable std::default_random_engine engine_;
122  DistributionPtr d{nullptr};
123 };
124 
125 class DistributionFactory : public fable::schema::Factory<DistributionPtr> {
126  public:
127  DistributionFactory(DistributionPtr* ptr, std::string desc)
128  : fable::schema::Factory<DistributionPtr>(ptr, std::move(desc)) {
129  this->set_factory_key("binding");
130  this->set_args_key("");
131  this->add_default_factory<NormalDistribution<double>>("normal");
132  };
133  virtual ~DistributionFactory() = default;
134 };
135 
136 class NoiseConf : public Confable {
137  public:
138  NoiseConf() = default;
139 
140  virtual ~NoiseConf() noexcept = default;
141 
142  double get() const { return rnd_.get(); }
143 
144  virtual void reset(unsigned long seed) {
145  rnd_.reset(distr_default);
146  rnd_.reset(seed);
147  // In case of multiple random number generators, a different seed must
148  // be used for each generator (e.g. increment after each rnd_.reset).
149  }
150 
151  CONFABLE_SCHEMA(NoiseConf) {
152  return Schema{
153  // clang-format off
154  {"distribution", DistributionFactory(&distr_default, "set distribution binding and arguments")},
155  // clang-format on
156  };
157  }
158 
159  void to_json(Json& j) const override {
160  j = Json{
161  {"distribution", distr_default},
162  };
163  }
164 
165  private:
166  DistributionPtr distr_default{nullptr};
167  Random<double> rnd_ = Random<double>(0, distr_default);
168 };
169 
170 struct NoisySensorConf : public Confable {
174  bool enabled = true;
175 
181  bool reuse_seed = true;
182 
186  unsigned long seed = 0;
187 
188  CONFABLE_SCHEMA(NoisySensorConf) {
189  return Schema{
190  {"enable", Schema(&enabled, "enable or disable component")},
191  {"reuse_seed", Schema(&reuse_seed, "whether to get a new seed on reset")},
192  {"seed", Schema(&seed, "set random engine seed (effective on reset)")},
193  };
194  }
195 
196  void to_json(Json& j) const override {
197  j = Json{
198  {"enable", enabled},
199  {"reuse_seed", reuse_seed},
200  {"seed", seed},
201  };
202  }
203 };
204 
205 } // namespace component
206 } // namespace cloe
Definition: entity.hpp:50
const std::string & name() const
Definition: entity.hpp:67
Definition: model.hpp:62
Definition: noise_data.hpp:125
Definition: noise_data.hpp:41
Definition: noise_data.hpp:136
Definition: noise_data.hpp:60
Schema schema_impl() override
Definition: noise_data.hpp:81
void from_conf(const Conf &c) override
Definition: noise_data.hpp:75
Definition: noise_data.hpp:102
Definition: conf.hpp:76
Definition: confable.hpp:43
virtual void from_conf(const Conf &c)
Definition: confable.cpp:70
Json to_json() const
Definition: confable.cpp:78
Definition: schema.hpp:175
void set_factory_key(const std::string &keyword)
Definition: factory.hpp:177
void set_args_key(const std::string &keyword)
Definition: factory.hpp:192
Definition: factory.hpp:425
Definition: noise_data.hpp:170
unsigned long seed
Definition: noise_data.hpp:186
bool enabled
Definition: noise_data.hpp:174
bool reuse_seed
Definition: noise_data.hpp:181