From 416c2293c5f136cffe20bf12f5babdb2c17a9c6b Mon Sep 17 00:00:00 2001 From: joanvallve Date: Thu, 4 Jul 2024 16:02:44 +0200 Subject: [PATCH] validate agains BASE if TYPE=derived and properly reset log --- src/yaml_schema.cpp | 20 +++---- src/yaml_server.cpp | 1 + test/gtest_apply_schema.cpp | 22 ++++++++ test/schema/complex_case/MapBase.schema | 15 +++++ .../schema/complex_case/MotionProvider.schema | 9 +++ test/schema/complex_case/None.schema | 5 ++ test/schema/complex_case/Problem.schema | 29 ++++++++++ test/schema/complex_case/Problem3d.schema | 20 +++++++ test/schema/complex_case/ProcessorBase.schema | 22 ++++++++ .../ProcessorBaseWithSensor.schema | 6 ++ .../complex_case/ProcessorMotion.schema | 23 ++++++++ .../complex_case/ProcessorOdom3d.schema | 1 + test/schema/complex_case/SensorBase.schema | 6 ++ test/schema/complex_case/SensorOdom3d.schema | 32 +++++++++++ test/schema/complex_case/StateO3d.schema | 22 ++++++++ test/schema/complex_case/StateP3d.schema | 22 ++++++++ .../schema/complex_case/StateSensorO3d.schema | 26 +++++++++ .../schema/complex_case/StateSensorP3d.schema | 26 +++++++++ test/schema/complex_case/StateV3d.schema | 22 ++++++++ .../complex_case/TreeManagerBase.schema | 4 ++ test/schema/complex_case/TypeAndPlugin.schema | 9 +++ test/yaml/complex_case.yaml | 55 +++++++++++++++++++ 22 files changed, 386 insertions(+), 11 deletions(-) create mode 100644 test/schema/complex_case/MapBase.schema create mode 100644 test/schema/complex_case/MotionProvider.schema create mode 100644 test/schema/complex_case/None.schema create mode 100644 test/schema/complex_case/Problem.schema create mode 100644 test/schema/complex_case/Problem3d.schema create mode 100644 test/schema/complex_case/ProcessorBase.schema create mode 100644 test/schema/complex_case/ProcessorBaseWithSensor.schema create mode 100644 test/schema/complex_case/ProcessorMotion.schema create mode 100644 test/schema/complex_case/ProcessorOdom3d.schema create mode 100644 test/schema/complex_case/SensorBase.schema create mode 100644 test/schema/complex_case/SensorOdom3d.schema create mode 100644 test/schema/complex_case/StateO3d.schema create mode 100644 test/schema/complex_case/StateP3d.schema create mode 100644 test/schema/complex_case/StateSensorO3d.schema create mode 100644 test/schema/complex_case/StateSensorP3d.schema create mode 100644 test/schema/complex_case/StateV3d.schema create mode 100644 test/schema/complex_case/TreeManagerBase.schema create mode 100644 test/schema/complex_case/TypeAndPlugin.schema create mode 100644 test/yaml/complex_case.yaml diff --git a/src/yaml_schema.cpp b/src/yaml_schema.cpp index b0ddcea..c199981 100644 --- a/src/yaml_schema.cpp +++ b/src/yaml_schema.cpp @@ -108,9 +108,11 @@ void checkSchema(const YAML::Node& node_schema, { throw std::runtime_error("YAML schema: In " + node_field + ", " + TYPE + " should be a string"); } - if (node_schema[TYPE].as().find("derived") != std::string::npos) + auto type = + isSequenceSchema(node_schema) ? getTypeOfSequence(node_schema) : node_schema[TYPE].as(); + // If type=="derived" or "derived[]", 'BASE' of type string is required + if (type == "derived") { - // If type=="derived" or "derived[]", 'base' of type string is required if (not node_schema[BASE]) { throw std::runtime_error("YAML schema: " + node_field + " of derived type does not contain " + BASE); @@ -119,6 +121,8 @@ void checkSchema(const YAML::Node& node_schema, { throw std::runtime_error("YAML schema: In " + node_field + ", " + BASE + " should be a string"); } + // store type as BASE to check OPTIONS, VALUE & DEFAULT + type = node_schema[BASE].as(); } // Required 'doc' of type string if (not node_schema[DOC]) @@ -150,9 +154,7 @@ void checkSchema(const YAML::Node& node_schema, // OPTIONAL 'value' if (node_schema[VALUE]) { - // check type - auto type = - isSequenceSchema(node_schema) ? getTypeOfSequence(node_schema) : node_schema[TYPE].as(); + // CHECK TYPE (take BASE if "derived") // trivial type if (isTrivialType(type)) { @@ -194,9 +196,7 @@ void checkSchema(const YAML::Node& node_schema, " value cannot be defined in mandatory field"); } - // check type - auto type = - isSequenceSchema(node_schema) ? getTypeOfSequence(node_schema) : node_schema[TYPE].as(); + // CHECK TYPE (take BASE if "derived") // trivial type if (isTrivialType(type)) { @@ -229,9 +229,7 @@ void checkSchema(const YAML::Node& node_schema, { throw std::runtime_error("YAML schema: " + node_field + ", " + OPTIONS + " should be a sequence"); } - // check that all items have valid type - auto type = - isSequenceSchema(node_schema) ? getTypeOfSequence(node_schema) : node_schema[TYPE].as(); + // CHECK TYPE (take BASE if "derived") for (auto n_i = 0; n_i < node_schema[OPTIONS].size(); n_i++) { // trivial type diff --git a/src/yaml_server.cpp b/src/yaml_server.cpp index 52d440f..f1b2558 100644 --- a/src/yaml_server.cpp +++ b/src/yaml_server.cpp @@ -60,6 +60,7 @@ void YamlServer::setYaml(const YAML::Node _node_input) bool YamlServer::applySchema(const std::string& name_schema) { + log_.str(""); log_.clear(); std::string header1, header2, header3; diff --git a/test/gtest_apply_schema.cpp b/test/gtest_apply_schema.cpp index a9a9bac..d730920 100644 --- a/test/gtest_apply_schema.cpp +++ b/test/gtest_apply_schema.cpp @@ -109,6 +109,28 @@ TEST(schema, nontrivial_options_default_value) std::cout << "log: \n" << server.getLog() << std::endl; } +TEST(schema, complex_case) +{ + YamlServer server = YamlServer({ROOT_DIR + "/test/schema/folder_schema"}, ROOT_DIR + "/test/yaml/complex_case.yaml"); + + std::cout << "before: \n" << server.getNode() << std::endl; + + server.addFolderSchema(ROOT_DIR + "/test/schema/complex_case"); + + EXPECT_TRUE(server.applySchema("Problem.schema")); + + std::cout << "after Problem.schema: \n" << server.getNode() << std::endl; + + std::cout << "log: \n" << server.getLog() << std::endl; + + bool is2D = server.getNode()["problem"]["dimension"].as() == 2; + EXPECT_TRUE(server.applySchema(is2D ? "Problem2d.schema" : "Problem3d.schema")); + + std::cout << "after Problem3d.schema: \n" << server.getNode() << std::endl; + + std::cout << "log: \n" << server.getLog() << std::endl; +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); diff --git a/test/schema/complex_case/MapBase.schema b/test/schema/complex_case/MapBase.schema new file mode 100644 index 0000000..dceb442 --- /dev/null +++ b/test/schema/complex_case/MapBase.schema @@ -0,0 +1,15 @@ +type: + _mandatory: true + _type: string + _doc: Type of the Map used in the problem. + +plugin: + _mandatory: true + _type: string + _doc: Name of the wolf plugin where the map type is implemented. + +landmarks: + _mandatory: false + _type: derived[] + _base: LandmarkBase + _doc: Sequence of derived landmarks. \ No newline at end of file diff --git a/test/schema/complex_case/MotionProvider.schema b/test/schema/complex_case/MotionProvider.schema new file mode 100644 index 0000000..3881ba7 --- /dev/null +++ b/test/schema/complex_case/MotionProvider.schema @@ -0,0 +1,9 @@ +state_provider: + _mandatory: true + _type: bool + _doc: If the processor is used by the problem as provider of state. + +state_provider_order: + _mandatory: $state_provider + _type: double + _doc: The order number of this processor when problem gets the state (only used if state_provider = true). Two processors cannot have the same priority (if so, when installing the second is increased). \ No newline at end of file diff --git a/test/schema/complex_case/None.schema b/test/schema/complex_case/None.schema new file mode 100644 index 0000000..1271241 --- /dev/null +++ b/test/schema/complex_case/None.schema @@ -0,0 +1,5 @@ +type: + _mandatory: false + _options: ["None"] + _type: string + _doc: Nothing to say here diff --git a/test/schema/complex_case/Problem.schema b/test/schema/complex_case/Problem.schema new file mode 100644 index 0000000..f681a49 --- /dev/null +++ b/test/schema/complex_case/Problem.schema @@ -0,0 +1,29 @@ +problem: + tree_manager: + _type: derived + _base: TreeManagerBase.schema + _mandatory: true + _doc: Tree manager parameters + dimension: + _type: int + _mandatory: true + _options: [2, 3] + _doc: "Dimension of the problem. '2' for 2D or '3' for 3D" +map: + _type: derived + _base: MapBase.schema + _mandatory: false + _default: + type: MapBase + plugin: core + _doc: The map used in the wolf problem. +sensors: + _type: derived[] + _base: SensorBase.schema + _mandatory: true + _doc: A sequence of all the sensors. +processors: + _type: derived[] + _base: ProcessorBaseWithSensor.schema + _mandatory: true + _doc: A sequence of all the processors. diff --git a/test/schema/complex_case/Problem3d.schema b/test/schema/complex_case/Problem3d.schema new file mode 100644 index 0000000..b4f875f --- /dev/null +++ b/test/schema/complex_case/Problem3d.schema @@ -0,0 +1,20 @@ +follow: Problem.schema +problem: + first_frame: + P: + _mandatory: false + _type: StateP3d + _doc: "specification for the first frame position state" + O: + _mandatory: false + _type: StateO3d + _doc: "specification for the first frame orientation state" + V: + _mandatory: false + _type: StateV3d + _doc: "specification for the first frame linear velocity state" + dimension: + _type: int + _mandatory: true + _options: [3] + _doc: "Dimension of the problem: '3' for 3D" \ No newline at end of file diff --git a/test/schema/complex_case/ProcessorBase.schema b/test/schema/complex_case/ProcessorBase.schema new file mode 100644 index 0000000..51f801a --- /dev/null +++ b/test/schema/complex_case/ProcessorBase.schema @@ -0,0 +1,22 @@ +follow: TypeAndPlugin.schema + +name: + _mandatory: true + _type: string + _doc: The processor's name. It has to be unique. + +time_tolerance: + _mandatory: true + _type: double + _doc: Maximum time difference between a Keyframe time stamp and a particular Capture of this processor to allow assigning this Capture to the Keyframe. [s]. + +keyframe_vote: + voting_active: + _mandatory: true + _type: bool + _doc: If the processor is allowed to decide to create a frame. + +apply_loss_function: + _mandatory: true + _type: bool + _doc: If the factors created by the processor have loss function. \ No newline at end of file diff --git a/test/schema/complex_case/ProcessorBaseWithSensor.schema b/test/schema/complex_case/ProcessorBaseWithSensor.schema new file mode 100644 index 0000000..41f0c13 --- /dev/null +++ b/test/schema/complex_case/ProcessorBaseWithSensor.schema @@ -0,0 +1,6 @@ +follow: ProcessorBase.schema + +sensor_name: + _mandatory: true + _type: string + _doc: The name of the sensor corresponding to this processor. \ No newline at end of file diff --git a/test/schema/complex_case/ProcessorMotion.schema b/test/schema/complex_case/ProcessorMotion.schema new file mode 100644 index 0000000..6f4c5b1 --- /dev/null +++ b/test/schema/complex_case/ProcessorMotion.schema @@ -0,0 +1,23 @@ +follow: ProcessorBase.schema +follow: MotionProvider.schema +keyframe_vote: + max_time_span: + _mandatory: $voting_active + _type: double + _doc: Time threshold to create a new frame [s]. + max_buff_length: + _mandatory: $voting_active + _type: unsigned int + _doc: Maximum size of the buffer of motions. + max_dist_traveled: + _mandatory: $voting_active + _type: double + _doc: Distance traveled threshold to create a new frame [m]. + max_angle_turned: + _mandatory: $voting_active + _type: double + _doc: Angle turned threshold to create a new frame [rad]. +unmeasured_perturbation_std: + _mandatory: true + _type: double + _doc: Noise (standard deviation) of the integrated movement in the not observed directions. \ No newline at end of file diff --git a/test/schema/complex_case/ProcessorOdom3d.schema b/test/schema/complex_case/ProcessorOdom3d.schema new file mode 100644 index 0000000..3823a08 --- /dev/null +++ b/test/schema/complex_case/ProcessorOdom3d.schema @@ -0,0 +1 @@ +follow: ProcessorMotion.schema \ No newline at end of file diff --git a/test/schema/complex_case/SensorBase.schema b/test/schema/complex_case/SensorBase.schema new file mode 100644 index 0000000..e9aa53f --- /dev/null +++ b/test/schema/complex_case/SensorBase.schema @@ -0,0 +1,6 @@ +follow: TypeAndPlugin.schema + +name: + _mandatory: true + _type: string + _doc: The sensor's name. It has to be unique. \ No newline at end of file diff --git a/test/schema/complex_case/SensorOdom3d.schema b/test/schema/complex_case/SensorOdom3d.schema new file mode 100644 index 0000000..5a2f1c1 --- /dev/null +++ b/test/schema/complex_case/SensorOdom3d.schema @@ -0,0 +1,32 @@ +follow: SensorBase.schema + +k_disp_to_disp: + _mandatory: true + _type: double + _doc: ratio of displacement variance to displacement, for odometry noise calculation. + +k_disp_to_rot: + _mandatory: true + _type: double + _doc: ratio of displacement variance to rotation, for odometry noise calculation. + +k_rot_to_rot: + _mandatory: true + _type: double + _doc: ratio of rotation variance to rotation, for odometry noise calculation. + +min_disp_var: + _mandatory: true + _type: double + _doc: minimum displacement variance, for odometry noise calculation. + +min_rot_var: + _mandatory: true + _type: double + _doc: minimum rotation variance, for odometry noise calculation. + +states: + P: + follow: StateSensorP3d.schema + O: + follow: StateSensorO3d.schema \ No newline at end of file diff --git a/test/schema/complex_case/StateO3d.schema b/test/schema/complex_case/StateO3d.schema new file mode 100644 index 0000000..30ac4c6 --- /dev/null +++ b/test/schema/complex_case/StateO3d.schema @@ -0,0 +1,22 @@ +type: + _type: string + _mandatory: false + _value: StateQuaternion + _doc: "The type of the state for orientation in 3D: StateQuaternion. Not required to be filled by the user" + +value: + _type: Vector4d + _mandatory: true + _doc: A vector containing the quaternion values (x, y, z, w) + +prior: + mode: + _type: string + _mandatory: true + _options: ["fix", "factor", "initial_guess"] + _doc: Can be 'factor' to add an absolute factor (with covariance defined in 'factor_std'), 'fix' to set the values constant or 'initial_guess' to just set the values. + + factor_std: + _type: Vector3d + _mandatory: $mode == 'factor' + _doc: A vector containing the stdev values of the noise of the factor, i.e. the sqrt of the diagonal elements of the covariance matrix [rad]. \ No newline at end of file diff --git a/test/schema/complex_case/StateP3d.schema b/test/schema/complex_case/StateP3d.schema new file mode 100644 index 0000000..d62b95f --- /dev/null +++ b/test/schema/complex_case/StateP3d.schema @@ -0,0 +1,22 @@ +type: + _type: string + _mandatory: false + _value: StatePoint3d + _doc: "The type of the state for position in 3D: StatePoint3d. Not required to be filled by the user" + +value: + _type: Vector3d + _mandatory: true + _doc: A vector containing the position (x, y, z) [m]. + +prior: + mode: + _type: string + _mandatory: true + _options: ["fix", "factor", "initial_guess"] + _doc: Can be 'factor' to add an absolute factor (with covariance defined in 'factor_std'), 'fix' to set the values constant or 'initial_guess' to just set the values. + + factor_std: + _type: Vector3d + _mandatory: $mode == 'factor' + _doc: A vector containing the stdev values of the noise of the factor, i.e. the sqrt of the diagonal elements of the covariance matrix [m]. \ No newline at end of file diff --git a/test/schema/complex_case/StateSensorO3d.schema b/test/schema/complex_case/StateSensorO3d.schema new file mode 100644 index 0000000..aefcaa8 --- /dev/null +++ b/test/schema/complex_case/StateSensorO3d.schema @@ -0,0 +1,26 @@ +dynamic: + _type: bool + _mandatory: true + _doc: If the orientation is dynamic, i.e. it changes along time. + +value: + _type: Vector4d + _mandatory: true + _doc: A vector containing the quaternion values (x, y, z, w) + +prior: + mode: + _type: string + _mandatory: true + _options: ["fix", "factor", "initial_guess"] + _doc: Can be 'factor' to add an absolute factor (with covariance defined in 'factor_std'), 'fix' to set the values constant or 'initial_guess' to just set the values. + + factor_std: + _type: Vector3d + _mandatory: $mode == 'factor' + _doc: A vector containing the stdev values of the noise of the factor, i.e. the sqrt of the diagonal elements of the covariance matrix [rad]. + +drift_std: + _type: Vector3d + _mandatory: false + _doc: A vector containing the stdev values of the noise of the drift factor per second (only if dynamic==true), i.e. the sqrt of the diagonal elements of the covariance matrix [rad/sqrt(s)]. \ No newline at end of file diff --git a/test/schema/complex_case/StateSensorP3d.schema b/test/schema/complex_case/StateSensorP3d.schema new file mode 100644 index 0000000..c4fed2f --- /dev/null +++ b/test/schema/complex_case/StateSensorP3d.schema @@ -0,0 +1,26 @@ +dynamic: + _type: bool + _mandatory: true + _doc: If the position is dynamic, i.e. it changes along time. + +value: + _type: Vector3d + _mandatory: true + _doc: A vector containing the position (x, y, z) [m]. + +prior: + mode: + _type: string + _mandatory: true + _options: ["fix", "factor", "initial_guess"] + _doc: Can be 'factor' to add an absolute factor (with covariance defined in 'factor_std'), 'fix' to set the values constant or 'initial_guess' to just set the values. + + factor_std: + _type: Vector3d + _mandatory: $mode == 'factor' + _doc: A vector containing the stdev values of the noise of the factor, i.e. the sqrt of the diagonal elements of the covariance matrix [m]. + +drift_std: + _type: Vector3d + _mandatory: false + _doc: A vector containing the stdev values of the noise of the drift factor per second (only if dynamic==true) i.e. the sqrt of the diagonal elements of the covariance matrix [m/sqrt(s)]. \ No newline at end of file diff --git a/test/schema/complex_case/StateV3d.schema b/test/schema/complex_case/StateV3d.schema new file mode 100644 index 0000000..158fe5b --- /dev/null +++ b/test/schema/complex_case/StateV3d.schema @@ -0,0 +1,22 @@ +type: + _type: string + _mandatory: false + _value: StateVector3d + _doc: "The type of the state for linear velocity in 3D: StateVector3d. Not required to be filled by the user" + +value: + _type: Vector3d + _mandatory: true + _doc: A vector containing the linear velocity components (x, y, z) [m]. + +prior: + mode: + _type: string + _mandatory: true + _options: ["fix", "factor", "initial_guess"] + _doc: Can be 'factor' to add an absolute factor (with covariance defined in 'factor_std'), 'fix' to set the values constant or 'initial_guess' to just set the values. + + factor_std: + _type: Vector3d + _mandatory: $mode == 'factor' + _doc: A vector containing the stdev values of the noise of the factor, i.e. the sqrt of the diagonal elements of the covariance matrix [m]. \ No newline at end of file diff --git a/test/schema/complex_case/TreeManagerBase.schema b/test/schema/complex_case/TreeManagerBase.schema new file mode 100644 index 0000000..8cf6fdd --- /dev/null +++ b/test/schema/complex_case/TreeManagerBase.schema @@ -0,0 +1,4 @@ +type: + _mandatory: true + _type: string + _doc: Type of the TreeManager. To keep all frames, use "none". \ No newline at end of file diff --git a/test/schema/complex_case/TypeAndPlugin.schema b/test/schema/complex_case/TypeAndPlugin.schema new file mode 100644 index 0000000..1a98e1d --- /dev/null +++ b/test/schema/complex_case/TypeAndPlugin.schema @@ -0,0 +1,9 @@ +type: + _mandatory: true + _type: string + _doc: The class name + +plugin: + _mandatory: true + _type: string + _doc: plugin where the class is implemented diff --git a/test/yaml/complex_case.yaml b/test/yaml/complex_case.yaml new file mode 100644 index 0000000..928c72a --- /dev/null +++ b/test/yaml/complex_case.yaml @@ -0,0 +1,55 @@ +problem: + dimension: 3 + first_frame: + P: + value: [0,0,0] + prior: + mode: "factor" + factor_std: [0.31, 0.31, 0.31] + O: + value: [0,0,0,1] + prior: + mode: "factor" + factor_std: [0.31, 0.31, 0.31] + tree_manager: + type: "None" +sensors: + - + type: "SensorOdom3d" + name: "odom" + plugin: "core" + k_disp_to_disp: 0.1 + k_disp_to_rot: 0.1 + k_rot_to_rot: 0.1 + min_disp_var: 0.1 + min_rot_var: 0.1 + states: + P: + value: [1,2,3] + prior: + mode: fix + dynamic: false + O: + value: [0,0,0,1] + prior: + mode: "fix" + dynamic: false +processors: + - + type: "ProcessorOdom3d" + name: "my_proc_odom3d" + sensor_name: "odom" + plugin: "core" + apply_loss_function: false + time_tolerance: 0.01 # seconds + keyframe_vote: + voting_active: true + max_time_span: 1.95 # seconds + max_buff_length: 999 # motion deltas + max_dist_traveled: 999 # meters + max_angle_turned: 999 # radians (1 rad approx 57 deg, approx 60 deg) + + unmeasured_perturbation_std: 0.00111 + + state_provider: true + state_provider_order: 1