ros2_control - rolling
Loading...
Searching...
No Matches
differential_transmission.hpp
1// Copyright 2020 PAL Robotics S.L.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef TRANSMISSION_INTERFACE__DIFFERENTIAL_TRANSMISSION_HPP_
16#define TRANSMISSION_INTERFACE__DIFFERENTIAL_TRANSMISSION_HPP_
17
18#include <fmt/compile.h>
19
20#include <cassert>
21#include <string>
22#include <vector>
23
24#include "hardware_interface/types/hardware_interface_type_values.hpp"
25#include "transmission_interface/accessor.hpp"
26#include "transmission_interface/exception.hpp"
27#include "transmission_interface/transmission.hpp"
28
30{
32
113{
114public:
122 const std::vector<double> & actuator_reduction, const std::vector<double> & joint_reduction,
123 const std::vector<double> & joint_offset = {0.0, 0.0});
124
130 void configure(
131 const std::vector<JointHandle> & joint_handles,
132 const std::vector<ActuatorHandle> & actuator_handles) override;
133
135
140 void actuator_to_joint() override;
141
143
148 void joint_to_actuator() override;
149
150 std::size_t num_actuators() const override { return 2; }
151 std::size_t num_joints() const override { return 2; }
152
153 const std::vector<double> & get_actuator_reduction() const { return actuator_reduction_; }
154 const std::vector<double> & get_joint_reduction() const { return joint_reduction_; }
155 const std::vector<double> & get_joint_offset() const { return joint_offset_; }
156
158 std::string get_handles_info() const;
159
166
173
174protected:
175 std::vector<double> actuator_reduction_;
176 std::vector<double> joint_reduction_;
177 std::vector<double> joint_offset_;
178
179 std::vector<JointHandle> joint_position_;
180 std::vector<JointHandle> joint_velocity_;
181 std::vector<JointHandle> joint_effort_;
182 std::vector<JointHandle> joint_torque_;
183 std::vector<JointHandle> joint_force_;
184 std::vector<JointHandle> joint_absolute_position_;
185
186 std::vector<ActuatorHandle> actuator_position_;
187 std::vector<ActuatorHandle> actuator_velocity_;
188 std::vector<ActuatorHandle> actuator_effort_;
189 std::vector<ActuatorHandle> actuator_torque_;
190 std::vector<ActuatorHandle> actuator_force_;
191 std::vector<ActuatorHandle> actuator_absolute_position_;
192};
193
195 const std::vector<double> & actuator_reduction, const std::vector<double> & joint_reduction,
196 const std::vector<double> & joint_offset)
197: actuator_reduction_(actuator_reduction),
198 joint_reduction_(joint_reduction),
199 joint_offset_(joint_offset)
200{
201 if (
202 num_actuators() != actuator_reduction_.size() || num_joints() != joint_reduction_.size() ||
203 num_joints() != joint_offset_.size())
204 {
205 throw Exception("Reduction and offset vectors must have size 2.");
206 }
207
208 if (
209 0.0 == actuator_reduction_[0] || 0.0 == actuator_reduction_[1] || 0.0 == joint_reduction_[0] ||
210 0.0 == joint_reduction_[1])
211 {
212 throw Exception("Transmission reduction ratios cannot be zero.");
213 }
214}
215
217 const std::vector<JointHandle> & joint_handles,
218 const std::vector<ActuatorHandle> & actuator_handles)
219{
220 if (joint_handles.empty())
221 {
222 throw Exception("No joint handles were passed in");
223 }
224
225 if (actuator_handles.empty())
226 {
227 throw Exception("No actuator handles were passed in");
228 }
229
230 const auto joint_names = get_names(joint_handles);
231 if (joint_names.size() != 2)
232 {
233 throw Exception(
234 fmt::format(
235 FMT_COMPILE("There should be exactly two unique joint names but was given '{}'."),
236 to_string(joint_names)));
237 }
238 const auto actuator_names = get_names(actuator_handles);
239 if (actuator_names.size() != 2)
240 {
241 throw Exception(
242 fmt::format(
243 FMT_COMPILE("There should be exactly two unique actuator names but was given '{}'."),
244 to_string(actuator_names)));
245 }
246
247 joint_position_ =
248 get_ordered_handles(joint_handles, joint_names, hardware_interface::HW_IF_POSITION);
249 joint_velocity_ =
250 get_ordered_handles(joint_handles, joint_names, hardware_interface::HW_IF_VELOCITY);
251 joint_effort_ = get_ordered_handles(joint_handles, joint_names, hardware_interface::HW_IF_EFFORT);
252 joint_torque_ = get_ordered_handles(joint_handles, joint_names, hardware_interface::HW_IF_TORQUE);
253 joint_force_ = get_ordered_handles(joint_handles, joint_names, hardware_interface::HW_IF_FORCE);
254 joint_absolute_position_ =
255 get_ordered_handles(joint_handles, joint_names, HW_IF_ABSOLUTE_POSITION);
256
257 if (!joint_position_.empty() && joint_position_.size() != 2)
258 {
259 throw Exception(
260 fmt::format(
261 FMT_COMPILE("Not enough valid or required joint position handles were present. \n{}"),
263 }
264 if (!joint_velocity_.empty() && joint_velocity_.size() != 2)
265 {
266 throw Exception(
267 fmt::format(
268 FMT_COMPILE("Not enough valid or required joint velocity handles were present. \n{}"),
270 }
271 if (!joint_effort_.empty() && joint_effort_.size() != 2)
272 {
273 throw Exception(
274 fmt::format(
275 FMT_COMPILE("Not enough valid or required joint effort handles were present. \n{}"),
277 }
278 if (!joint_torque_.empty() && joint_torque_.size() != 2)
279 {
280 throw Exception(
281 fmt::format(
282 FMT_COMPILE("Not enough valid or required joint torque handles were present. \n{}"),
284 }
285 if (!joint_force_.empty() && joint_force_.size() != 2)
286 {
287 throw Exception(
288 fmt::format(
289 FMT_COMPILE("Not enough valid or required joint force handles were present. \n{}"),
291 }
292 if (!joint_absolute_position_.empty() && joint_absolute_position_.size() != 2)
293 {
294 throw Exception(
295 fmt::format(
296 FMT_COMPILE(
297 "Not enough valid or required joint absolute position handles were present. \n{}"),
299 }
300
301 actuator_position_ =
302 get_ordered_handles(actuator_handles, actuator_names, hardware_interface::HW_IF_POSITION);
303 actuator_velocity_ =
304 get_ordered_handles(actuator_handles, actuator_names, hardware_interface::HW_IF_VELOCITY);
305 actuator_effort_ =
306 get_ordered_handles(actuator_handles, actuator_names, hardware_interface::HW_IF_EFFORT);
307 actuator_torque_ =
308 get_ordered_handles(actuator_handles, actuator_names, hardware_interface::HW_IF_TORQUE);
309 actuator_force_ =
310 get_ordered_handles(actuator_handles, actuator_names, hardware_interface::HW_IF_FORCE);
311 actuator_absolute_position_ =
312 get_ordered_handles(actuator_handles, actuator_names, HW_IF_ABSOLUTE_POSITION);
313
314 if (!actuator_position_.empty() && actuator_position_.size() != 2)
315 {
316 throw Exception(
317 fmt::format(
318 FMT_COMPILE("Not enough valid or required actuator position handles were present. \n{}"),
320 }
321 if (!actuator_velocity_.empty() && actuator_velocity_.size() != 2)
322 {
323 throw Exception(
324 fmt::format(
325 FMT_COMPILE("Not enough valid or required actuator velocity handles were present. \n{}"),
327 }
328 if (!actuator_effort_.empty() && actuator_effort_.size() != 2)
329 {
330 throw Exception(
331 fmt::format(
332 FMT_COMPILE("Not enough valid or required actuator effort handles were present. \n{}"),
334 }
335 if (!actuator_torque_.empty() && actuator_torque_.size() != 2)
336 {
337 throw Exception(
338 fmt::format(
339 FMT_COMPILE("Not enough valid or required actuator torque handles were present. \n{}"),
341 }
342 if (!actuator_force_.empty() && actuator_force_.size() != 2)
343 {
344 throw Exception(
345 fmt::format(
346 FMT_COMPILE("Not enough valid or required actuator force handles were present. \n{}"),
348 }
349 if (!actuator_absolute_position_.empty() && actuator_absolute_position_.size() != 2)
350 {
351 throw Exception(
352 fmt::format(
353 FMT_COMPILE(
354 "Not enough valid or required actuator absolute position handles were "
355 "present. \n{}"),
357 }
358
359 if (
360 !joint_position_.empty() && !actuator_position_.empty() &&
361 joint_position_.size() != actuator_position_.size())
362 {
363 throw Exception(
364 fmt::format(
365 FMT_COMPILE("Pair-wise mismatch on position interfaces. \n{}"), get_handles_info()));
366 }
367 if (
368 !joint_velocity_.empty() && !actuator_velocity_.empty() &&
369 joint_velocity_.size() != actuator_velocity_.size())
370 {
371 throw Exception(
372 fmt::format(
373 FMT_COMPILE("Pair-wise mismatch on velocity interfaces. \n{}"), get_handles_info()));
374 }
375 if (
376 !joint_effort_.empty() && !actuator_effort_.empty() &&
377 joint_effort_.size() != actuator_effort_.size())
378 {
379 throw Exception(
380 fmt::format(
381 FMT_COMPILE("Pair-wise mismatch on effort interfaces. \n{}"), get_handles_info()));
382 }
383 if (
384 !joint_torque_.empty() && !actuator_torque_.empty() &&
385 joint_torque_.size() != actuator_torque_.size())
386 {
387 throw Exception(
388 fmt::format(
389 FMT_COMPILE("Pair-wise mismatch on torque interfaces. \n{}"), get_handles_info()));
390 }
391 if (
392 !joint_force_.empty() && !actuator_force_.empty() &&
393 joint_force_.size() != actuator_force_.size())
394 {
395 throw Exception(
396 fmt::format(FMT_COMPILE("Pair-wise mismatch on force interfaces. \n{}"), get_handles_info()));
397 }
398 if (
399 !joint_absolute_position_.empty() && !actuator_absolute_position_.empty() &&
400 joint_absolute_position_.size() != actuator_absolute_position_.size())
401 {
402 throw Exception(
403 fmt::format(
404 FMT_COMPILE("Pair-wise mismatch on absolute position interfaces. \n{}"),
406 }
407
408 // Check at least one pair-wise interface is available
409 if (!((!joint_position_.empty() && !actuator_position_.empty() &&
410 joint_position_.size() == actuator_position_.size()) ||
411 (!joint_velocity_.empty() && !actuator_velocity_.empty() &&
412 joint_velocity_.size() == actuator_velocity_.size()) ||
413 (!joint_effort_.empty() && !actuator_effort_.empty() &&
414 joint_effort_.size() == actuator_effort_.size()) ||
415 (!joint_torque_.empty() && !actuator_torque_.empty() &&
416 joint_torque_.size() == actuator_torque_.size()) ||
417 (!joint_force_.empty() && !actuator_force_.empty() &&
418 joint_force_.size() == actuator_force_.size()) ||
419 (!joint_absolute_position_.empty() && !actuator_absolute_position_.empty() &&
420 joint_absolute_position_.size() == actuator_absolute_position_.size())))
421 {
422 throw Exception(
423 fmt::format(
424 FMT_COMPILE("No pair-wise interface available between joints and actuators. \n{}"),
426 }
427}
428
430{
431 const auto & ar = actuator_reduction_;
432 const auto & jr = joint_reduction_;
433
434 auto & act_pos = actuator_position_;
435 auto & joint_pos = joint_position_;
436 if (act_pos.size() == num_actuators() && joint_pos.size() == num_joints())
437 {
438 assert(act_pos[0] && act_pos[1] && joint_pos[0] && joint_pos[1]);
439
440 joint_pos[0].set_value(
441 (act_pos[0].get_value() / ar[0] + act_pos[1].get_value() / ar[1]) / (2.0 * jr[0]) +
442 joint_offset_[0]);
443 joint_pos[1].set_value(
444 (act_pos[0].get_value() / ar[0] - act_pos[1].get_value() / ar[1]) / (2.0 * jr[1]) +
445 joint_offset_[1]);
446 }
447
448 auto & act_vel = actuator_velocity_;
449 auto & joint_vel = joint_velocity_;
450 if (act_vel.size() == num_actuators() && joint_vel.size() == num_joints())
451 {
452 assert(act_vel[0] && act_vel[1] && joint_vel[0] && joint_vel[1]);
453
454 joint_vel[0].set_value(
455 (act_vel[0].get_value() / ar[0] + act_vel[1].get_value() / ar[1]) / (2.0 * jr[0]));
456 joint_vel[1].set_value(
457 (act_vel[0].get_value() / ar[0] - act_vel[1].get_value() / ar[1]) / (2.0 * jr[1]));
458 }
459
460 auto & act_eff = actuator_effort_;
461 auto & joint_eff = joint_effort_;
462 if (act_eff.size() == num_actuators() && joint_eff.size() == num_joints())
463 {
464 assert(act_eff[0] && act_eff[1] && joint_eff[0] && joint_eff[1]);
465
466 joint_eff[0].set_value(
467 jr[0] * (act_eff[0].get_value() * ar[0] + act_eff[1].get_value() * ar[1]));
468 joint_eff[1].set_value(
469 jr[1] * (act_eff[0].get_value() * ar[0] - act_eff[1].get_value() * ar[1]));
470 }
471
472 auto & act_tor = actuator_torque_;
473 auto & joint_tor = joint_torque_;
474 if (act_tor.size() == num_actuators() && joint_tor.size() == num_joints())
475 {
476 assert(act_tor[0] && act_tor[1] && joint_tor[0] && joint_tor[1]);
477
478 joint_tor[0].set_value(
479 jr[0] * (act_tor[0].get_value() * ar[0] + act_tor[1].get_value() * ar[1]));
480 joint_tor[1].set_value(
481 jr[1] * (act_tor[0].get_value() * ar[0] - act_tor[1].get_value() * ar[1]));
482 }
483
484 auto & act_for = actuator_force_;
485 auto & joint_for = joint_force_;
486 if (act_for.size() == num_actuators() && joint_for.size() == num_joints())
487 {
488 assert(act_for[0] && act_for[1] && joint_for[0] && joint_for[1]);
489
490 joint_for[0].set_value(
491 jr[0] * (act_for[0].get_value() * ar[0] + act_for[1].get_value() * ar[1]));
492 joint_for[1].set_value(
493 jr[1] * (act_for[0].get_value() * ar[0] - act_for[1].get_value() * ar[1]));
494 }
495
496 auto & act_abs_pos = actuator_absolute_position_;
497 auto & joint_abs_pos = joint_absolute_position_;
498 if (act_abs_pos.size() == num_actuators() && joint_abs_pos.size() == num_joints())
499 {
500 assert(act_abs_pos[0] && act_abs_pos[1] && joint_abs_pos[0] && joint_abs_pos[1]);
501
502 joint_abs_pos[0].set_value(
503 (act_abs_pos[0].get_value() / ar[0] + act_abs_pos[1].get_value() / ar[1]) / (2.0 * jr[0]) +
504 joint_offset_[0]);
505 joint_abs_pos[1].set_value(
506 (act_abs_pos[0].get_value() / ar[0] - act_abs_pos[1].get_value() / ar[1]) / (2.0 * jr[1]) +
507 joint_offset_[1]);
508 }
509}
510
512{
513 const auto & ar = actuator_reduction_;
514 const auto & jr = joint_reduction_;
515
516 auto & act_pos = actuator_position_;
517 auto & joint_pos = joint_position_;
518 if (act_pos.size() == num_actuators() && joint_pos.size() == num_joints())
519 {
520 assert(act_pos[0] && act_pos[1] && joint_pos[0] && joint_pos[1]);
521
522 double joints_offset_applied[2] = {
523 joint_pos[0].get_value() - joint_offset_[0], joint_pos[1].get_value() - joint_offset_[1]};
524 act_pos[0].set_value(
525 (joints_offset_applied[0] * jr[0] + joints_offset_applied[1] * jr[1]) * ar[0]);
526 act_pos[1].set_value(
527 (joints_offset_applied[0] * jr[0] - joints_offset_applied[1] * jr[1]) * ar[1]);
528 }
529
530 auto & act_vel = actuator_velocity_;
531 auto & joint_vel = joint_velocity_;
532 if (act_vel.size() == num_actuators() && joint_vel.size() == num_joints())
533 {
534 assert(act_vel[0] && act_vel[1] && joint_vel[0] && joint_vel[1]);
535
536 act_vel[0].set_value(
537 (joint_vel[0].get_value() * jr[0] + joint_vel[1].get_value() * jr[1]) * ar[0]);
538 act_vel[1].set_value(
539 (joint_vel[0].get_value() * jr[0] - joint_vel[1].get_value() * jr[1]) * ar[1]);
540 }
541
542 auto & act_eff = actuator_effort_;
543 auto & joint_eff = joint_effort_;
544 if (act_eff.size() == num_actuators() && joint_eff.size() == num_joints())
545 {
546 assert(act_eff[0] && act_eff[1] && joint_eff[0] && joint_eff[1]);
547
548 act_eff[0].set_value(
549 (joint_eff[0].get_value() / jr[0] + joint_eff[1].get_value() / jr[1]) / (2.0 * ar[0]));
550 act_eff[1].set_value(
551 (joint_eff[0].get_value() / jr[0] - joint_eff[1].get_value() / jr[1]) / (2.0 * ar[1]));
552 }
553
554 auto & act_tor = actuator_torque_;
555 auto & joint_tor = joint_torque_;
556 if (act_tor.size() == num_actuators() && joint_tor.size() == num_joints())
557 {
558 assert(act_tor[0] && act_tor[1] && joint_tor[0] && joint_tor[1]);
559
560 act_tor[0].set_value(
561 (joint_tor[0].get_value() / jr[0] + joint_tor[1].get_value() / jr[1]) / (2.0 * ar[0]));
562 act_tor[1].set_value(
563 (joint_tor[0].get_value() / jr[0] - joint_tor[1].get_value() / jr[1]) / (2.0 * ar[1]));
564 }
565
566 auto & act_for = actuator_force_;
567 auto & joint_for = joint_force_;
568 if (act_for.size() == num_actuators() && joint_for.size() == num_joints())
569 {
570 assert(act_for[0] && act_for[1] && joint_for[0] && joint_for[1]);
571
572 act_for[0].set_value(
573 (joint_for[0].get_value() / jr[0] + joint_for[1].get_value() / jr[1]) / (2.0 * ar[0]));
574 act_for[1].set_value(
575 (joint_for[0].get_value() / jr[0] - joint_for[1].get_value() / jr[1]) / (2.0 * ar[1]));
576 }
577}
578
580{
581 return fmt::format(
582 FMT_COMPILE(
583 "Got the following handles:\n"
584 "Joint position: {}, Actuator position: {}\n"
585 "Joint velocity: {}, Actuator velocity: {}\n"
586 "Joint effort: {}, Actuator effort: {}\n"
587 "Joint torque: {}, Actuator torque: {}\n"
588 "Joint force: {}, Actuator force: {}\n"
589 "Joint absolute position: {}, Actuator absolute position: {}"),
590 to_string(get_names(joint_position_)), to_string(get_names(actuator_position_)),
591 to_string(get_names(joint_velocity_)), to_string(get_names(actuator_velocity_)),
592 to_string(get_names(joint_effort_)), to_string(get_names(actuator_effort_)),
593 to_string(get_names(joint_torque_)), to_string(get_names(actuator_torque_)),
594 to_string(get_names(joint_force_)), to_string(get_names(actuator_force_)),
595 to_string(get_names(joint_absolute_position_)),
596 to_string(get_names(actuator_absolute_position_)));
597}
598
599} // namespace transmission_interface
600
601#endif // TRANSMISSION_INTERFACE__DIFFERENTIAL_TRANSMISSION_HPP_
Implementation of a differential transmission.
Definition differential_transmission.hpp:113
DifferentialTransmission(const std::vector< double > &actuator_reduction, const std::vector< double > &joint_reduction, const std::vector< double > &joint_offset={0.0, 0.0})
Definition differential_transmission.hpp:194
std::vector< std::string > get_supported_actuator_interfaces() const override
Definition differential_transmission.hpp:160
std::size_t num_joints() const override
Definition differential_transmission.hpp:151
void joint_to_actuator() override
Transform variables from joint to actuator space.
Definition differential_transmission.hpp:511
void actuator_to_joint() override
Transform variables from actuator to joint space.
Definition differential_transmission.hpp:429
std::string get_handles_info() const
Get human-friendly report of handles.
Definition differential_transmission.hpp:579
std::vector< std::string > get_supported_joint_interfaces() const override
Definition differential_transmission.hpp:167
void configure(const std::vector< JointHandle > &joint_handles, const std::vector< ActuatorHandle > &actuator_handles) override
Definition differential_transmission.hpp:216
std::size_t num_actuators() const override
Definition differential_transmission.hpp:150
Definition exception.hpp:23
Abstract base class for representing mechanical transmissions.
Definition transmission.hpp:50
constexpr char HW_IF_EFFORT[]
Constant defining effort interface name.
Definition hardware_interface_type_values.hpp:27
constexpr char HW_IF_FORCE[]
Constant defining force interface name.
Definition mujoco_system_interface.hpp:61
constexpr char HW_IF_TORQUE[]
Constant defining torque interface name.
Definition mujoco_system_interface.hpp:59
constexpr char HW_IF_VELOCITY[]
Constant defining velocity interface name.
Definition hardware_interface_type_values.hpp:23
constexpr char HW_IF_POSITION[]
Constant defining position interface name.
Definition hardware_interface_type_values.hpp:21
Definition accessor.hpp:26