-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hugo/feature/Update MotionKit to Fusion #1292
Changes from all commits
d26062d
cafb664
3d39c35
5b2ee62
da669cf
5fb0885
9a12ca7
280f03a
8bb3ba3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Leka - LekaOS | ||
// Copyright 2023 APF France handicap | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#pragma once | ||
|
||
#include <functional> | ||
|
||
namespace leka { | ||
|
||
struct EulerAngles { | ||
float pitch; | ||
float roll; | ||
float yaw; | ||
}; | ||
|
||
namespace interface { | ||
|
||
class IMUKit | ||
{ | ||
public: | ||
using angles_ready_callback_t = std::function<void(const EulerAngles &)>; | ||
|
||
virtual ~IMUKit() = default; | ||
|
||
virtual void start() = 0; | ||
virtual void stop() = 0; | ||
|
||
virtual void setOrigin() = 0; | ||
virtual void onEulerAnglesReady(angles_ready_callback_t const &callback) = 0; | ||
[[nodiscard]] virtual auto getEulerAngles() const -> EulerAngles = 0; | ||
}; | ||
|
||
} // namespace interface | ||
|
||
} // namespace leka |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,63 +7,46 @@ | |
#include <interface/drivers/Motor.h> | ||
#include <interface/libs/EventLoop.h> | ||
|
||
#include "IMUKit.hpp" | ||
#include "PID.hpp" | ||
#include "RotationControl.hpp" | ||
#include "StabilizationControl.hpp" | ||
#include "interface/drivers/Timeout.h" | ||
#include "interface/libs/IMUKit.hpp" | ||
|
||
namespace leka { | ||
|
||
class MotionKit | ||
{ | ||
public: | ||
MotionKit(interface::Motor &motor_left, interface::Motor &motor_right, IMUKit &imu_kit, | ||
interface::EventLoop &event_loop, interface::Timeout &timeout) | ||
: _motor_left(motor_left), | ||
_motor_right(motor_right), | ||
_imukit(imu_kit), | ||
_event_loop(event_loop), | ||
_timeout(timeout) | ||
MotionKit(interface::Motor &motor_left, interface::Motor &motor_right, interface::IMUKit &imu_kit, | ||
interface::Timeout &timeout) | ||
: _motor_left(motor_left), _motor_right(motor_right), _imukit(imu_kit), _timeout(timeout) | ||
{ | ||
} | ||
|
||
void init(); | ||
|
||
void rotate(uint8_t number_of_rotations, Rotation direction, | ||
void rotate(float number_of_rotations, Rotation direction, | ||
const std::function<void()> &on_rotation_ended_callback = {}); | ||
void startStabilisation(); | ||
void startStabilization(); | ||
|
||
void stop(); | ||
|
||
private: | ||
void run(); | ||
void processAngleForRotation(const EulerAngles &angles, Rotation direction); | ||
void processAngleForStabilization(const EulerAngles &angles); | ||
Comment on lines
+33
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in a future PR, this should replaced by |
||
|
||
[[nodiscard]] auto mapSpeed(float speed) const -> float; | ||
void executeSpeed(float speed, Rotation direction); | ||
void setMotorsSpeedAndDirection(float speed, Rotation direction); | ||
|
||
interface::Motor &_motor_left; | ||
interface::Motor &_motor_right; | ||
IMUKit &_imukit; | ||
interface::EventLoop &_event_loop; | ||
interface::IMUKit &_imukit; | ||
interface::Timeout &_timeout; | ||
PID _pid; | ||
|
||
uint8_t _rotations_to_execute = 0; | ||
RotationControl _rotation_control; | ||
StabilizationControl _stabilization_control; | ||
Comment on lines
+43
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for now, we'll say this is okay. for 1.5.0, it must be refactored to instanciate control classes outside and register/start them when needed. on the same model as CommandKit This will allow us to add more controls without the need to recompile MotionKit |
||
|
||
std::function<void()> _on_rotation_ended_callback {}; | ||
|
||
bool _target_not_reached = false; | ||
bool _stabilisation_requested = false; | ||
bool _rotate_x_turns_requested = false; | ||
|
||
const float kReferenceAngle = 180.F; | ||
const float kPIDMaxValue = 1.8F; | ||
|
||
// ? When the motor is stopped, PWM values under kMinimalViableRobotPwm are too low to generate enough torque for | ||
// ? the motor to start spinning ? At the same time, kMinimalViableRobotPwm needs to be the lowest possible to avoid | ||
// ? overshooting when the target is reached | ||
|
||
const float kMinimalViableRobotPwm = 0.15F; | ||
const float kPwmMaxValue = 1.F; | ||
const float kEpsilon = 0.005F; | ||
}; | ||
|
||
} // namespace leka |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Leka - LekaOS | ||
// Copyright 2023 APF France handicap | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#pragma once | ||
|
||
#include "interface/libs/IMUKit.hpp" | ||
namespace leka { | ||
|
||
class RotationControl | ||
{ | ||
public: | ||
RotationControl() = default; | ||
|
||
void init(EulerAngles starting_angles, float number_of_rotations); | ||
auto processRotationAngle(EulerAngles current_angles) -> float; | ||
|
||
private: | ||
void calculateTotalYawRotation(EulerAngles angle); | ||
[[nodiscard]] auto mapSpeed(float speed) const -> float; | ||
|
||
// ? Kp, Ki, Kd were found empirically by increasing Kp until the rotation angle exceeds the target angle | ||
// ? Then increase Kd to fix this excess angle | ||
// ? Repeat this protocol until there is no Kd high enough to compensate Kp | ||
// ? Then take the last set of Kp, Kd value with no excess angle | ||
// ? Finally choose a low Ki that smooth out the movement | ||
struct Parameters { | ||
static constexpr auto Kp = float {0.3F}; | ||
static constexpr auto Ki = float {0.0001F}; | ||
static constexpr auto Kd = float {0.4F}; | ||
}; | ||
|
||
static constexpr float kStaticBound = 5.F; | ||
static constexpr float kDeltaT = 20.F; | ||
|
||
// ? When the motor is stopped, PWM values under kMinimalViableRobotPwm are too low to generate enough torque for | ||
// ? the motor to start spinning ? At the same time, kMinimalViableRobotPwm needs to be the lowest possible to avoid | ||
// ? overshooting when the target is reached | ||
static constexpr float kMinimalViableRobotPwm = 0.15F; | ||
static constexpr float kPwmMaxValue = 1.F; | ||
static constexpr float kEpsilon = 0.005F; | ||
|
||
static constexpr float kInputSpeedLimit = 90 * (Parameters::Kp + Parameters::Kd) / kDeltaT; | ||
|
||
float _angle_rotation_target = 0.F; | ||
float _angle_rotation_sum = 0.F; | ||
|
||
EulerAngles _euler_angles_previous {}; | ||
|
||
float _error_position_total = 0.F; | ||
float _error_position_last = 0.F; | ||
float _proportional = 0.F; | ||
float _integral = 0.F; | ||
float _derivative = 0.F; | ||
}; | ||
|
||
} // namespace leka |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in a futur PR/refactor, I think MotionKit will not depend on IMUKit but instead, each control class that needs it will depend on what is needed.
just like CommandKit
same for the motors, etc.
MotionKit will just need to start and stop the control without knowing what the control actually does.