Skip to content

Commit a00f64f

Browse files
tobifalkcassava
authored andcommitted
noisy_sensor: Extend to lane boundaries and refine noise configuration
1 parent ea59553 commit a00f64f

16 files changed

+1026
-114
lines changed

conanfile.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def requirements(self):
4646
"cloe-plugin-gndtruth-extractor",
4747
"cloe-plugin-speedometer",
4848
"cloe-plugin-minimator",
49-
"cloe-plugin-noisy-object-sensor",
49+
"cloe-plugin-noisy-sensor",
5050
"cloe-plugin-virtue",
5151
]
5252
if self.options.with_vtd:

plugins/noisy_object_sensor/CMakeLists.txt

-52
This file was deleted.

plugins/noisy_sensor/CMakeLists.txt

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
2+
3+
project(cloe_plugin_noisy_sensor LANGUAGES CXX)
4+
5+
# Conan / Editor -----------------------------------------------------
6+
include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
7+
conan_basic_setup(TARGETS NO_OUTPUT_DIRS)
8+
9+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
10+
11+
include(TargetLinting)
12+
include(GNUInstallDirs)
13+
14+
function(add_cloe_plugin target_output sources)
15+
message(STATUS "-> Building ${target_output} module.")
16+
add_library(${target_output} MODULE ${sources})
17+
set(cloe_lib_dir ${CMAKE_CURRENT_BINARY_DIR}/lib/cloe)
18+
set_target_properties(${target_output} PROPERTIES
19+
CXX_STANDARD 14
20+
CXX_STANDARD_REQUIRED ON
21+
ARCHIVE_OUTPUT_DIRECTORY ${cloe_lib_dir}
22+
LIBRARY_OUTPUT_DIRECTORY ${cloe_lib_dir}
23+
RUNTIME_OUTPUT_DIRECTORY ${cloe_lib_dir}
24+
OUTPUT_NAME ${target_output}
25+
PREFIX ""
26+
)
27+
set_target_linting(${target_output})
28+
target_compile_options(${target_output}
29+
PRIVATE
30+
-fvisibility=hidden -fvisibility-inlines-hidden
31+
)
32+
target_link_libraries(${target_output}
33+
PRIVATE
34+
CONAN_PKG::cloe-runtime
35+
CONAN_PKG::cloe-models
36+
)
37+
target_compile_definitions(${target_output}
38+
PRIVATE
39+
PROJECT_SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"
40+
)
41+
42+
install(TARGETS ${target_output}
43+
LIBRARY
44+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cloe
45+
)
46+
endfunction()
47+
48+
add_cloe_plugin(component_noisy_object_sensor src/noisy_object_sensor.cpp)
49+
add_cloe_plugin(component_noisy_lane_sensor src/noisy_lane_sensor.cpp)
File renamed without changes.

plugins/noisy_object_sensor/conanfile.py renamed to plugins/noisy_sensor/conanfile.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from conans import ConanFile, CMake, tools
33

44

5-
class CloeComponentNoisyObjectSensor(ConanFile):
6-
name = "cloe-plugin-noisy-object-sensor"
5+
class CloeComponentNoisySensor(ConanFile):
6+
name = "cloe-plugin-noisy-sensor"
77
url = "https://github.com/eclipse/cloe"
88
description = "Cloe component plugin that adds noise to sensed data"
99
license = "Apache-2.0"
+271
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
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+
*/
18+
/**
19+
* \file noise_data.hpp
20+
*/
21+
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+
33+
namespace cloe {
34+
namespace component {
35+
36+
using Generator = std::default_random_engine;
37+
38+
template <typename T>
39+
class Distribution : public Confable, public Entity {
40+
public:
41+
using Entity::Entity;
42+
virtual ~Distribution() noexcept = default;
43+
44+
virtual T get(Generator&) const = 0;
45+
46+
void to_json(Json& j) const override {
47+
j = Json{
48+
{"binding", name()},
49+
};
50+
}
51+
52+
virtual void reset() {}
53+
54+
CONFABLE_FRIENDS(Distribution)
55+
};
56+
57+
template <typename T>
58+
class NormalDistribution : public Distribution<T> {
59+
public:
60+
NormalDistribution() : Distribution<T>("normal") {}
61+
virtual ~NormalDistribution() noexcept = default;
62+
63+
T get(Generator& g) const override { return distribution(g); }
64+
65+
void reset() override { distribution = std::normal_distribution<T>{mean, std_deviation}; }
66+
67+
void to_json(Json& j) const override {
68+
Distribution<T>::to_json(j);
69+
j["args"] = Json{
70+
{"mean", mean},
71+
{"std_deviation", std_deviation},
72+
};
73+
}
74+
75+
void from_conf(const Conf& c) override {
76+
Confable::from_conf(c);
77+
reset();
78+
}
79+
80+
protected:
81+
Schema schema_impl() override {
82+
// clang-format off
83+
return Schema{
84+
{"binding", make_const_schema(this->name(), "identifier of this distribution").require()},
85+
{"args", Schema{
86+
{"mean", make_schema(&mean, "mean value of normal distribution")},
87+
{"std_deviation", make_schema(&std_deviation, "standard deviation of normal distribution")},
88+
}},
89+
};
90+
// clang-format on
91+
}
92+
93+
private:
94+
// Configuration
95+
double mean = 0.0;
96+
double std_deviation = 0.1;
97+
98+
// State
99+
mutable std::normal_distribution<double> distribution{mean, std_deviation};
100+
};
101+
102+
using DistributionPtr = std::shared_ptr<Distribution<double>>;
103+
104+
template <typename T = double, typename P = std::shared_ptr<Distribution<T>>>
105+
class DistributionSchema : public schema::Base<DistributionSchema<T, P>> {
106+
using Base = schema::Base<DistributionSchema<T, P>>;
107+
using Type = P;
108+
109+
const std::map<std::string, std::function<Distribution<T>*(const Conf& c)>> distributions{
110+
{"normal",
111+
[](const Conf& c) {
112+
auto d = new NormalDistribution<T>();
113+
if (c.has("args")) {
114+
d->from_conf(c);
115+
}
116+
return d;
117+
}},
118+
};
119+
120+
public: // Constructors
121+
DistributionSchema(Type* ptr, std::string&& desc)
122+
: Base(JsonType::object, std::move(desc)), ptr_(ptr) {}
123+
124+
public: // Special
125+
const std::vector<Schema>& schemas() const { return schemas_; }
126+
Json json_schemas() const {
127+
Json vec = Json::array();
128+
for (const auto& s : schemas_) {
129+
vec.push_back(s.json_schema());
130+
}
131+
return vec;
132+
}
133+
134+
public: // Overrides
135+
Json json_schema() const override {
136+
Json j{
137+
{"oneOf", json_schemas()},
138+
};
139+
this->augment_schema(j);
140+
return j;
141+
}
142+
143+
void validate(const Conf& c) const override {
144+
size_t valid = 0;
145+
for (const auto& s : schemas_) {
146+
if (s.is_valid(c)) {
147+
valid++;
148+
}
149+
}
150+
if (valid != 1) {
151+
this->throw_error(c, "require exactly one sub-schema to match");
152+
}
153+
}
154+
155+
void to_json(Json& j) const override { j = serialize(*ptr_); }
156+
157+
void from_conf(const Conf& c) override {
158+
assert(ptr_ != nullptr);
159+
*ptr_ = deserialize(c);
160+
}
161+
162+
Json serialize(const Type& x) const { return x; }
163+
164+
Type deserialize(const Conf& c) const {
165+
auto binding = c.get<std::string>("binding");
166+
return Type(distributions.at(binding)(c));
167+
}
168+
169+
void reset_ptr() override {
170+
ptr_ = nullptr;
171+
for (auto& s : schemas_) {
172+
s.reset_ptr();
173+
}
174+
}
175+
176+
private:
177+
Type* ptr_{nullptr};
178+
std::vector<Schema> schemas_{
179+
NormalDistribution<T>().schema(),
180+
};
181+
};
182+
183+
template <typename T>
184+
class Random {
185+
public:
186+
Random(const unsigned long& seed, DistributionPtr dist) : engine_(seed), d(dist) {}
187+
188+
virtual ~Random() noexcept = default;
189+
190+
T get() const { return d->get(engine_); }
191+
192+
void reset(const unsigned long& seed) { engine_ = std::default_random_engine(seed); }
193+
194+
void reset(DistributionPtr dist) { d = dist; }
195+
196+
private:
197+
mutable std::default_random_engine engine_;
198+
DistributionPtr d;
199+
};
200+
201+
class NoiseConf : public Confable {
202+
public:
203+
NoiseConf() = default;
204+
205+
virtual ~NoiseConf() noexcept = default;
206+
207+
double get() const { return rnd_.get(); }
208+
209+
virtual void reset(unsigned long seed) {
210+
rnd_.reset(distr_default);
211+
rnd_.reset(seed);
212+
// In case of multiple random number generators, a different seed must
213+
// be used for each generator (e.g. increment after each rnd_.reset).
214+
}
215+
216+
CONFABLE_SCHEMA(NoiseConf) {
217+
return Schema{
218+
// clang-format off
219+
{"distribution", DistributionSchema<>(&distr_default, "set distribution binding and arguments")},
220+
// clang-format on
221+
};
222+
}
223+
224+
void to_json(Json& j) const override {
225+
j = Json{
226+
{"distribution", distr_default},
227+
};
228+
}
229+
230+
private:
231+
DistributionPtr distr_default{nullptr};
232+
Random<double> rnd_ = Random<double>(0, distr_default);
233+
};
234+
235+
struct NoisySensorConf : public Confable {
236+
/**
237+
* This flag exists so that an action can modify it at runtime.
238+
*/
239+
bool enabled = true;
240+
241+
/**
242+
* If reuse_seed is true, then in every reset we want to use the same
243+
* random seed. This is generally the behavior that we want when
244+
* restarting a simulation, as this preserves the same noise pattern.
245+
*/
246+
bool reuse_seed = true;
247+
248+
/**
249+
* When set to 0, a new random seed is retrieved.
250+
*/
251+
unsigned long seed = 0;
252+
253+
CONFABLE_SCHEMA(NoisySensorConf) {
254+
return Schema{
255+
{"enable", Schema(&enabled, "enable or disable component")},
256+
{"reuse_seed", Schema(&reuse_seed, "whether to get a new seed on reset")},
257+
{"seed", Schema(&seed, "set random engine seed (effective on reset)")},
258+
};
259+
}
260+
261+
void to_json(Json& j) const override {
262+
j = Json{
263+
{"enable", enabled},
264+
{"reuse_seed", reuse_seed},
265+
{"seed", seed},
266+
};
267+
}
268+
};
269+
270+
} // namespace component
271+
} // namespace cloe

0 commit comments

Comments
 (0)