Control Libraries 6.3.4
Loading...
Searching...
No Matches
bind_clproto.cpp
1#include "clproto_bindings.h"
2#include "parameter_container.h"
3
4#include <string>
5
6#include <state_representation/State.hpp>
7#include <state_representation/space/SpatialState.hpp>
8#include <state_representation/space/cartesian/CartesianState.hpp>
9#include <state_representation/space/cartesian/CartesianPose.hpp>
10#include <state_representation/space/cartesian/CartesianTwist.hpp>
11#include <state_representation/space/cartesian/CartesianWrench.hpp>
12#include <state_representation/space/Jacobian.hpp>
13#include <state_representation/space/joint/JointState.hpp>
14#include <state_representation/space/joint/JointPositions.hpp>
15#include <state_representation/space/joint/JointVelocities.hpp>
16#include <state_representation/space/joint/JointAccelerations.hpp>
17#include <state_representation/space/joint/JointTorques.hpp>
18#include <state_representation/geometry/Shape.hpp>
19#include <state_representation/geometry/Ellipsoid.hpp>
20
21using namespace clproto;
22using namespace state_representation;
23using namespace py_parameter;
24
25template<typename T>
26inline py::bytes encode_bytes(const T& object) {
27 return py::bytes(encode(object));
28}
29
30py::bytes encode_parameter_container(const ParameterContainer& container) {
31 switch (container.get_parameter_type()) {
32 case ParameterType::INT:
33 return py::bytes(encode(Parameter(container.get_name(), container.values.int_value)));
34 case ParameterType::INT_ARRAY:
35 return py::bytes(encode(Parameter(container.get_name(), container.values.int_array_value)));
36 case ParameterType::DOUBLE:
37 return py::bytes(encode(Parameter(container.get_name(), container.values.double_value)));
38 case ParameterType::DOUBLE_ARRAY:
39 return py::bytes(encode(Parameter(container.get_name(), container.values.double_array_value)));
40 case ParameterType::BOOL:
41 return py::bytes(encode(Parameter(container.get_name(), container.values.bool_value)));
42 case ParameterType::BOOL_ARRAY:
43 return py::bytes(encode(Parameter(container.get_name(), container.values.bool_array_value)));
44 case ParameterType::STRING:
45 return py::bytes(encode(Parameter(container.get_name(), container.values.string_value)));
46 case ParameterType::STRING_ARRAY:
47 return py::bytes(encode(Parameter(container.get_name(), container.values.string_array_value)));
48 case ParameterType::MATRIX:
49 return py::bytes(encode(Parameter(container.get_name(), container.values.matrix_value)));
50 case ParameterType::VECTOR:
51 return py::bytes(encode(Parameter(container.get_name(), container.values.vector_value)));
52 default:
53 throw std::invalid_argument("This StateType is not a valid Parameter.");
54 break;
55 }
56}
57
58py::object decode_parameter(const std::string& msg) {
59 py::object PyParameter = py::module_::import("state_representation").attr("Parameter");
60 switch (check_parameter_message_type(msg)) {
61 case ParameterMessageType::INT: {
62 auto param = decode<Parameter<int>>(msg);
63 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
64 }
65 case ParameterMessageType::INT_ARRAY: {
66 auto param = decode<Parameter<std::vector<int>>>(msg);
67 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
68 }
69 case ParameterMessageType::DOUBLE: {
70 auto param = decode<Parameter<double>>(msg);
71 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
72 }
73 case ParameterMessageType::DOUBLE_ARRAY: {
74 auto param = decode<Parameter<std::vector<double>>>(msg);
75 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
76 }
77 case ParameterMessageType::BOOL: {
78 auto param = decode<Parameter<bool>>(msg);
79 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
80 }
81 case ParameterMessageType::BOOL_ARRAY: {
82 auto param = decode<Parameter<std::vector<bool>>>(msg);
83 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
84 }
85 case ParameterMessageType::STRING: {
86 auto param = decode<Parameter<std::string>>(msg);
87 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
88 }
89 case ParameterMessageType::STRING_ARRAY: {
90 auto param = decode<Parameter<std::vector<std::string>>>(msg);
91 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
92 }
93 case ParameterMessageType::VECTOR: {
94 auto param = decode<Parameter<Eigen::VectorXd>>(msg);
95 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
96 }
97 case ParameterMessageType::MATRIX: {
98 auto param = decode<Parameter<Eigen::MatrixXd>>(msg);
99 return PyParameter(param.get_name(), py::cast(param.get_value()), param.get_parameter_type());
100 }
101 default:
102 throw std::invalid_argument("The message is not a valid encoded Parameter.");
103 break;
104 }
105}
106
107void parameter_message_type(py::module_& m) {
108 py::enum_<ParameterMessageType>(m, "ParameterMessageType")
109 .value("UNKNOWN_PARAMETER", ParameterMessageType::UNKNOWN_PARAMETER)
110 .value("INT", ParameterMessageType::INT)
111 .value("INT_ARRAY", ParameterMessageType::INT_ARRAY)
112 .value("DOUBLE", ParameterMessageType::DOUBLE)
113 .value("DOUBLE_ARRAY", ParameterMessageType::DOUBLE_ARRAY)
114 .value("BOOL", ParameterMessageType::BOOL)
115 .value("BOOL_ARRAY", ParameterMessageType::BOOL_ARRAY)
116 .value("STRING", ParameterMessageType::STRING)
117 .value("STRING_ARRAY", ParameterMessageType::STRING_ARRAY)
118 .value("MATRIX", ParameterMessageType::MATRIX)
119 .value("VECTOR", ParameterMessageType::VECTOR)
120 .export_values();
121}
122
123void message_type(py::module_& m) {
124 py::enum_<MessageType>(m, "MessageType")
125 .value("UNKNOWN_MESSAGE", MessageType::UNKNOWN_MESSAGE)
126 .value("STATE_MESSAGE", MessageType::STATE_MESSAGE)
127 .value("SPATIAL_STATE_MESSAGE", MessageType::SPATIAL_STATE_MESSAGE)
128 .value("CARTESIAN_STATE_MESSAGE", MessageType::CARTESIAN_STATE_MESSAGE)
129 .value("CARTESIAN_POSE_MESSAGE", MessageType::CARTESIAN_POSE_MESSAGE)
130 .value("CARTESIAN_TWIST_MESSAGE", MessageType::CARTESIAN_TWIST_MESSAGE)
131 .value("CARTESIAN_ACCELERATION_MESSAGE", MessageType::CARTESIAN_ACCELERATION_MESSAGE)
132 .value("CARTESIAN_WRENCH_MESSAGE", MessageType::CARTESIAN_WRENCH_MESSAGE)
133 .value("JACOBIAN_MESSAGE", MessageType::JACOBIAN_MESSAGE)
134 .value("JOINT_STATE_MESSAGE", MessageType::JOINT_STATE_MESSAGE)
135 .value("JOINT_POSITIONS_MESSAGE", MessageType::JOINT_POSITIONS_MESSAGE)
136 .value("JOINT_VELOCITIES_MESSAGE", MessageType::JOINT_VELOCITIES_MESSAGE)
137 .value("JOINT_ACCELERATIONS_MESSAGE", MessageType::JOINT_ACCELERATIONS_MESSAGE)
138 .value("JOINT_TORQUES_MESSAGE", MessageType::JOINT_TORQUES_MESSAGE)
139 .value("SHAPE_MESSAGE", MessageType::SHAPE_MESSAGE)
140 .value("ELLIPSOID_MESSAGE", MessageType::ELLIPSOID_MESSAGE)
141 .value("PARAMETER_MESSAGE", MessageType::PARAMETER_MESSAGE)
142 .export_values();
143}
144
145void methods(py::module_& m) {
146 m.def("is_valid", &is_valid, "Check if a serialized binary string can be decoded into a support control libraries message type.", "msg"_a);
147 m.def("check_message_type", &check_message_type, "Check which control libraries message type a serialized binary string can be decoded as, if at all.", "msg"_a);
148 m.def("check_parameter_message_type", &check_parameter_message_type, "Check which control libraries message type a serialized binary string can be decoded as, if at all.", "msg"_a);
149
150 m.def("pack_fields", [](const std::vector<std::string>& encoded_fields) -> py::bytes {
151 char data[CLPROTO_PACKING_MAX_FIELDS * CLPROTO_PACKING_MAX_FIELD_LENGTH];
152 std::size_t packet_size = sizeof(field_length_t) * (encoded_fields.size() + 1);
153 for (const auto& field : encoded_fields) {
154 packet_size += field.size();
155 }
156 pack_fields(encoded_fields, data);
157 return std::string(data, packet_size);
158 }, "Pack an ordered vector of encoded field messages into a single data array.", "encoded_fields"_a);
159 m.def("unpack_fields", [](const std::string& packet) -> std::vector<py::bytes> {
160 std::vector<py::bytes> encoded_fields;
161 for (std::string field : unpack_fields(packet.c_str())) {
162 encoded_fields.emplace_back(field);
163 }
164 return encoded_fields;
165 }, "Unpack a data array into an ordered vector of encoded field messages.", "data"_a);
166
167 m.def("encode", [](const py::object& object, const MessageType& type) -> py::bytes {
168 switch (type) {
169 case MessageType::STATE_MESSAGE:
170 return encode_bytes<State>(object.cast<State>());
171 case MessageType::SPATIAL_STATE_MESSAGE:
172 return encode_bytes<SpatialState>(object.cast<SpatialState>());
173 case MessageType::CARTESIAN_STATE_MESSAGE:
174 return encode_bytes<CartesianState>(object.cast<CartesianState>());
175 case MessageType::CARTESIAN_POSE_MESSAGE:
176 return encode_bytes<CartesianPose>(object.cast<CartesianPose>());
177 case MessageType::CARTESIAN_TWIST_MESSAGE:
178 return encode_bytes<CartesianTwist>(object.cast<CartesianTwist>());
179 case MessageType::CARTESIAN_WRENCH_MESSAGE:
180 return encode_bytes<CartesianWrench>(object.cast<CartesianWrench>());
181 case MessageType::JACOBIAN_MESSAGE:
182 return encode_bytes<Jacobian>(object.cast<Jacobian>());
183 case MessageType::JOINT_STATE_MESSAGE:
184 return encode_bytes<JointState>(object.cast<JointState>());
185 case MessageType::JOINT_POSITIONS_MESSAGE:
186 return encode_bytes<JointPositions>(object.cast<JointPositions>());
187 case MessageType::JOINT_VELOCITIES_MESSAGE:
188 return encode_bytes<JointVelocities>(object.cast<JointVelocities>());
189 case MessageType::JOINT_ACCELERATIONS_MESSAGE:
190 return encode_bytes<JointAccelerations>(object.cast<JointAccelerations>());
191 case MessageType::JOINT_TORQUES_MESSAGE:
192 return encode_bytes<JointTorques>(object.cast<JointTorques>());
193 case MessageType::PARAMETER_MESSAGE:
194 return encode_parameter_container(object.cast<ParameterContainer>());
195 default:
196 throw std::invalid_argument("The message is not a valid encoded StateMessage.");
197 break;
198 }
199 }, "Encode a control libraries object into a serialized binary string representation (wire format).", py::arg("object"), py::arg("type"));
200
201 m.def("decode", [](const std::string& msg) -> py::object {
202 switch (check_message_type(msg)) {
203 case MessageType::STATE_MESSAGE:
204 return py::cast(decode<State>(msg));
205 case MessageType::SPATIAL_STATE_MESSAGE:
206 return py::cast(decode<SpatialState>(msg));
207 case MessageType::CARTESIAN_STATE_MESSAGE:
208 return py::cast<CartesianState>(decode<CartesianState>(msg));
209 case MessageType::CARTESIAN_POSE_MESSAGE:
210 return py::cast(decode<CartesianPose>(msg));
211 case MessageType::CARTESIAN_TWIST_MESSAGE:
212 return py::cast(decode<CartesianTwist>(msg));
213 case MessageType::CARTESIAN_WRENCH_MESSAGE:
214 return py::cast(decode<CartesianWrench>(msg));
215 case MessageType::JACOBIAN_MESSAGE:
216 return py::cast(decode<Jacobian>(msg));
217 case MessageType::JOINT_STATE_MESSAGE:
218 return py::cast(decode<JointState>(msg));
219 case MessageType::JOINT_POSITIONS_MESSAGE:
220 return py::cast(decode<JointPositions>(msg));
221 case MessageType::JOINT_VELOCITIES_MESSAGE:
222 return py::cast(decode<JointVelocities>(msg));
223 case MessageType::JOINT_ACCELERATIONS_MESSAGE:
224 return py::cast(decode<JointAccelerations>(msg));
225 case MessageType::JOINT_TORQUES_MESSAGE:
226 return py::cast(decode<JointTorques>(msg));
227 case MessageType::PARAMETER_MESSAGE:
228 return decode_parameter(msg);
229 default:
230 return py::none();
231 }
232 }, "Decode a serialized binary string from wire format into a control libraries object instance.", "msg"_a);
233
234 m.def("to_json", [](const std::string& msg) { return to_json(msg); }, "Convert a serialized binary string from wire format into a JSON formatted state message description", "msg"_a);
235 m.def("from_json", [](const std::string& json) -> py::bytes { return from_json(json); }, "Convert a JSON formatted state message description into a serialized binary string representation (wire format).", "msg"_a);
236}
237
238void bind_clproto(py::module_& m) {
239 message_type(m);
240 parameter_message_type(m);
241 methods(m);
242}
ParameterType get_parameter_type() const
Get the parameter type.
const std::string & get_name() const
Getter of the name as const reference.
Definition: State.cpp:48
Bindings to encode and decode state objects into serialised binary message.
ParameterMessageType check_parameter_message_type(const std::string &msg)
Check which control libraries parameter type a serialized binary string can be decoded as,...
Definition: clproto.cpp:61
uint32_t field_length_t
Size type used to indicate number of fields and field data length in pack_fields() and unpack_fields(...
Definition: clproto.h:24
std::string from_json(const std::string &json)
Convert a JSON formatted state message description into a serialized binary string representation (wi...
Definition: clproto.cpp:137
MessageType check_message_type(const std::string &msg)
Check which control libraries message type a serialized binary string can be decoded as,...
Definition: clproto.cpp:38
MessageType
The MessageType enumeration contains the possible message types in the clproto.
Definition: clproto.h:62
std::string to_json(const std::string &msg)
Convert a serialized binary string from wire format into a JSON formatted state message description.
Definition: clproto.cpp:120
void pack_fields(const std::vector< std::string > &fields, char *data)
Pack an ordered vector of encoded field messages into a single data array.
Definition: clproto.cpp:70
std::string encode(const T &obj)
Encode a control libraries object into a serialized binary string representation (wire format).
std::vector< std::string > unpack_fields(const char *data)
Unpack a data array into an ordered vector of encoded field messages.
Definition: clproto.cpp:94
bool is_valid(const std::string &msg)
Check if a serialized binary string can be decoded into a support control libraries message type.
Definition: clproto.cpp:34
Core state variables and objects.