Description
Problem Statement
Parsing complex objects from JSON uses a __type
field inside the JSON to determine the C++ type. Conveniently, when registering the type with the JSON exporter, the template automatically infers a string to represent the type. (See tutorial page for how serialization is done and registered with BehaviorTree.CPP.)
C++ templates are infamous for their verbosity. Even something relatively svelte
std::vector<std::double>
hides default value complexity, and so gets converted to something verbose in its full name:
"std::vector<double, std::allocator<double> >"
This is what happens to some common ROS2 types (at least in humble
):
"geometry_msgs::msg::Pose_<std::allocator<void> >"
"geometry_msgs::msg::Quaternion_<std::allocator<void> >"
"geometry_msgs::msg::Transform_<std::allocator<void> >"
"geometry_msgs::msg::Vector3_<std::allocator<void> >"
"geometry_msgs::msg::Point_<std::allocator<void> >"
Issues caused
- It's verbose and ugly. These full template names aren't commonly used in C++ for a reason, and even the short ones are commonly abbreviated with aliases.
- It requires an exact string match, instead of merely valid C++. E.g. this does not get parsed
and fails silently in certain parts of the BehaviorTree.CPP stack, e.g.
{ grasp_pose": { "__type": "geometry_msgs::msg::Pose<std::allocator<void> >", "position": { "x": 1.307, "y": -2.127, "z": 0.5 }, "orientation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 } } }
ImportBlackBoardFromJSON()
skips over it, leaving you confused about why that blackboard entry is empty. - It is specific to C++. Currently, the
__type
field must match what BehaviorTree.CPP expects -- which could cause a name collision for other languages and libraries deserializing the same JSON. It is common in large systems to define types using some common schema language, e.g. ROS2 IDL, JSON schema, or protobuf, then generate the types in C++ and other languages. These serialization/schema languages have their own programming-language-independent notation for representing types, e.g.geometry_msgs/Transform
in ROS2 IDL, e.g. type hints (.NET docs)"Circle:http://schemas.datacontract.org/2004/07/MyApp.Shapes"
or"Circle:#MyApp.Shapes"
.
Requested solution
When registering JSON function, support a custom type name string.
Interface Change
Add an optional type_name
parameter to the BT::JsonExporter::addConverter()
functions and BT::RegisterJsonDefinition()
. E.g.
template <typename T>
inline void JsonExporter::addConverter()
becomes
template <typename T>
inline void JsonExporter::addConverter(const std::string& type_name="")
Behavior
If the type name is left blank, it behaves as it does currently, with BT::demangle()
's best effort to create a readable type name.
If the type name is provided, then it is used instead in the JSONExporter::type_names_
map.
Ideally, if called multiple times, it would register multiple names for the same type.
Discussion
This added freedom addresses all three issues. Application developers can:
- Can use short names in
__type
- Register several variations of the type name for less brittle JSON
- Use existing, language-non-specific type name conventions