Control Libraries 7.4.0
Loading...
Searching...
No Matches
PointAttractor.cpp
1#include "dynamical_systems/PointAttractor.hpp"
2
3#include "dynamical_systems/exceptions/NotImplementedException.hpp"
4#include "dynamical_systems/exceptions/EmptyAttractorException.hpp"
5#include "state_representation/exceptions/InvalidParameterException.hpp"
6#include "dynamical_systems/exceptions/IncompatibleSizeException.hpp"
7#include "state_representation/exceptions/EmptyStateException.hpp"
8#include "state_representation/exceptions/IncompatibleReferenceFramesException.hpp"
9#include "state_representation/space/cartesian/CartesianPose.hpp"
10#include "state_representation/space/cartesian/CartesianState.hpp"
11#include "state_representation/space/joint/JointPositions.hpp"
12#include "state_representation/space/joint/JointState.hpp"
13
14using namespace state_representation;
15
16namespace dynamical_systems {
17
18template<>
20 attractor_(make_shared_parameter<CartesianState>("attractor", CartesianState())),
21 gain_(make_shared_parameter<Eigen::MatrixXd>("gain", Eigen::MatrixXd::Identity(6, 6))) {
22 this->parameters_.insert(std::make_pair("attractor", attractor_));
23 this->parameters_.insert(std::make_pair("gain", gain_));
24}
25
26template<>
27PointAttractor<JointState>::PointAttractor() :
28 attractor_(make_shared_parameter<JointState>("attractor", JointState())),
29 gain_(std::make_shared<Parameter<Eigen::MatrixXd>>("gain")) {
30 this->parameters_.insert(std::make_pair("attractor", attractor_));
31 this->parameters_.insert(std::make_pair("gain", gain_));
32}
33
34template<class S>
35bool PointAttractor<S>::is_compatible(const S& state) const {
37}
38
40
41template<>
43 auto attractor = this->get_parameter_value<JointState>("attractor");
44 if (attractor.is_empty()) {
45 throw exceptions::EmptyAttractorException("The attractor of the dynamical system is empty.");
46 }
47 bool compatible = (attractor.get_size() == state.get_size());
48 if (compatible) {
49 for (unsigned int i = 0; i < attractor.get_size(); ++i) {
50 compatible = (compatible && attractor.get_names()[i] == state.get_names()[i]);
51 }
52 }
53 return compatible;
54}
55
56template<class S>
57void PointAttractor<S>::set_gain(const std::shared_ptr<ParameterInterface>& parameter, unsigned int expected_size) {
58 if (parameter->get_parameter_type() == ParameterType::DOUBLE) {
59 auto gain = parameter->get_parameter_value<double>();
60 this->gain_->set_value(gain * Eigen::MatrixXd::Identity(expected_size, expected_size));
61 } else if (parameter->get_parameter_type() == ParameterType::DOUBLE_ARRAY) {
62 auto gain = parameter->get_parameter_value<std::vector<double>>();
63 if (gain.size() != expected_size) {
65 "The provided diagonal coefficients do not correspond to the expected size of the attractor");
66 }
67 Eigen::VectorXd diagonal = Eigen::VectorXd::Map(gain.data(), expected_size);
68 this->gain_->set_value(diagonal.asDiagonal());
69 } else if (parameter->get_parameter_type() == ParameterType::MATRIX) {
70 auto gain = parameter->get_parameter_value<Eigen::MatrixXd>();
71 if (gain.rows() != expected_size && gain.cols() != expected_size) {
73 "The provided gain matrix do not have the expected size (" + std::to_string(expected_size) + "x"
74 + std::to_string(expected_size) + ")");
75 }
76 this->gain_->set_value(gain);
77 } else {
78 throw state_representation::exceptions::InvalidParameterException("Parameter 'gain' has incorrect type");
79 }
80}
81
82template<class S>
83void PointAttractor<S>::set_attractor(const S&) {
84 throw exceptions::NotImplementedException("set_attractor is not implemented for this type of DS");
85}
86
87template<>
88void PointAttractor<CartesianState>::set_attractor(const CartesianState& attractor) {
89 if (attractor.is_empty()) {
90 throw state_representation::exceptions::EmptyStateException(attractor.get_name() + " state is empty");
91 }
92 if (this->get_base_frame().is_empty()) {
93 IDynamicalSystem<CartesianState>::set_base_frame(
95 }
96 // validate that the reference frame of the attractor is always compatible with the DS reference frame
97 if (attractor.get_reference_frame() != this->get_base_frame().get_name()) {
98 if (attractor.get_reference_frame() != this->get_base_frame().get_reference_frame()) {
100 "The reference frame of the attractor " + attractor.get_name() + " in frame "
101 + attractor.get_reference_frame() + " is incompatible with the base frame of the dynamical system "
102 + this->get_base_frame().get_name() + " in frame " + this->get_base_frame().get_reference_frame() + ".");
103 }
104 this->attractor_->set_value(this->get_base_frame().inverse() * attractor);
105 } else {
106 this->attractor_->set_value(attractor);
107 }
108}
109
110template<>
111void PointAttractor<JointState>::set_attractor(const JointState& attractor) {
112 if (attractor.is_empty()) {
113 throw state_representation::exceptions::EmptyStateException(attractor.get_name() + " state is empty");
114 }
115 this->attractor_->set_value(attractor);
116 if (this->gain_->is_empty()) {
117 this->gain_->set_value(Eigen::MatrixXd::Identity(attractor.get_size(), attractor.get_size()));
118 }
119}
120
121template<class S>
122void PointAttractor<S>::set_base_frame(const S& base_frame) {
123 this->IDynamicalSystem<S>::set_base_frame(base_frame);
124}
125
126template void PointAttractor<JointState>::set_base_frame(const JointState& base_frame);
127
128template<>
130 if (base_frame.is_empty()) {
131 throw state_representation::exceptions::EmptyStateException(base_frame.get_name() + " state is empty");
132 }
133 IDynamicalSystem<CartesianState>::set_base_frame(base_frame);
134 if (!this->attractor_->get_value().is_empty()) {
135 // update reference frame of attractor
136 auto attractor = this->attractor_->get_value();
137 attractor.set_reference_frame(base_frame.get_name());
138 this->set_attractor(attractor);
139 }
140}
141
142template<>
143void PointAttractor<CartesianState>::validate_and_set_parameter(const std::shared_ptr<ParameterInterface>& parameter) {
144 if (parameter->get_name() == "attractor") {
145 if (parameter->get_parameter_state_type() == StateType::CARTESIAN_STATE) {
146 this->set_attractor(parameter->get_parameter_value<CartesianState>());
147 } else if (parameter->get_parameter_state_type() == StateType::CARTESIAN_POSE) {
148 this->set_attractor(parameter->get_parameter_value<CartesianPose>());
149 }
150 } else if (parameter->get_name() == "gain") {
151 this->set_gain(parameter, 6);
152 } else {
154 "No parameter with name '" + parameter->get_name() + "' found");
155 }
156}
157
158template<>
159void PointAttractor<JointState>::validate_and_set_parameter(const std::shared_ptr<ParameterInterface>& parameter) {
160 if (parameter->get_name() == "attractor") {
161 if (parameter->get_parameter_state_type() == StateType::JOINT_STATE) {
162 this->set_attractor(parameter->get_parameter_value<JointState>());
163 } else if (parameter->get_parameter_state_type() == StateType::JOINT_POSITIONS) {
164 this->set_attractor(parameter->get_parameter_value<JointPositions>());
165 }
166 } else if (parameter->get_name() == "gain") {
167 this->set_gain(parameter, this->attractor_->get_value().get_size());
168 } else {
170 "No parameter with name '" + parameter->get_name() + "' found");
171 }
172}
173
174template<class S>
176 throw exceptions::NotImplementedException("compute_dynamics is not implemented for this type of DS");
177}
178
179template<>
181 if (this->attractor_->get_value().is_empty()) {
182 throw exceptions::EmptyAttractorException("The attractor of the dynamical system is empty.");
183 }
184 CartesianTwist twist = CartesianPose(this->attractor_->get_value()) - CartesianPose(state);
185 twist = this->gain_->get_value() * twist;
186 return CartesianTwist(state.get_name(), twist.get_twist(), this->attractor_->get_value().get_reference_frame());
187}
188
189template<>
190JointState PointAttractor<JointState>::compute_dynamics(const JointState& state) const {
191 JointVelocities velocities = JointPositions(this->attractor_->get_value()) - JointPositions(state);
192 velocities = this->gain_->get_value() * velocities;
193 return JointVelocities(state.get_name(), this->attractor_->get_value().get_names(), velocities.get_velocities());
194}
195}// namespace dynamical_systems
Abstract class for a dynamical system.
Represents a dynamical system to move towards an attractor.
PointAttractor()
Empty constructor.
Class to define Cartesian pose in Cartesian space as 3D position and quaternion based orientation.
Class to represent a state in Cartesian space.
Eigen::Matrix< double, 6, 1 > get_twist() const
Getter of the 6d twist from linear and angular velocity attributes.
static CartesianState Identity(const std::string &name, const std::string &reference="world")
Constructor for the identity Cartesian state (identity pose and 0 for the rest)
Class to define twist in Cartesian space as 3D linear and angular velocity vectors.
Class to define positions of the joints.
Class to define a state in joint space.
const Eigen::VectorXd & get_velocities() const
Getter of the velocities attribute.
unsigned int get_size() const
Getter of the size from the attributes.
Class to define velocities of the joints.
Class to represent name-value pairs of different types.
Definition Parameter.hpp:18
const std::string & get_reference_frame() const
Getter of the reference frame as const reference.
const std::string & get_name() const
Getter of the name attribute.
Definition State.cpp:29
bool is_empty() const
Getter of the empty attribute.
Definition State.cpp:33
Systems of equations relating state variables to their derivatives.
Definition Circular.hpp:7
Core state variables and objects.