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->center_->get_value().set_empty();
23 this->rotation_offset_->set_value(
24 CartesianPose(
"rotation", Eigen::Quaterniond::Identity(), this->center_->get_value().get_name()));
25 this->
parameters_.insert(std::make_pair(
"center", this->center_));
26 this->
parameters_.insert(std::make_pair(
"rotation_offset", this->rotation_offset_));
27 this->
parameters_.insert(std::make_pair(
"radius", this->radius_));
28 this->
parameters_.insert(std::make_pair(
"width", this->width_));
29 this->
parameters_.insert(std::make_pair(
"speed", this->speed_));
30 this->
parameters_.insert(std::make_pair(
"field_strength", this->field_strength_));
31 this->
parameters_.insert(std::make_pair(
"normal_gain", this->normal_gain_));
32 this->
parameters_.insert(std::make_pair(
"angular_gain", this->angular_gain_));
35Ring::Ring(
const std::list<std::shared_ptr<state_representation::ParameterInterface>>& parameters) :
Ring() {
52 +
" is incompatible with the base frame of the dynamical system " + this->get_base_frame().get_name()
53 +
" in frame " + this->get_base_frame().get_reference_frame() +
"."
56 this->center_->set_value(this->
get_base_frame().inverse() * center);
58 this->center_->set_value(center);
60 this->set_rotation_offset(this->get_rotation_offset());
63void Ring::set_rotation_offset(
const Eigen::Quaterniond& rotation) {
64 auto pose =
CartesianPose(
"rotation", rotation, this->center_->get_value().get_name());
65 this->rotation_offset_->set_value(pose);
68Eigen::Quaterniond Ring::get_rotation_offset()
const {
69 return this->rotation_offset_->get_value().get_orientation();
78 if (!this->center_->get_value().is_empty()) {
79 auto center = this->center_->get_value();
81 this->center_->set_value(center);
85void Ring::validate_and_set_parameter(
const std::shared_ptr<ParameterInterface>& parameter) {
86 if (parameter->get_name() ==
"center") {
89 }
else if (parameter->get_name() ==
"rotation_offset") {
92 }
else if (parameter->get_name() ==
"radius") {
94 this->radius_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
95 }
else if (parameter->get_name() ==
"width") {
97 this->width_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
98 }
else if (parameter->get_name() ==
"speed") {
100 this->speed_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
101 }
else if (parameter->get_name() ==
"field_strength") {
103 this->field_strength_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
104 }
else if (parameter->get_name() ==
"normal_gain") {
106 this->normal_gain_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
107 }
else if (parameter->get_name() ==
"angular_gain") {
109 this->angular_gain_->set_value(std::static_pointer_cast<
Parameter<double>>(parameter)->get_value());
112 "No parameter with name '" + parameter->get_name() +
"' found"
117Eigen::Vector3d Ring::calculate_local_linear_velocity(
const CartesianPose& pose,
double& local_field_strength)
const {
118 Eigen::Vector3d local_linear_velocity = Eigen::Vector3d::Zero();
123 double d = position2d.norm();
125 return local_linear_velocity;
128 double re = M_PI_2 * (d - this->radius_->get_value()) / this->width_->get_value();
131 }
else if (re < -M_PI_2) {
137 R << -sin(re), -cos(re), cos(re), -sin(re);
138 Eigen::Vector2d velocity2d = R * position2d / d;
141 velocity2d *= this->speed_->get_value();
144 double vz = -this->normal_gain_->get_value() * pose.
get_position().z();
147 local_linear_velocity << velocity2d, vz;
150 local_field_strength = this->field_strength_->get_value() + (1 - this->field_strength_->get_value()) * cos(re);
151 local_linear_velocity *= local_field_strength;
153 return local_linear_velocity;
156Eigen::Vector3d Ring::calculate_local_angular_velocity(
157 const CartesianPose& pose,
const Eigen::Vector3d& linearVelocity,
double local_field_strength
159 Eigen::Vector3d local_angular_velocity = Eigen::Vector3d::Zero();
163 Eigen::Quaterniond qd = Eigen::Quaterniond::Identity();
164 qd.w() = cos(theta / 2);
165 qd.z() = sin(theta / 2);
168 qd.coeffs() = -qd.coeffs();
172 if (deltaQ.vec().norm() < 1e-7) {
173 return local_angular_velocity;
177 Eigen::Quaterniond deltaOmega = Eigen::Quaterniond::Identity();
179 double phi = atan2(deltaQ.vec().norm(), deltaQ.w());
180 deltaOmega.vec() = 2 * deltaQ.vec() * phi / sin(phi);
182 local_angular_velocity = this->angular_gain_->get_value() * deltaOmega.vec();
183 local_angular_velocity *= local_field_strength;
186 Eigen::Vector2d linear_velocity2d(linearVelocity.x(), linearVelocity.y());
187 if (position2d.norm() < 1e-7 || linear_velocity2d.norm() < 1e-7) {
188 return local_angular_velocity;
193 if (linear_velocity2d.norm() > (0.5 * position2d.norm())) {
194 linear_velocity2d = linear_velocity2d.normalized() * (0.5 * position2d).norm();
196 double projection = position2d.normalized().dot((position2d + linear_velocity2d).normalized());
198 if (1 - abs(projection) > 1e-7) {
199 dthetaZ = acos(projection);
201 local_angular_velocity.z() += dthetaZ;
203 return local_angular_velocity;
207 if (this->center_->get_value().is_empty()) {
212 pose = this->center_->get_value().inverse() * pose;
217 double local_field_strength;
218 twist.
set_linear_velocity(this->calculate_local_linear_velocity(pose, local_field_strength));
220 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 CartesianPose 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 CartesianState (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.
void assert_parameter_valid(const std::shared_ptr< ParameterInterface > ¶meter)
Check if a parameter 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 as const reference.
bool is_empty() const
Getter of the empty attribute.
Systems of equations relating state variables to their derivatives.
Core state variables and objects.