Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add includes parameter #91

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Added `includes` parameter to `creo2urdf` to include additional yamls.

## [0.4.7] - 2024-04-09
- Made `creo2urdf` runnable from terminal

Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,18 @@ If the export process was successful, you should see three files": "bar.stl", "b

### YAML Parameter File
The YAML format is used to pass parameters to the plugin to customized the conversion process.
The parameter accepted by the plugin are documented in the following.
The parameters accepted by the plugin are documented in the following.

##### Include Parameters
The YAML can eventually include other YAML files using the `includes` parameter, if so, the included files are merged with the main file.
All internal groups are merged if they are maps, they are overwritten only if an element is not a map, taking precedence over the main file in case of conflicts.

> [!NOTE]
> The `includes` parameter is not mandatory, but if it is present, it must be a list of strings, containing relative path respect the directory of the main YAML file.

| Attribute name | Type | Default Value | Description |
|:----------------:|:---------:|:------------:|:-------------:|
| `includes` | List of strings | "" | List of paths relative to the main YAML directory |

##### Severity Parameters
| Attribute name | Type | Default Value | Description |
Expand Down
19 changes: 19 additions & 0 deletions src/creo2urdf/include/creo2urdf/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/RevoluteJoint.h>
#include <iDynTree/Model/FixedJoint.h>
#include <yaml-cpp/yaml.h>

/**
* @brief Small positive value used for numerical precision comparisons.
Expand Down Expand Up @@ -439,4 +440,22 @@ std::pair<bool, iDynTree::Transform> getTransformFromPart(pfcModel_ptr modelhdl,
*/
std::pair<bool, iDynTree::Direction> getAxisFromPart(pfcModel_ptr modelhdl, const std::string& axis_name, const std::string& link_frame_name, const array<double, 3>& scale);

/**
* @brief Extracts the folder path from a file path.
*
* @param filePath The file path from which to extract the folder path.
* @return std::string The folder path extracted from the input file path.
*/
std::string extractFolderPath(const std::string& filePath);

/**
* @brief Merge two YAML nodes, recursively.
*
* @param dest The destination YAML node.
* @param src The source YAML node.
* @return void
*
*/
void mergeYAMLNodes(YAML::Node& dest, const YAML::Node& src);

#endif // !UTILS_H
15 changes: 14 additions & 1 deletion src/creo2urdf/src/Creo2Urdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ void Creo2Urdf::OnCommand() {
m_yaml_path.clear();
m_csv_path.clear();
m_output_path.clear();
config = YAML::Node();
m_asm_model_ptr = nullptr;

return;
Expand Down Expand Up @@ -723,7 +724,19 @@ bool Creo2Urdf::loadYamlConfig(const std::string& filename)
{
try
{
config = YAML::LoadFile(filename);
auto config_temp = YAML::LoadFile(filename);
auto folder_path = extractFolderPath(filename);
if (config_temp["includes"].IsDefined() && config_temp["includes"].IsSequence()) {
for (const auto& include : config_temp["includes"]) {
auto include_filename = folder_path + include.as<std::string>();
auto include_config = YAML::LoadFile(include_filename);
mergeYAMLNodes(config, include_config);
}
}
else
{
config = config_temp;
}
}
catch (YAML::BadFile file_does_not_exist)
{
Expand Down
35 changes: 35 additions & 0 deletions src/creo2urdf/src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,38 @@ std::pair<bool, iDynTree::Direction> getAxisFromPart(pfcModel_ptr modelhdl, cons

return { true, axis_unit_vector };
}

std::string extractFolderPath(const std::string& filePath) {
auto found = std::find_if(filePath.rbegin(), filePath.rend(),
[](char c) { return c == '/' || c == '\\'; });

if (found != filePath.rend()) {
return std::string(filePath.begin(), found.base());
}
else {
return "";
}
}


void mergeYAMLNodes(YAML::Node& dest, const YAML::Node& src) {

for (const auto& item : src) {
std::string key = item.first.as<std::string>();
if (!dest[key]) {
// If the key doesn't exist in the destination node, simply add it
dest[key] = item.second;
}
else {
// If the key exists in the destination node, merge the values
// If both values are maps, recursively merge them
if (dest[key].IsMap() && item.second.IsMap()) {
mergeYAMLNodes(dest[key], item.second);
}
else {
// Otherwise, overwrite the value in the destination node
dest[key] = item.second;
}
}
}
}