1#include "dynamical_systems/Ring.hpp"
3#include "dynamical_systems/exceptions/EmptyAttractorException.hpp"
4#include "state_representation/exceptions/InvalidParameterException.hpp"
5#include "state_representation/space/cartesian/CartesianTwist.hpp"
6#include "state_representation/exceptions/IncompatibleReferenceFramesException.hpp"
7#include "state_representation/exceptions/EmptyStateException.hpp"
16 radius_(std::make_shared<
Parameter<double>>(
"radius", 1.0)),
17 width_(std::make_shared<
Parameter<double>>(
"width", 0.5)),
18 speed_(std::make_shared<
Parameter<double>>(
"speed", 1.0)),
19 field_strength_(std::make_shared<
Parameter<double>>(
"field_strength", 1.0)),
20 normal_gain_(std::make_shared<
Parameter<double>>(
"normal_gain", 1.0)),
21 angular_gain_(std::make_shared<
Parameter<double>>(
"angular_gain", 1.0)) {
22 this->rotation_offset_->set_value(
23 CartesianPose(
"rotation", Eigen::Quaterniond::Identity(), this->center_->get_value().get_name()));
24 this->
parameters_.insert(std::make_pair(
"center", this->center_));
25 this->
parameters_.insert(std::make_pair(
"rotation_offset", this->rotation_offset_));
26 this->
parameters_.insert(std::make_pair(
"radius", this->radius_));
27 this->
parameters_.insert(std::make_pair(
"width", this->width_));
28 this->
parameters_.insert(std::make_pair(
"speed", this->speed_));
29 this->
parameters_.insert(std::make_pair(
"field_strength", this->field_strength_));
30 this->
parameters_.insert(std::make_pair(
"normal_gain", this->normal_gain_));
31 this->
parameters_.insert(std::make_pair(
"angular_gain", this->angular_gain_));
34Ring::Ring(
const std::list<std::shared_ptr<state_representation::ParameterInterface>>& parameters) :
Ring() {
51 +
" is incompatible with the base frame of the dynamical system " + this->get_base_frame().get_name()
52 +
" in frame " + this->get_base_frame().get_reference_frame() +
"."
55 this->center_->set_value(this->
get_base_frame().inverse() * center);
57 this->center_->set_value(center);
59 this->set_rotation_offset(this->get_rotation_offset());
62void Ring::set_rotation_offset(
const Eigen::Quaterniond& rotation) {
63 auto pose =
CartesianPose(
"rotation", rotation, this->center_->get_value().get_name());
64 this->rotation_offset_->set_value(pose);
67Eigen::Quaterniond Ring::get_rotation_offset()
const {
68 return this->rotation_offset_->get_value().get_orientation();
77 if (!this->center_->get_value().is_empty()) {
78 auto center = this->center_->get_value();
80 this->center_->set_value(center);
84void Ring::validate_and_set_parameter(
const std::shared_ptr<ParameterInterface>& parameter) {
85 if (parameter->get_name() ==
"center") {
88 }
else if (parameter->get_name() ==
"rotation_offset") {
91 }
else if (parameter->get_name() ==
"radius") {
93 this->radius_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
94 }
else if (parameter->get_name() ==
"width") {
96 this->width_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
97 }
else if (parameter->get_name() ==
"speed") {
99 this->speed_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
100 }
else if (parameter->get_name() ==
"field_strength") {
102 this->field_strength_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
103 }
else if (parameter->get_name() ==
"normal_gain") {
105 this->normal_gain_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
106 }
else if (parameter->get_name() ==
"angular_gain") {
108 this->angular_gain_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
111 "No parameter with name '" + parameter->get_name() +
"' found"
116Eigen::Vector3d Ring::calculate_local_linear_velocity(
const CartesianPose& pose,
double& local_field_strength)
const {
117 Eigen::Vector3d local_linear_velocity = Eigen::Vector3d::Zero();
122 double d = position2d.norm();
124 return local_linear_velocity;
127 double re = M_PI_2 * (d - this->radius_->get_value()) / this->width_->get_value();
130 }
else if (re < -M_PI_2) {
136 R << -sin(re), -cos(re), cos(re), -sin(re);
137 Eigen::Vector2d velocity2d = R * position2d / d;
140 velocity2d *= this->speed_->get_value();
143 double vz = -this->normal_gain_->get_value() * pose.
get_position().z();
146 local_linear_velocity << velocity2d, vz;
149 local_field_strength = this->field_strength_->get_value() + (1 - this->field_strength_->get_value()) * cos(re);
150 local_linear_velocity *= local_field_strength;
152 return local_linear_velocity;
155Eigen::Vector3d Ring::calculate_local_angular_velocity(
156 const CartesianPose& pose,
const Eigen::Vector3d& linearVelocity,
double local_field_strength
158 Eigen::Vector3d local_angular_velocity = Eigen::Vector3d::Zero();
162 Eigen::Quaterniond qd = Eigen::Quaterniond::Identity();
163 qd.w() = cos(theta / 2);
164 qd.z() = sin(theta / 2);
167 qd.coeffs() = -qd.coeffs();
171 if (deltaQ.vec().norm() < 1e-7) {
172 return local_angular_velocity;
176 Eigen::Quaterniond deltaOmega = Eigen::Quaterniond::Identity();
178 double phi = atan2(deltaQ.vec().norm(), deltaQ.w());
179 deltaOmega.vec() = 2 * deltaQ.vec() * phi / sin(phi);
181 local_angular_velocity = this->angular_gain_->get_value() * deltaOmega.vec();
182 local_angular_velocity *= local_field_strength;
185 Eigen::Vector2d linear_velocity2d(linearVelocity.x(), linearVelocity.y());
186 if (position2d.norm() < 1e-7 || linear_velocity2d.norm() < 1e-7) {
187 return local_angular_velocity;
192 if (linear_velocity2d.norm() > (0.5 * position2d.norm())) {
193 linear_velocity2d = linear_velocity2d.normalized() * (0.5 * position2d).norm();
195 double projection = position2d.normalized().dot((position2d + linear_velocity2d).normalized());
197 if (1 - abs(projection) > 1e-7) {
198 dthetaZ = acos(projection);
200 local_angular_velocity.z() += dthetaZ;
202 return local_angular_velocity;
206 if (this->center_->get_value().is_empty()) {
211 pose = this->center_->get_value().inverse() * pose;
216 double local_field_strength;
217 twist.
set_linear_velocity(this->calculate_local_linear_velocity(pose, local_field_strength));
219 this->calculate_local_angular_velocity(
state_representation::CartesianState get_base_frame() const
Return the base frame of the dynamical system.
virtual void set_base_frame(const S &base_frame)
Set the base frame of the dynamical system.
Represent a Ring dynamical system limit cycle to move around a radius within a fixed width.
state_representation::CartesianState compute_dynamics(const state_representation::CartesianState &state) const override
Compute the dynamics of the input state. Internal function, to be redefined based on the type of dyna...
void set_base_frame(const state_representation::CartesianState &base_frame) override
Set a parameter.
Class to define Cartesian pose in Cartesian space as 3D position and quaternion based orientation.
Class to represent a state in Cartesian space.
void set_orientation(const Eigen::Quaterniond &orientation)
Setter of the orientation.
const Eigen::Vector3d & get_linear_velocity() const
Getter of the linear velocity attribute.
const Eigen::Vector3d & get_position() const
Getter of the position attribute.
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)
const Eigen::Quaterniond & get_orientation() const
Getter of the orientation attribute.
void set_linear_velocity(const Eigen::Vector3d &linear_velocity)
Setter of the linear velocity attribute.
void set_angular_velocity(const Eigen::Vector3d &angular_velocity)
Setter of the angular velocity attribute.
Class to define twist in Cartesian space as 3D linear and angular velocity vectors.
Class to represent name-value pairs of different types.
void assert_parameter_valid(const std::shared_ptr< ParameterInterface > ¶meter)
Check if a parameter exists and has the expected type, throw an exception otherwise.
void set_parameters(const ParameterInterfaceList ¶meters)
Set parameters from a list of parameters.
ParameterInterfaceMap parameters_
map of parameters by name
virtual void set_reference_frame(const std::string &reference_frame)
Setter of the reference frame.
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.
bool is_empty() const
Getter of the empty attribute.
Systems of equations relating state variables to their derivatives.
Core state variables and objects.