Skip to content

Commit 5e91938

Browse files
aaronchongthAddisu Z. Taddese
andauthored
Support printing sdf poses in degrees and allow snapping to commonly used angles (#689)
* Ruby option to print in_degrees or snap_to_degrees Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Basic PrintConfig added Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * PrintConfig gets passed into printing implementations of Element and Param Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding basic test for print options Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Reverting to PrintConfig with basic API Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Moved creation of PrintConfig into ign functions Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Param value GetPoseAsString and tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Moved attribute painting to its own function, fixed test strings Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added basic tests for pose rotation input as quaternions Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Using different flags for ign sdf -p, allow snapping to different values Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Disabling test on windows, fixing comment Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Remove stale function, fixed linting Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding tolerance as a argument, added tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Use 3 spaces when changing rotation formats or snapping to degrees Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added check for tolerance larger than snapping interval Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Moving PrintAttributes to ElementPrivate to remain ABI stability Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Using true/false instead of 1/0 Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Remove use of SDF_ASSERT in GetAsString Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added tests for //include/pose Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding parsing passing test for empty quat_xyzw pose Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added check for default string values to be modified when rotation_format is defined Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Reparsing translates default value into string to be used if values have not been assigned to param Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Using StringFromValueImpl for getting strings from all ParamVariants Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Refactor pose string from value into its own function Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Fixing casting erroerror, added documentation and tests for tolerance < interval Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Correcting stale comments Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Fixing snapToInterval math, added more tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Removed unneeded visibility macro Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding return documentation and using const reference to variant instead of pointer Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Returning string directly, removing stale _config, reverting strValue to nullopt Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Remove use of assertions Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Suggested changes to #729 (#748) Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org> * Using three space delimiter between position and rotation if attributes are set Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added comment regarding use of default PrintConfig in Reparse Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding equality comparison for PrintConfig Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Removed stale include Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Uniied string and value parsing behavior, and modified necessary tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Overloaded function to maintain ABI stability Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Fixing missing space in test for exec command Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Adding comment regarding attributeExceptions Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Indenting help message, adding test for shuffling command flags Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Modifying cmd flag shuffling test to handling flags with arguments too Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Removed Get from PrintConfig getter functions Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Using std optional's converting constructor Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Modified snapToInterval implementation, added test Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added bool type specific value parser, values are parsed using ParamStreamer by default Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Reverting all unnecessary changes made in sdf12 to old tests Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added comparison for PreserveIncludes Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Check for 'type' attribute in unknown elements as well, in order to parse booleans into true/false, instead of 1/0 Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Only checking for pose related PrintConfig options for returning string instead of default PrintConfig Signed-off-by: Aaron Chong <aaronchongth@gmail.com> * Added comment regarding sanitizing -0 in test outputs Signed-off-by: Aaron Chong <aaronchongth@gmail.com> Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
1 parent de356cd commit 5e91938

27 files changed

Lines changed: 1262 additions & 138 deletions

include/sdf/Element.hh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ namespace sdf
199199
/// \param[in] _prefix String value to prefix to the output.
200200
/// \param[in] _includeDefaultElements flag to include default elements.
201201
/// \param[in] _includeDefaultAttributes flag to include default attributes.
202-
/// \param[in] _config Configuration for printing the values.
202+
/// \param[in] _config Configuration for converting to string.
203203
/// \return The string representation.
204204
public: std::string ToString(
205205
const std::string &_prefix,
@@ -589,7 +589,7 @@ namespace sdf
589589
/// \param[in] _includeDefaultElements flag to include default elements.
590590
/// \param[in] _includeDefaultAttributes flag to include default attributes.
591591
/// \param[in] _config Configuration for printing values.
592-
/// \param[out] _out the std::ostreamstream to write output to.
592+
/// \param[out] _out the std::ostringstream to write output to.
593593
private: void PrintValuesImpl(const std::string &_prefix,
594594
bool _includeDefaultElements,
595595
bool _includeDefaultAttributes,
@@ -685,6 +685,14 @@ namespace sdf
685685

686686
/// \brief XML path of this element.
687687
public: std::string xmlPath;
688+
689+
/// \brief Generate the string (XML) for the attributes.
690+
/// \param[in] _includeDefaultAttributes flag to include default attributes.
691+
/// \param[in] _config Configuration for printing attributes.
692+
/// \param[out] _out the std::ostringstream to write output to.
693+
public: void PrintAttributes(bool _includeDefaultAttributes,
694+
const PrintConfig &_config,
695+
std::ostringstream &_out) const;
688696
};
689697

690698
///////////////////////////////////////////////

include/sdf/Param.hh

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -401,17 +401,34 @@ namespace sdf
401401
const std::string &_valueStr,
402402
ParamVariant &_valueToSet) const;
403403

404-
/// \brief Method used to get the string representation from a ParamVariant
404+
/// \brief Method used to get the string representation from a ParamVariant,
405+
/// or the string that was used to set it.
405406
/// \param[in] _config Print configuration for the string output
406407
/// \param[in] _typeName The data type of the value
407408
/// \param[in] _value The value
408-
/// \param[in] _valueStr The string representation of the value
409-
/// \return True if the string was successfully retrieved from the value,
410-
/// false otherwise.
411-
public: bool StringFromValueImpl(const PrintConfig &_config,
412-
const std::string &_typeName,
413-
const ParamVariant &_value,
414-
std::string &_valueStr) const;
409+
/// \param[out] _valueStr The output string.
410+
/// \return True if the string was successfully retrieved, false otherwise.
411+
public: bool StringFromValueImpl(
412+
const PrintConfig &_config,
413+
const std::string &_typeName,
414+
const ParamVariant &_value,
415+
std::string &_valueStr) const;
416+
417+
/// \brief Method used to get the string representation from a ParamVariant,
418+
/// or the string that was used to set it.
419+
/// \param[in] _config Print configuration for the string output
420+
/// \param[in] _typeName The data type of the value
421+
/// \param[in] _value The value
422+
/// \param[in] _orignalStr The original string that was used to set the
423+
/// value. A nullopt can be passed in if it is not available.
424+
/// \param[out] _valueStr The output string.
425+
/// \return True if the string was successfully retrieved, false otherwise.
426+
public: bool StringFromValueImpl(
427+
const PrintConfig &_config,
428+
const std::string &_typeName,
429+
const ParamVariant &_value,
430+
const std::optional<std::string> &_originalStr,
431+
std::string &_valueStr) const;
415432

416433
/// \brief Data type to string mapping
417434
/// \return The type as a string, empty string if unknown type

include/sdf/PrintConfig.hh

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SDF_PRINTCONFIG_HH_
1818
#define SDF_PRINTCONFIG_HH_
1919

20+
#include <optional>
2021
#include <ignition/utils/ImplPtr.hh>
2122

2223
#include "sdf/sdf_config.h"
@@ -29,9 +30,41 @@ namespace sdf
2930
/// This class contains configuration options for printing elements.
3031
class SDFORMAT_VISIBLE PrintConfig
3132
{
32-
/// \brief Default constructor.
33+
/// \brief Default constructor. All options are set to false by default.
3334
public: PrintConfig();
3435

36+
/// \brief Sets the option for printing pose rotations in degrees if true,
37+
/// otherwise they will be printed as radians by default.
38+
/// \param[in] _value Whether to print pose rotations in degrees.
39+
public: void SetRotationInDegrees(bool _value);
40+
41+
/// \brief Returns whether or not pose rotations should be printed in
42+
/// degrees.
43+
/// \return True if pose rotations are printed in degrees, false otherwise.
44+
public: bool RotationInDegrees() const;
45+
46+
/// \brief Sets the option for printing pose rotation in degrees as well as
47+
/// snapping the rotation to the desired interval, with the provided
48+
/// tolerance.
49+
/// \param[in] _interval Degrees interval to snap to, this value must be
50+
/// larger than 0, and less than or equal to 360.
51+
/// \param[in] _tolerance Tolerance which snapping occurs, this value must
52+
/// be larger than 0, less than 360, and less than the provided interval.
53+
/// \return True, unless any of the provided values are not valid.
54+
public: bool SetRotationSnapToDegrees(unsigned int _interval,
55+
double _tolerance);
56+
57+
/// \brief Returns the current degree value that pose rotations will snap to
58+
/// when printed.
59+
/// \return The assigned degrees interval value to snap to. If it has not
60+
/// been assigned, a nullopt will be returned.
61+
public: std::optional<unsigned int> RotationSnapToDegrees() const;
62+
63+
/// \brief Returns the tolerance for snapping degree values when printed.
64+
/// \return The assigned tolerance value which allows snapping to happen. If
65+
/// it has not been assigned, a nullopt will be returned.
66+
public: std::optional<double> RotationSnapTolerance() const;
67+
3568
/// \brief Set print config to preserve <include> tags.
3669
/// \param[in] _preserve True to preserve <include> tags.
3770
/// False to expand included model.
@@ -42,6 +75,11 @@ namespace sdf
4275
/// False if they are to be expanded.
4376
public: bool PreserveIncludes() const;
4477

78+
/// \brief Return true if both PrintConfig objects contain the same values.
79+
/// \param[in] _config PrintConfig to compare.
80+
/// \return True if 'this' == _config.
81+
public: bool operator==(const PrintConfig &_config) const;
82+
4583
/// \brief Private data pointer.
4684
IGN_UTILS_IMPL_PTR(dataPtr)
4785
};

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ if (BUILD_SDF_TEST)
136136
Pbr_TEST.cc
137137
Physics_TEST.cc
138138
Plugin_TEST.cc
139-
PrintConfig_TEST.cc
140139
Plane_TEST.cc
140+
PrintConfig_TEST.cc
141141
Root_TEST.cc
142142
Scene_TEST.cc
143143
SemanticPose_TEST.cc

src/Element.cc

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ void Element::PrintDocLeftPane(std::string &_html, int _spacing,
499499
_html += "</div>\n";
500500
}
501501

502+
/////////////////////////////////////////////////
502503
void Element::PrintValuesImpl(const std::string &_prefix,
503504
bool _includeDefaultElements,
504505
bool _includeDefaultAttributes,
@@ -513,22 +514,7 @@ void Element::PrintValuesImpl(const std::string &_prefix,
513514
{
514515
_out << _prefix << "<" << this->dataPtr->name;
515516

516-
Param_V::const_iterator aiter;
517-
for (aiter = this->dataPtr->attributes.begin();
518-
aiter != this->dataPtr->attributes.end(); ++aiter)
519-
{
520-
// Only print attribute values if they were set
521-
// TODO(anyone): GetRequired is added here to support up-conversions where
522-
// a new required attribute with a default value is added. We would have
523-
// better separation of concerns if the conversion process set the
524-
// required attributes with their default values.
525-
if ((*aiter)->GetSet() || (*aiter)->GetRequired() ||
526-
_includeDefaultAttributes)
527-
{
528-
_out << " " << (*aiter)->GetKey() << "='"
529-
<< (*aiter)->GetAsString(_config) << "'";
530-
}
531-
}
517+
this->dataPtr->PrintAttributes(_includeDefaultAttributes, _config, _out);
532518

533519
if (this->dataPtr->elements.size() > 0)
534520
{
@@ -560,6 +546,50 @@ void Element::PrintValuesImpl(const std::string &_prefix,
560546
}
561547
}
562548

549+
/////////////////////////////////////////////////
550+
void ElementPrivate::PrintAttributes(bool _includeDefaultAttributes,
551+
const PrintConfig &_config,
552+
std::ostringstream &_out) const
553+
{
554+
// Attribute exceptions are used in the event of a non-default PrintConfig
555+
// which modifies the Attributes of this Element that are printed out. The
556+
// modifications to an Attribute by a PrintConfig will overwrite the original
557+
// existing Attribute when this Element is printed.
558+
std::set<std::string> attributeExceptions;
559+
if (this->name == "pose")
560+
{
561+
if (_config.RotationInDegrees() || _config.RotationSnapToDegrees())
562+
{
563+
attributeExceptions.insert("degrees");
564+
_out << " " << "degrees='true'";
565+
566+
attributeExceptions.insert("rotation_format");
567+
_out << " " << "rotation_format='euler_rpy'";
568+
}
569+
}
570+
571+
Param_V::const_iterator aiter;
572+
for (aiter = this->attributes.begin();
573+
aiter != this->attributes.end(); ++aiter)
574+
{
575+
// Only print attribute values if they were set
576+
// TODO(anyone): GetRequired is added here to support up-conversions where
577+
// a new required attribute with a default value is added. We would have
578+
// better separation of concerns if the conversion process set the
579+
// required attributes with their default values.
580+
if ((*aiter)->GetSet() || (*aiter)->GetRequired() ||
581+
_includeDefaultAttributes)
582+
{
583+
const std::string key = (*aiter)->GetKey();
584+
const auto it = attributeExceptions.find(key);
585+
if (it == attributeExceptions.end())
586+
{
587+
_out << " " << key << "='" << (*aiter)->GetAsString(_config) << "'";
588+
}
589+
}
590+
}
591+
}
592+
563593
/////////////////////////////////////////////////
564594
void Element::PrintValues(std::string _prefix, const PrintConfig &_config) const
565595
{

0 commit comments

Comments
 (0)