Skip to content

Commit

Permalink
--Configurations : Expand and unify vector/array-backed value handling (
Browse files Browse the repository at this point in the history
#2395)

* --manage arrays and array-like key-value stores consistently
* --add vector-of-floats specialization to vector value set/get
* --update current vector-based fields to be handled consistently as subcfgs
  • Loading branch information
jturner65 authored May 13, 2024
1 parent 1db01c7 commit b8d5ef8
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 228 deletions.
100 changes: 71 additions & 29 deletions src/esp/core/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,41 +490,36 @@ int Configuration::loadOneConfigFromJson(int numConfigSettings,
} else {
// The array does not match any currently supported magnum
// objects, so place in indexed subconfig of values.
// decrement count by 1 - the recursive subgroup load will count all the
// values.
--numConfigSettings;
// create a new subgroup
std::shared_ptr<core::config::Configuration> subGroupPtr =
getSubconfigCopy<core::config::Configuration>(key);

for (size_t i = 0; i < jsonObj.Size(); ++i) {
const std::string subKey =
Cr::Utility::formatString("{}_{:.03d}", key, i);
numConfigSettings += subGroupPtr->loadOneConfigFromJson(
numConfigSettings, subKey, jsonObj[i]);
}
setSubconfigPtr<core::config::Configuration>(key, subGroupPtr);
editSubconfig<core::config::Configuration>(key);
// load array into subconfig
numConfigSettings += subGroupPtr->loadFromJsonArray(jsonObj);
}
// value in array is a number of specified length, else it is a string, an
// object or a nested array
} else {
// decrement count by 1 - the recursive subgroup load will count all the
// values.
--numConfigSettings;
// create a new subgroup
std::shared_ptr<core::config::Configuration> subGroupPtr =
getSubconfigCopy<core::config::Configuration>(key);

for (size_t i = 0; i < jsonObj.Size(); ++i) {
const std::string subKey =
Cr::Utility::formatString("{}_{:.03d}", key, i);
numConfigSettings += subGroupPtr->loadOneConfigFromJson(
numConfigSettings, subKey, jsonObj[i]);
}
setSubconfigPtr<core::config::Configuration>(key, subGroupPtr);
editSubconfig<core::config::Configuration>(key);
// load array into subconfig
numConfigSettings += subGroupPtr->loadFromJsonArray(jsonObj);
}
} else if (jsonObj.IsObject()) {
// support nested objects
// create a new subgroup
// decrement count by 1 - the recursive subgroup load will count all the
// values.
--numConfigSettings;
std::shared_ptr<core::config::Configuration> subGroupPtr =
getSubconfigCopy<core::config::Configuration>(key);
editSubconfig<core::config::Configuration>(key);
numConfigSettings += subGroupPtr->loadFromJson(jsonObj);
// save subgroup's subgroup configuration in original config
setSubconfigPtr<core::config::Configuration>(key, subGroupPtr);
//
} else {
// TODO support other types?
Expand All @@ -535,18 +530,35 @@ int Configuration::loadOneConfigFromJson(int numConfigSettings,
"skipping this key.";
}
return numConfigSettings;
} // namespace config
} // Configuration::loadOneConfigFromJson

int Configuration::loadFromJsonArray(const io::JsonGenericValue& jsonObj) {
// Passed config is found to be a json array, so load every value into this
// configuration with key as string version of index.
int numConfigSettings = 0;
for (size_t i = 0; i < jsonObj.Size(); ++i) {
const std::string subKey = Cr::Utility::formatString("{:.03d}", i);
numConfigSettings =
loadOneConfigFromJson(numConfigSettings, subKey, jsonObj[i]);
}
return numConfigSettings;
} // Configuration::loadFromJsonArray

int Configuration::loadFromJson(const io::JsonGenericValue& jsonObj) {
// count number of valid user config settings found
int numConfigSettings = 0;
for (rapidjson::Value::ConstMemberIterator it = jsonObj.MemberBegin();
it != jsonObj.MemberEnd(); ++it) {
// for each key, attempt to parse
const std::string key{it->name.GetString()};

numConfigSettings +=
loadOneConfigFromJson(numConfigSettings, key, it->value);
if (jsonObj.IsArray()) {
// load array into this Configuration
numConfigSettings = loadFromJsonArray(jsonObj);
} else {
for (rapidjson::Value::ConstMemberIterator it = jsonObj.MemberBegin();
it != jsonObj.MemberEnd(); ++it) {
// for each key, attempt to parse
const std::string key{it->name.GetString()};
// load value and attach it to given key
numConfigSettings =
loadOneConfigFromJson(numConfigSettings, key, it->value);
}
}
return numConfigSettings;
} // Configuration::loadFromJson
Expand Down Expand Up @@ -621,6 +633,36 @@ io::JsonGenericValue Configuration::writeToJsonObject(
return jsonObj;
} // writeToJsonObject

template <>

std::vector<float> Configuration::getSubconfigValsOfTypeInVector(
const std::string& subCfgName) const {
const ConfigValType desiredType = configValTypeFor<double>();
const auto subCfg = getSubconfigView(subCfgName);
const auto& subCfgTags = subCfg->getKeysByType(desiredType, true);
std::vector<float> res;
res.reserve(subCfgTags.size());
for (const auto& tag : subCfgTags) {
res.emplace_back(static_cast<float>(subCfg->get<double>(tag)));
}
return res;
} // getSubconfigValsOfTypeInVector float specialization

template <>
void Configuration::setSubconfigValsOfTypeInVector(
const std::string& subCfgName,
const std::vector<float>& values) {
auto subCfg = editSubconfig<Configuration>(subCfgName);
// remove existing values in subconfig of specified type
subCfg->removeAllOfType<double>();
// add new values, building string key from index in values array of each
// value.
for (std::size_t i = 0; i < values.size(); ++i) {
const std::string& key = Cr::Utility::formatString("{:.03d}", i);
subCfg->set(key, values[i]);
}
} // setSubconfigValsOfTypeInVector float specialization

/**
* @brief Retrieves a shared pointer to a copy of the subConfig @ref
* esp::core::config::Configuration that has the passed @p name . This will
Expand Down
54 changes: 38 additions & 16 deletions src/esp/core/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,7 @@ class Configuration {
}
return res;
} // getSubconfigValsOfTypeInVector

/**
* @brief Set all values from vector of passed type into subconfig specified
* by given tag @p subCfgName as key-value pairs where the key is the index in
Expand Down Expand Up @@ -1055,7 +1056,8 @@ class Configuration {
const std::string& key = Cr::Utility::formatString("{:.03d}", i);
subCfg->set(key, values[i]);
}
}
} // setSubconfigValsOfTypeInVector

// ==================== load from and save to json =========================

/**
Expand Down Expand Up @@ -1152,20 +1154,6 @@ class Configuration {
void _clearAllValues() { valueMap_.clear(); }

protected:
/**
* @brief Process passed json object into this Configuration, using passed
* key.
*
* @param numVals number of values/configs loaded so far
* @param key key to use to search @p jsonObj and also to set value or
* subconfig within this Configuration.
* @return the number of total fields successfully loaded after this
* function executes.
*/
int loadOneConfigFromJson(int numVals,
const std::string& key,
const io::JsonGenericValue& jsonObj);

/**
* @brief Friend function. Checks if passed @p key is contained in @p
* config. Returns the highest level where @p key was found
Expand Down Expand Up @@ -1225,8 +1213,32 @@ class Configuration {
return result;
}

private:
/**
* @brief Map to hold configurations as subgroups
* @brief Process passed json object into this Configuration, using passed
* key.
*
* @param numVals number of values/configs loaded so far
* @param key key to use to search @p jsonObj and also to set value or
* subconfig within this Configuration.
* @return the number of total fields successfully loaded after this
* function executes.
*/
int loadOneConfigFromJson(int numVals,
const std::string& key,
const io::JsonGenericValue& jsonObj);

/**
* @brief Process passed json array into this Configuration.
*
* @param jsonObj The json object being treated as an array
* @return the number of elements loaded into this configuration from the
* source json array.
*/
int loadFromJsonArray(const io::JsonGenericValue& jsonObj);

/**
* @brief Map to hold Configurations as subgroups
*/
ConfigMapType configMap_{};

Expand All @@ -1235,6 +1247,7 @@ class Configuration {
*/
ValueMapType valueMap_{};

public:
ESP_SMART_POINTERS(Configuration)
}; // class Configuration

Expand All @@ -1244,6 +1257,15 @@ class Configuration {
MAGNUM_EXPORT Mn::Debug& operator<<(Mn::Debug& debug,
const Configuration& value);

template <>
std::vector<float> Configuration::getSubconfigValsOfTypeInVector(
const std::string& subCfgName) const;

template <>
void Configuration::setSubconfigValsOfTypeInVector(
const std::string& subCfgName,
const std::vector<float>& values);

/**
* @brief Retrieves a shared pointer to a copy of the subConfig @ref
* esp::core::config::Configuration that has the passed @p name . This will
Expand Down
31 changes: 14 additions & 17 deletions src/esp/metadata/attributes/SceneInstanceAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ SceneAOInstanceAttributes::SceneAOInstanceAttributes(const std::string& handle)
// Set render mode to be unspecified - if not set in instance json, use
// ao_config value
setRenderMode(getAORenderModeName(ArticulatedObjectRenderMode::Unspecified));
editSubconfig<Configuration>("initial_joint_pose");
editSubconfig<Configuration>("initial_joint_velocities");
}

SceneAOInstanceAttributes::SceneAOInstanceAttributes(
Expand All @@ -193,18 +195,22 @@ SceneAOInstanceAttributes::SceneAOInstanceAttributes(
setMassScale(aObjAttribs->getMassScale());
// Prepopulate user config to match attribs' user config.
overwriteWithConfig(aObjAttribs->getUserConfiguration());
editSubconfig<Configuration>("initial_joint_pose");
editSubconfig<Configuration>("initial_joint_velocities");
}

std::string SceneAOInstanceAttributes::getSceneObjInstanceInfoHeaderInternal()
const {
std::string infoHdr{"Base Type,Inertia Source,Link Order,Render Mode,"};
int iter = 0;
for (const auto& it : initJointPose_) {
const auto initJointPose = getInitJointPose();
for (const auto& it : initJointPose) {
Cr::Utility::formatInto(infoHdr, infoHdr.size(), "Init Pose {},",
std::to_string(iter++));
}
iter = 0;
for (const auto& it : initJointPose_) {
const auto initJointVel = getInitJointVelocities();
for (const auto& it : initJointVel) {
Cr::Utility::formatInto(infoHdr, infoHdr.size(), "Init Vel {},",
std::to_string(iter++));
}
Expand All @@ -219,14 +225,16 @@ std::string SceneAOInstanceAttributes::getSceneObjInstanceInfoInternal() const {
getAOInertiaSourceName(getInertiaSource()),
getAOLinkOrderName(getLinkOrder()),
getAORenderModeName(getRenderMode()));
for (const auto& it : initJointPose_) {
const auto initJointPose = getInitJointPose();
for (const auto& it : initJointPose) {
Cr::Utility::formatInto(initPoseStr, initPoseStr.size(), "{},",
std::to_string(it.second));
std::to_string(it));
}
Cr::Utility::formatInto(initPoseStr, initPoseStr.size(), "],[");
for (const auto& it : initJointPose_) {
const auto initJointVel = getInitJointVelocities();
for (const auto& it : initJointVel) {
Cr::Utility::formatInto(initPoseStr, initPoseStr.size(), "{},",
std::to_string(it.second));
std::to_string(it));
}
Cr::Utility::formatInto(initPoseStr, initPoseStr.size(), "]");

Expand All @@ -251,17 +259,6 @@ void SceneAOInstanceAttributes::writeValuesToJsonInternal(

writeValueToJson("auto_clamp_joint_limits", jsonObj, allocator);

// write out map where key is joint tag, and value is joint pose value.
if (!initJointPose_.empty()) {
io::addMember(jsonObj, "initial_joint_pose", initJointPose_, allocator);
}

// write out map where key is joint tag, and value is joint angular vel value.
if (!initJointVelocities_.empty()) {
io::addMember(jsonObj, "initial_joint_velocities", initJointVelocities_,
allocator);
}

} // SceneAOInstanceAttributes::writeValuesToJsonInternal

////////////////////////////////
Expand Down
Loading

0 comments on commit b8d5ef8

Please sign in to comment.