Skip to content

Commit 938a4dc

Browse files
committed
Added the PSim configuration/parameter system.
1 parent 3c2cde8 commit 938a4dc

16 files changed

+855
-15
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,6 @@ bazel-out
153153
bazel-psim
154154
bazel-testlogs
155155
bazel-genfiles
156+
157+
# Compiler commands from Bazel
158+
compile_commands.json

BUILD

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,19 @@ cc_library(
5757
# Build all PSim models as a library
5858
#
5959
# This will be linked with executables later on.
60-
# cc_library(
61-
# name = "psim",
62-
# srcs = glob([
63-
# "src/psim/**/*.hpp", "src/psim/**/*.inl", "src/psim/**/*.cpp",
64-
# ]),
65-
# hdrs = glob(
66-
# ["include/psim/**/*.hpp", "include/psim/**/*.inl"],
67-
# exclude = ["include/psim/**/*.yml.hpp"],
68-
# ),
69-
# includes = ["include"],
70-
# copts = ["-Isrc"],
71-
# linkstatic = True,
72-
# visibility = ["//visibility:public"],
73-
# deps = ["@lin//:lin", "//:gnc", "//:autocode"],
74-
# )
60+
cc_library(
61+
name = "psim",
62+
srcs = glob([
63+
"src/psim/**/*.hpp", "src/psim/**/*.inl", "src/psim/**/*.cpp",
64+
"include/psim/**/*.inl", # "include/psim/**/*.yml.hpp",
65+
]),
66+
hdrs = glob(
67+
["include/psim/**/*.hpp"],
68+
#exclude = ["include/psim/**/*.yml.hpp"],
69+
),
70+
includes = ["include"],
71+
copts = ["-Isrc"],
72+
linkstatic = True,
73+
visibility = ["//visibility:public"],
74+
deps = ["@lin//:lin", "//:gnc"],# "//:autocode"],
75+
)

include/psim/core/configuration.hpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2020 Pathfinder for Autonomous Navigation (PAN)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
25+
/** @file psim/core/configuration.hpp
26+
* @author Kyle Krol
27+
*/
28+
29+
#ifndef PSIM_CORE_CONFIGURATION_HPP_
30+
#define PSIM_CORE_CONFIGURATION_HPP_
31+
32+
#include "parameter.hpp"
33+
#include "parameter_base.hpp"
34+
#include "types.hpp"
35+
36+
#include <string>
37+
#include <unordered_map>
38+
39+
namespace psim {
40+
41+
/** @brief Represents a set of parameters used to initialize a simulation.
42+
*
43+
* A configuration is a set of parameters parsed from a configuration file. These
44+
* parameters are made accesible to the simulation's models during intialization
45+
* to specify initial conditions and configure constants.
46+
*/
47+
class Configuration {
48+
private:
49+
/** @brief Map containing the parameter pointers.
50+
*/
51+
std::unordered_map<std::string, ParameterBase const *> _parameters;
52+
53+
Configuration() = default;
54+
55+
/** @brief Adds a parameter and associates it with the specified name.
56+
*
57+
* @param[in] name
58+
* @param[in] value
59+
*
60+
* If a parameter has already been associated with the name, a runtime error is
61+
* thrown.
62+
*/
63+
template <typename T>
64+
void add(std::string const &name, T &&value);
65+
66+
public:
67+
Configuration(Configuration const &) = delete;
68+
Configuration &operator=(Configuration const &) = delete;
69+
70+
Configuration(Configuration &&config);
71+
Configuration &operator=(Configuration &&config);
72+
73+
virtual ~Configuration();
74+
75+
/** @brief Retrives a parameter by name.
76+
*
77+
* @param[in] name
78+
*
79+
* @return Pointer to the parameter.
80+
*
81+
* If no parameter is found by the specified name, a null pointer is returned.
82+
*/
83+
ParameterBase const *get(std::string const &name) const;
84+
85+
/** @brief Retrives a parameter by name.
86+
*
87+
* @param[in] name
88+
*
89+
* @return Pointer to the parameter.
90+
*
91+
* If no parameter is found by the specified name, a runtime error is thrown.
92+
*/
93+
ParameterBase const &operator[](std::string const &name) const;
94+
95+
/** @brief Parses a configuration file into a set of parameters.
96+
*
97+
* @param[in] file Configuration file.
98+
*
99+
* @return Parameters.
100+
*
101+
* If the configuration file doesn't exist, or a line with invalid formatting
102+
* is encountered, a runtime error will be thrown.
103+
*/
104+
static Configuration make(std::string const &file);
105+
};
106+
} // namespace psim
107+
108+
#endif

include/psim/core/parameter.hpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2020 Pathfinder for Autonomous Navigation (PAN)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
25+
/** @file psim/core/parameters.hpp
26+
* @author Kyle Krol
27+
*/
28+
29+
#ifndef PSIM_CORE_PARAMETER_HPP_
30+
#define PSIM_CORE_PARAMETER_HPP_
31+
32+
#include "parameter_base.hpp"
33+
34+
#include <type_traits>
35+
#include <utility>
36+
37+
namespace psim {
38+
39+
/** @brief Simulation parameter holding a single value of the underlying type.
40+
*
41+
* @tparam T Underlying type.
42+
*/
43+
template <typename T>
44+
class Parameter : public ParameterBase {
45+
private:
46+
/** @brief Underlying value.
47+
*/
48+
T _value;
49+
50+
public:
51+
virtual ~Parameter() = default;
52+
53+
/** @brief Default constructs the parameter's initial value.
54+
*
55+
* https://stackoverflow.com/questions/2417065/does-the-default-constructor-initialize-built-in-types
56+
*/
57+
Parameter()
58+
: _value() { }
59+
60+
/** @param[in] value Parameter's initial value.
61+
*
62+
* @{
63+
*/
64+
Parameter(T const &value)
65+
: _value(value) { }
66+
67+
Parameter(T &&value)
68+
: _value(std::move(value)) { }
69+
/** @}
70+
*/
71+
72+
/** @param[in] value Parameter's initial value.
73+
*
74+
* If the passed parameter's underlying type does not match, a runtime error
75+
* will be thrown.
76+
*
77+
* @{
78+
*/
79+
Parameter(ParameterBase const &param)
80+
: _value(param.get<T>()) { }
81+
82+
Parameter(ParameterBase &&param)
83+
: _value(std::move(param.get<T>())) { }
84+
/** @}
85+
*/
86+
87+
/** @return Reference to the underlying type.
88+
*
89+
* @{
90+
*/
91+
operator T const & () const {
92+
return _value;
93+
}
94+
95+
operator T & () {
96+
return _value;
97+
}
98+
/** @}
99+
*/
100+
101+
/** @param[in] value New value held by the parameter.
102+
*
103+
* @return Reference to this parameter.
104+
*
105+
* @{
106+
*/
107+
Parameter<T> &operator=(T const &value) {
108+
_value = value;
109+
}
110+
111+
Parameter<T> &operator=(T &&value) {
112+
_value = std::move(value);
113+
}
114+
/** @}
115+
*/
116+
117+
/** @param[in] param New value held by the parameter.
118+
*
119+
* @return Reference to this parameter.
120+
*
121+
* If the passed parameter's underlying type does not match a runtime error
122+
* will be thrown.
123+
*
124+
* @{
125+
*/
126+
Parameter<T> &operator=(ParameterBase const &param) {
127+
_value = param.get<T>();
128+
}
129+
130+
Parameter<T> &operator=(ParameterBase &&param) {
131+
_value = std::move(param.get<T>());
132+
}
133+
/** @}
134+
*/
135+
136+
/** @returns Reference to the underlying value.
137+
*
138+
* This function was re-implemented to avoid potential type checking overhead
139+
* and keep a consistant interface.
140+
*
141+
* @{
142+
*/
143+
template <typename U = T>
144+
U const &get() const {
145+
static_assert(std::is_same<U, T>::value, "Invalid parameter type in call to 'get'.");
146+
return _value;
147+
}
148+
149+
template <typename U = T>
150+
U &get() {
151+
static_assert(std::is_same<U, T>::value, "Invalid parameter type in call to 'get'.");
152+
return _value;
153+
}
154+
/** @}
155+
*/
156+
};
157+
} // namespace psim
158+
159+
#endif

include/psim/core/parameter_base.hpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2020 Pathfinder for Autonomous Navigation (PAN)
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
25+
/** @file psim/core/parameter_base.hpp
26+
* @author Kyle Krol
27+
*/
28+
29+
#ifndef PSIM_CORE_PARAMETER_BASE_HPP_
30+
#define PSIM_CORE_PARAMETER_BASE_HPP_
31+
32+
#include <stdexcept>
33+
34+
namespace psim {
35+
36+
template <typename T>
37+
class Parameter;
38+
39+
/** @brief Virtual base class for all parameters.
40+
*
41+
* The main purpose of this class is to allow dynamic casting to be used to check
42+
* parameter types at runtime and provide helpful casting functions.
43+
*/
44+
class ParameterBase {
45+
protected:
46+
ParameterBase() = default;
47+
48+
public:
49+
virtual ~ParameterBase() = default;
50+
51+
/** @brief Attempt to get the parameter's underlying value.
52+
*
53+
* @tparam Expected underlying type.
54+
*
55+
* @return Reference to the underlying value.
56+
*
57+
* If the underlying type doesn't match the expected underlying type, a runtime
58+
* error will be thrown.
59+
*
60+
* @{
61+
*/
62+
template <typename T>
63+
T const &get() const {
64+
auto const *param_ptr = dynamic_cast<Parameter<T> const *>(this);
65+
if (!param_ptr)
66+
throw std::runtime_error("Invalid parameter type in call to 'get'.");
67+
68+
return (T const &) *param_ptr;
69+
}
70+
71+
template <typename T>
72+
T &get() {
73+
auto *param_ptr = dynamic_cast<Parameter<T> *>(this);
74+
if (!param_ptr)
75+
throw std::runtime_error("Invalid parameter type in call to 'get'.");
76+
77+
return (T &) *param_ptr;
78+
}
79+
/** @}
80+
*/
81+
};
82+
} // namespace psim
83+
84+
#endif

0 commit comments

Comments
 (0)