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 Passer { | ||||||
| namespace RoboidContol { | namespace RoboidContol { | ||||||
| 
 | 
 | ||||||
| class FeedbackServo : public ServoMotor { | class AbsoluteEncoder { | ||||||
| public: | public: | ||||||
|   FeedbackServo(); |   AbsoluteEncoder() {} | ||||||
| 
 | 
 | ||||||
|   virtual float GetActualAngle() = 0; |   virtual float GetActualAngle() = 0; | ||||||
|  |   virtual float GetActualVelocity() = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace RoboidContol
 | } // namespace RoboidContol
 | ||||||
							
								
								
									
										17
									
								
								Encoder.cpp
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								Encoder.cpp
									
									
									
									
									
								
							| @ -1,18 +1,21 @@ | |||||||
|  | /*
 | ||||||
| #include "Encoder.h" | #include "Encoder.h" | ||||||
| 
 | 
 | ||||||
| Encoder::Encoder(unsigned char pulsesPerRevolution, | IncrementalEncoder::IncrementalEncoder(unsigned char pulsesPerRevolution, | ||||||
|                                        unsigned char distancePerRotation) { |                                        unsigned char distancePerRotation) { | ||||||
|   //: Encoder::Encoder() {
 |  | ||||||
|   this->pulsesPerRevolution = pulsesPerRevolution; |   this->pulsesPerRevolution = pulsesPerRevolution; | ||||||
|   this->distancePerRevolution = distancePerRotation; |   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; } | ||||||
|  | */ | ||||||
							
								
								
									
										16
									
								
								Encoder.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Encoder.h
									
									
									
									
									
								
							| @ -1,18 +1,24 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "IncrementalEncoder.h" | ||||||
|  | 
 | ||||||
| namespace Passer { | namespace Passer { | ||||||
| namespace RoboidControl { | namespace RoboidControl { | ||||||
| 
 | 
 | ||||||
| /// @brief An Encoder measures the rotations of an axle using a rotary sensor
 | // Deprecated, use explicit IncrementalEncoder in the future
 | ||||||
| /// Some encoders are able to detect direction, while others can not.
 | using Encoder = IncrementalEncoder; | ||||||
| class Encoder { | 
 | ||||||
|  | /*
 | ||||||
|  | /// @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: | public: | ||||||
|   /// @brief Creates a sensor which measures distance from pulses
 |   /// @brief Creates a sensor which measures distance from pulses
 | ||||||
|   /// @param pulsesPerRevolution The number of pulse edges which make a
 |   /// @param pulsesPerRevolution The number of pulse edges which make a
 | ||||||
|   /// full rotation
 |   /// full rotation
 | ||||||
|   /// @param distancePerRevolution The distance a wheel travels per full
 |   /// @param distancePerRevolution The distance a wheel travels per full
 | ||||||
|   /// rotation
 |   /// rotation
 | ||||||
|   Encoder(unsigned char pulsesPerRevolution = 1, |   IncrementalEncoder(unsigned char pulsesPerRevolution = 1, | ||||||
|                      unsigned char distancePerRevolution = 1); |                      unsigned char distancePerRevolution = 1); | ||||||
| 
 | 
 | ||||||
|   /// @brief Get the total number of pulses since the previous call
 |   /// @brief Get the total number of pulses since the previous call
 | ||||||
| @ -45,7 +51,7 @@ public: | |||||||
|   /// meter
 |   /// meter
 | ||||||
|   unsigned char distancePerRevolution = 1; |   unsigned char distancePerRevolution = 1; | ||||||
| }; | }; | ||||||
| 
 | */ | ||||||
| } // namespace RoboidControl
 | } // namespace RoboidControl
 | ||||||
| } // namespace Passer
 | } // 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" | #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: | public: | ||||||
|   ServoMotor(); |   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
 | } // namespace RoboidContol
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Pascal Serrarens
						Pascal Serrarens