Merge branch 'Improved-servo-support' into 'main'
Improved servo support See merge request passer/cpp/roboidcontrol!3
This commit is contained in:
commit
fe3ca768d0
2
AbsoluteEncoder.cpp
Normal file
2
AbsoluteEncoder.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "AbsoluteEncoder.h"
|
||||
|
@ -5,11 +5,12 @@
|
||||
namespace Passer {
|
||||
namespace RoboidContol {
|
||||
|
||||
class FeedbackServo : public ServoMotor {
|
||||
class AbsoluteEncoder {
|
||||
public:
|
||||
FeedbackServo();
|
||||
AbsoluteEncoder() {}
|
||||
|
||||
virtual float GetActualAngle() = 0;
|
||||
virtual float GetActualVelocity() = 0;
|
||||
};
|
||||
|
||||
} // namespace RoboidContol
|
19
Encoder.cpp
19
Encoder.cpp
@ -1,18 +1,21 @@
|
||||
/*
|
||||
#include "Encoder.h"
|
||||
|
||||
Encoder::Encoder(unsigned char pulsesPerRevolution,
|
||||
unsigned char distancePerRotation) {
|
||||
//: Encoder::Encoder() {
|
||||
IncrementalEncoder::IncrementalEncoder(unsigned char pulsesPerRevolution,
|
||||
unsigned char distancePerRotation) {
|
||||
this->pulsesPerRevolution = pulsesPerRevolution;
|
||||
this->distancePerRevolution = distancePerRotation;
|
||||
}
|
||||
|
||||
int Encoder::GetPulseCount() { return 0; }
|
||||
int IncrementalEncoder::GetPulseCount() { return 0; }
|
||||
|
||||
float Encoder::GetDistance() { return 0; }
|
||||
float IncrementalEncoder::GetDistance() { return 0; }
|
||||
|
||||
float Encoder::GetPulsesPerSecond(float currentTimeMs) { return 0; }
|
||||
float IncrementalEncoder::GetPulsesPerSecond(float currentTimeMs) { return 0; }
|
||||
|
||||
float Encoder::GetRevolutionsPerSecond(float currentTimeMs) { return 0; }
|
||||
float IncrementalEncoder::GetRevolutionsPerSecond(float currentTimeMs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Encoder::GetSpeed(float currentTimeMs) { return 0; }
|
||||
float IncrementalEncoder::GetSpeed(float currentTimeMs) { return 0; }
|
||||
*/
|
20
Encoder.h
20
Encoder.h
@ -1,19 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "IncrementalEncoder.h"
|
||||
|
||||
namespace Passer {
|
||||
namespace RoboidControl {
|
||||
|
||||
/// @brief An Encoder measures the rotations of an axle using a rotary sensor
|
||||
/// Some encoders are able to detect direction, while others can not.
|
||||
class Encoder {
|
||||
// Deprecated, use explicit IncrementalEncoder in the future
|
||||
using Encoder = IncrementalEncoder;
|
||||
|
||||
/*
|
||||
/// @brief An Encoder measures the rotations of an axle using a rotary
|
||||
/// sensor Some encoders are able to detect direction, while others can not.
|
||||
class IncrementalEncoder {
|
||||
public:
|
||||
/// @brief Creates a sensor which measures distance from pulses
|
||||
/// @param pulsesPerRevolution The number of pulse edges which make a
|
||||
/// full rotation
|
||||
/// @param distancePerRevolution The distance a wheel travels per full
|
||||
/// rotation
|
||||
Encoder(unsigned char pulsesPerRevolution = 1,
|
||||
unsigned char distancePerRevolution = 1);
|
||||
IncrementalEncoder(unsigned char pulsesPerRevolution = 1,
|
||||
unsigned char distancePerRevolution = 1);
|
||||
|
||||
/// @brief Get the total number of pulses since the previous call
|
||||
/// @return The number of pulses, is zero or greater
|
||||
@ -45,7 +51,7 @@ public:
|
||||
/// meter
|
||||
unsigned char distancePerRevolution = 1;
|
||||
};
|
||||
|
||||
*/
|
||||
} // namespace RoboidControl
|
||||
} // namespace Passer
|
||||
using namespace Passer::RoboidControl;
|
||||
using namespace Passer::RoboidControl;
|
||||
|
@ -1,3 +0,0 @@
|
||||
#include "FeedbackServo.h"
|
||||
|
||||
FeedbackServo::FeedbackServo() {}
|
19
IncrementalEncoder.cpp
Normal file
19
IncrementalEncoder.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "Encoder.h"
|
||||
|
||||
IncrementalEncoder::IncrementalEncoder(unsigned char pulsesPerRevolution,
|
||||
unsigned char distancePerRotation) {
|
||||
this->pulsesPerRevolution = pulsesPerRevolution;
|
||||
this->distancePerRevolution = distancePerRotation;
|
||||
}
|
||||
|
||||
int IncrementalEncoder::GetPulseCount() { return 0; }
|
||||
|
||||
float IncrementalEncoder::GetDistance() { return 0; }
|
||||
|
||||
float IncrementalEncoder::GetPulsesPerSecond(float currentTimeMs) { return 0; }
|
||||
|
||||
float IncrementalEncoder::GetRevolutionsPerSecond(float currentTimeMs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float IncrementalEncoder::GetSpeed(float currentTimeMs) { return 0; }
|
51
IncrementalEncoder.h
Normal file
51
IncrementalEncoder.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
namespace Passer {
|
||||
namespace RoboidControl {
|
||||
|
||||
/// @brief An Encoder measures the rotations of an axle using a rotary
|
||||
/// sensor Some encoders are able to detect direction, while others can not.
|
||||
class IncrementalEncoder {
|
||||
public:
|
||||
/// @brief Creates a sensor which measures distance from pulses
|
||||
/// @param pulsesPerRevolution The number of pulse edges which make a
|
||||
/// full rotation
|
||||
/// @param distancePerRevolution The distance a wheel travels per full
|
||||
/// rotation
|
||||
IncrementalEncoder(unsigned char pulsesPerRevolution = 1,
|
||||
unsigned char distancePerRevolution = 1);
|
||||
|
||||
/// @brief Get the total number of pulses since the previous call
|
||||
/// @return The number of pulses, is zero or greater
|
||||
virtual int GetPulseCount();
|
||||
/// @brief Get the pulse speed since the previous call
|
||||
/// @param currentTimeMs The clock time in milliseconds
|
||||
/// @return The average pulses per second in the last period.
|
||||
virtual float GetPulsesPerSecond(float currentTimeMs);
|
||||
|
||||
/// @brief Get the distance traveled since the previous call
|
||||
/// @return The distance in meters.
|
||||
virtual float GetDistance();
|
||||
|
||||
/// @brief Get the rotation speed since the previous call
|
||||
/// @param currentTimeMs The clock time in milliseconds
|
||||
/// @return The speed in rotations per second
|
||||
virtual float GetRevolutionsPerSecond(float currentTimeMs);
|
||||
|
||||
/// @brief Get the speed since the previous call
|
||||
/// @param currentTimeMs The clock time in milliseconds
|
||||
/// @return The speed in meters per second.
|
||||
/// @note this value is dependent on the accurate setting of the
|
||||
/// pulsesPerRevolution and distancePerRevolution parameters;
|
||||
virtual float GetSpeed(float currentTimeMs);
|
||||
|
||||
/// @brief The numer of pulses corresponding to a full rotation of the axle
|
||||
unsigned char pulsesPerRevolution = 1;
|
||||
/// @brief The number of revolutions which makes the wheel move forward 1
|
||||
/// meter
|
||||
unsigned char distancePerRevolution = 1;
|
||||
};
|
||||
|
||||
} // namespace RoboidControl
|
||||
} // namespace Passer
|
||||
using namespace Passer::RoboidControl;
|
@ -1,3 +1,86 @@
|
||||
#include "ServoMotor.h"
|
||||
|
||||
ServoMotor::ServoMotor() {}
|
||||
#include "VectorAlgebra/FloatSingle.h"
|
||||
|
||||
ServoMotor::ServoMotor() {
|
||||
this->controlMode = ControlMode::Position;
|
||||
this->targetAngle = 0;
|
||||
this->hasTargetAngle = false;
|
||||
}
|
||||
|
||||
void ServoMotor::SetTargetAngle(float angle) {
|
||||
angle = Float::Clamp(angle, minAngle, maxAngle);
|
||||
|
||||
if (maxVelocity == 0.0F || hasTargetAngle == false) {
|
||||
SetAngle(angle);
|
||||
this->limitedTargetAngle = angle;
|
||||
} else if (angle != this->targetAngle) {
|
||||
// if the new target is the same, the limited angle is not overwritten
|
||||
this->limitedTargetAngle = this->targetAngle;
|
||||
}
|
||||
|
||||
this->controlMode = ControlMode::Position;
|
||||
this->targetAngle = angle;
|
||||
this->hasTargetAngle = true;
|
||||
}
|
||||
|
||||
float ServoMotor::GetTargetAngle() { return this->targetAngle; }
|
||||
|
||||
void ServoMotor::SetMaximumVelocity(float maxVelocity) {
|
||||
this->maxVelocity = maxVelocity;
|
||||
}
|
||||
|
||||
void ServoMotor::SetTargetVelocity(float targetVelocity) {
|
||||
targetVelocity =
|
||||
Float::Clamp(targetVelocity, -this->maxVelocity, maxVelocity);
|
||||
|
||||
this->controlMode = ControlMode::Velocity;
|
||||
this->targetVelocity = targetVelocity;
|
||||
this->hasTargetAngle = false; // can't we use the controlMode for this?
|
||||
}
|
||||
|
||||
float ServoMotor::GetTargetVelocity() { return this->targetVelocity; }
|
||||
|
||||
void ServoMotor::Update(float currentTimeMs) {
|
||||
if (this->lastUpdateTimeMs == 0 || currentTimeMs < this->lastUpdateTimeMs) {
|
||||
this->lastUpdateTimeMs = currentTimeMs;
|
||||
return;
|
||||
}
|
||||
|
||||
float deltaTime = (currentTimeMs - this->lastUpdateTimeMs) / 1000.0F;
|
||||
|
||||
if (controlMode == ControlMode::Position) {
|
||||
if (maxVelocity == 0.0F || hasTargetAngle == false) {
|
||||
this->lastUpdateTimeMs = currentTimeMs;
|
||||
return;
|
||||
|
||||
} else {
|
||||
float angleStep = maxVelocity * deltaTime;
|
||||
float deltaAngle = this->targetAngle - this->limitedTargetAngle;
|
||||
float absDeltaAngle = (deltaAngle < 0) ? -deltaAngle : deltaAngle;
|
||||
|
||||
if (absDeltaAngle < angleStep) {
|
||||
this->limitedTargetAngle = this->targetAngle;
|
||||
SetAngle(targetAngle);
|
||||
} else {
|
||||
if (deltaAngle < 0)
|
||||
limitedTargetAngle -= angleStep;
|
||||
else
|
||||
limitedTargetAngle += angleStep;
|
||||
}
|
||||
SetAngle(limitedTargetAngle);
|
||||
|
||||
this->lastUpdateTimeMs = currentTimeMs;
|
||||
return;
|
||||
}
|
||||
|
||||
} else { // Velocity Control
|
||||
float newAngle = this->targetAngle + targetVelocity * deltaTime;
|
||||
newAngle = Float::Clamp(newAngle, minAngle, maxAngle);
|
||||
|
||||
ServoMotor::SetTargetAngle(newAngle);
|
||||
SetAngle(newAngle);
|
||||
|
||||
this->lastUpdateTimeMs = currentTimeMs;
|
||||
}
|
||||
}
|
29
ServoMotor.h
29
ServoMotor.h
@ -9,7 +9,34 @@ class ServoMotor : public Thing {
|
||||
public:
|
||||
ServoMotor();
|
||||
|
||||
virtual void SetTargetAngle(float angle) = 0;
|
||||
float minAngle = -90.0F;
|
||||
float maxAngle = 90.0F;
|
||||
|
||||
enum ControlMode { Position, Velocity };
|
||||
ControlMode controlMode = ControlMode::Position;
|
||||
|
||||
virtual void SetTargetAngle(float angle);
|
||||
virtual float GetTargetAngle();
|
||||
|
||||
virtual void SetMaximumVelocity(float maxVelocity);
|
||||
|
||||
virtual void SetTargetVelocity(float velocity);
|
||||
virtual float GetTargetVelocity();
|
||||
|
||||
virtual void Update(float currentTimeMs);
|
||||
|
||||
protected:
|
||||
bool hasTargetAngle = false;
|
||||
float targetAngle = 0.0F;
|
||||
|
||||
float maxVelocity = 0.0F;
|
||||
|
||||
float targetVelocity = 0.0F;
|
||||
float limitedTargetAngle = 0.0F;
|
||||
|
||||
float lastUpdateTimeMs = 0.0F;
|
||||
|
||||
virtual void SetAngle(float angle) = 0;
|
||||
};
|
||||
|
||||
} // namespace RoboidContol
|
||||
|
Loading…
x
Reference in New Issue
Block a user