Skip to content

Commit 87aa7c9

Browse files
committed
Issue 14-2: Rewritten PIDReguator.cpp. Unit tests updated
1 parent dfc7c63 commit 87aa7c9

File tree

6 files changed

+59
-66
lines changed

6 files changed

+59
-66
lines changed

src/kpi_rover_ecu/include/PIDRegulator.h

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,19 @@
44
#pragma once
55

66
#include <array>
7-
#include <chrono>
8-
9-
#define SECONDSTOMINUTE 60
10-
#define MILISECONDSTOSECOND 1000
117

128
class PIDRegulator {
139
public:
14-
// PIDRegulator(vector<float> _coeficients);
15-
void Init(std::array<float, 3> _coeficients, int _loopsTicks, int _maxRPM);
16-
int Run(int setpoint, int ticksValue);
10+
void Init(std::array<float, 3> _coeficients);
11+
int Run(float kError, float kTimeDt);
1712

1813
private:
19-
float kp_;
20-
float ki_;
21-
float kd_;
22-
int previousError_ = 0;
23-
int integral_ = 0;
24-
const int kintegralLimit_ = 26500;
25-
const int koutputLimit_ = 26500;
26-
const int kSpeedIndexMultipler_ = 100;
27-
int loopsTicks_;
28-
int maxRPM_;
29-
30-
std::chrono::time_point<std::chrono::high_resolution_clock> lastTimePoint_;
14+
float kp_ = 0;
15+
float ki_ = 0;
16+
float kd_ = 0;
17+
float previousError_ = 0;
18+
float integral_ = 0;
19+
const float kIntegralLimit = 26500;
3120
};
3221

3322
#endif

src/kpi_rover_ecu/include/motor.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
#define MOTOR_H
33

44
#include <array>
5+
#include <chrono>
56

67
#include "PIDRegulator.h"
78

9+
#define SECONDSTOMINUTE 60
10+
#define MILISECONDSTOSECOND 1000
11+
812
class Motor {
913
public:
1014
static constexpr int kMinRpm = 8000;
1115
static constexpr int kMaxRpm = 26500;
1216
static constexpr int kLoopTicks = 821;
17+
static constexpr int kSpeedIndexMultipler = 100;
1318

1419
Motor(int assigned_number, bool is_inverted, std::array<float, 3> _coeficients);
1520
int MotorGo(int newRPM);
@@ -21,7 +26,10 @@ class Motor {
2126
static constexpr int kBrakeTime = 100000; // 100 ms
2227

2328
PIDRegulator pidRegulator_;
24-
int currentRpm_;
29+
int setpointRpm_;
30+
int actualRpm_;
31+
std::chrono::time_point<std::chrono::high_resolution_clock> lastTimePoint_;
32+
2533
int motorNumber_;
2634
bool inverted_;
2735
double currentDutyCycle_;

src/kpi_rover_ecu/src/PIDRegulator.cpp

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,28 @@
11
#include "PIDRegulator.h"
22

33
#include <array>
4-
#include <chrono>
54
#include <cmath>
6-
#include <iostream>
7-
#include <vector>
85

9-
void PIDRegulator::Init(std::array<float, 3> _coeficients, int _loopsTicks, int _maxRPM) {
6+
void PIDRegulator::Init(std::array<float, 3> _coeficients) {
107
kp_ = _coeficients[0];
118
ki_ = _coeficients[1];
129
kd_ = _coeficients[2];
13-
14-
loopsTicks_ = _loopsTicks;
15-
maxRPM_ = _maxRPM;
16-
lastTimePoint_ = std::chrono::high_resolution_clock::now();
17-
// cout << "PID regulator initialized" << '\n';
1810
}
1911

20-
int PIDRegulator::Run(int setpoint, int ticks_value) {
21-
const auto kCurrentTimePoint = std::chrono::high_resolution_clock::now();
22-
const std::chrono::duration<double, std::milli> kElapsedMilliseconds = kCurrentTimePoint - lastTimePoint_;
23-
lastTimePoint_ = kCurrentTimePoint;
24-
const auto kTimeDt = static_cast<float>(kElapsedMilliseconds.count());
25-
26-
const float kRevolutions = static_cast<float>(ticks_value) / static_cast<float>(loopsTicks_);
27-
28-
const float kInputPoint =
29-
static_cast<float>(std::round((kRevolutions * SECONDSTOMINUTE * MILISECONDSTOSECOND) / kTimeDt)) *
30-
kSpeedIndexMultipler_;
31-
32-
const float kError = static_cast<float>(setpoint) - kInputPoint;
33-
std::cout << "set point " << setpoint << " current point " << kInputPoint << " error " << kError << '\n';
34-
12+
int PIDRegulator::Run(float kError, float kTimeDt) {
3513
const float kPTerm = kp_ * kError;
3614

3715
integral_ += kError * kTimeDt;
38-
if (integral_ > kintegralLimit_) {
39-
integral_ = kintegralLimit_;
16+
if (integral_ > kIntegralLimit) {
17+
integral_ = kIntegralLimit;
4018
}
41-
if (integral_ < -kintegralLimit_) {
42-
integral_ = -kintegralLimit_;
19+
if (integral_ < -kIntegralLimit) {
20+
integral_ = -kIntegralLimit;
4321
}
4422

4523
const float kITerm = ki_ * integral_;
4624

47-
const float kDerivativePart = (kTimeDt > 0) ? (kError - previousError_) / kTimeDt : 0.0F;
25+
const float kDerivativePart = (kTimeDt > 0.0F) ? (kError - previousError_) / kTimeDt : 0.0F;
4826
const float kDTerm = kd_ * kDerivativePart;
4927

5028
previousError_ = kError;

src/kpi_rover_ecu/src/motor.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
#include <rc/encoder.h>
44
#include <rc/motor.h>
55

6+
#include <array>
7+
#include <chrono>
8+
#include <cmath>
69
#include <iostream>
710

811
#include "PIDRegulator.h"
912

1013
Motor::Motor(int assigned_number, bool is_inverted, std::array<float, 3> _coeficients)
11-
: motorNumber_(assigned_number), inverted_(is_inverted), currentDutyCycle_(0), currentRpm_(0) {
12-
pidRegulator_.Init(_coeficients, kLoopTicks, kMaxRpm);
14+
: motorNumber_(assigned_number), inverted_(is_inverted), currentDutyCycle_(0), setpointRpm_(0), actualRpm_(0) {
15+
pidRegulator_.Init(_coeficients);
16+
lastTimePoint_ = std::chrono::high_resolution_clock::now();
1317
}
1418

1519
int Motor::MotorGo(int newRPM) {
@@ -27,7 +31,7 @@ int Motor::MotorGo(int newRPM) {
2731
return -1;
2832
}
2933

30-
currentRpm_ = newRPM;
34+
setpointRpm_ = newRPM;
3135
return 0;
3236
}
3337

@@ -61,10 +65,24 @@ int Motor::GetEncoderCounter() {
6165
pid_encoder_ticks *= -1;
6266
}
6367

64-
const int kPidOutput = pidRegulator_.Run(currentRpm_, pid_encoder_ticks);
68+
const auto kCurrentTimePoint = std::chrono::high_resolution_clock::now();
69+
const std::chrono::duration<double, std::milli> kElapsedMilliseconds = kCurrentTimePoint - lastTimePoint_;
70+
lastTimePoint_ = kCurrentTimePoint;
71+
const auto kTimeDt = static_cast<float>(kElapsedMilliseconds.count());
72+
73+
const float kRevolutions = static_cast<float>(pid_encoder_ticks) / static_cast<float>(kLoopTicks);
74+
const float kInputPoint =
75+
static_cast<float>(std::round((kRevolutions * SECONDSTOMINUTE * MILISECONDSTOSECOND) / kTimeDt)) *
76+
kSpeedIndexMultipler;
77+
actualRpm_ = static_cast<int>(kInputPoint);
78+
const float kError = static_cast<float>(setpointRpm_) - kInputPoint;
79+
80+
std::cout << "set point " << setpointRpm_ << " current point " << kInputPoint << " error " << kError << '\n';
81+
82+
const int kPidOutput = pidRegulator_.Run(kError, kTimeDt);
6583
rc_encoder_write(motorNumber_, 0);
6684

67-
MotorSet(currentRpm_ + kPidOutput);
85+
MotorSet(setpointRpm_ + kPidOutput);
6886
return kEncoderTicks;
6987
}
7088

src/kpi_rover_ecu/tests/test_motor.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ TEST_F(MotorTest, MotorGoCallsRcMotorSet) {
3838
// Expect rc_motor_set to be called with channel 0 and duty cycle 256/1000.0
3939
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::DoubleEq(1))).WillOnce(::testing::Return(0));
4040

41-
motor = new Motor(0, false);
41+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
4242
int result = motor->MotorGo(Motor::kMaxRpm);
4343

4444
EXPECT_EQ(0, result) << "MotorGo should return success";
@@ -48,7 +48,7 @@ TEST_F(MotorTest, MotorGoCallsRcMotorSet) {
4848
TEST_F(MotorTest, MotorGoMinRPM) {
4949
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::_)).WillOnce(::testing::Return(0));
5050

51-
motor = new Motor(0, false);
51+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
5252
int result = motor->MotorGo(Motor::kMinRpm);
5353

5454
EXPECT_EQ(0, result);
@@ -59,7 +59,7 @@ TEST_F(MotorTest, MotorGoInverted) {
5959
// For inverted motor, the duty cycle should be negative
6060
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::Lt(0))).WillOnce(::testing::Return(0));
6161

62-
motor = new Motor(0, true);
62+
motor = new Motor(0, true, {1.5f, 0.056f, 1.5f});
6363
int result = motor->MotorGo(Motor::kMaxRpm);
6464

6565
EXPECT_EQ(0, result);
@@ -70,7 +70,7 @@ TEST_F(MotorTest, MotorGoBelowMinRPM) {
7070
// Verify behavior with RPM below minimum (should set to MIN_RPM or handle specially)
7171
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::_)).WillOnce(::testing::Return(0));
7272

73-
motor = new Motor(0, false);
73+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
7474
int result = motor->MotorGo(Motor::kMinRpm - 1);
7575

7676
EXPECT_EQ(0, result);
@@ -81,7 +81,7 @@ TEST_F(MotorTest, MotorGoAboveMaxRPM) {
8181
// Verify behavior with RPM above maximum (should clamp to MAX_RPM)
8282
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::DoubleEq(1))).WillOnce(::testing::Return(0));
8383

84-
motor = new Motor(0, false);
84+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
8585
int result = motor->MotorGo(Motor::kMaxRpm + 1);
8686

8787
EXPECT_EQ(0, result);
@@ -91,7 +91,7 @@ TEST_F(MotorTest, MotorGoAboveMaxRPM) {
9191
TEST_F(MotorTest, MotorGoSetError) {
9292
EXPECT_CALL(GetMockRCMotor(), set(0, ::testing::_)).WillOnce(::testing::Return(-1));
9393

94-
motor = new Motor(0, false);
94+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
9595
int result = motor->MotorGo(Motor::kMaxRpm);
9696

9797
EXPECT_NE(0, result) << "MotorGo should return error";
@@ -102,7 +102,7 @@ TEST_F(MotorTest, MotorStop) {
102102
// Stopping motor should set duty cycle to 0
103103
EXPECT_CALL(GetMockRCMotor(), brake(0)).WillOnce(::testing::Return(0));
104104

105-
motor = new Motor(0, false);
105+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
106106
int result = motor->MotorStop();
107107

108108
EXPECT_EQ(0, result) << "MotorStop should return success";
@@ -112,7 +112,7 @@ TEST_F(MotorTest, MotorStop) {
112112
TEST_F(MotorTest, MotorStopError) {
113113
EXPECT_CALL(GetMockRCMotor(), brake(0)).WillOnce(::testing::Return(-1));
114114

115-
motor = new Motor(0, false);
115+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
116116
int result = motor->MotorStop();
117117

118118
EXPECT_NE(0, result) << "MotorStop should return error";
@@ -122,7 +122,7 @@ TEST_F(MotorTest, MotorStopError) {
122122
TEST_F(MotorTest, GetEncoderCounter) {
123123
EXPECT_CALL(GetMockRCEncoder(), read(0)).WillOnce(::testing::Return(42));
124124

125-
motor = new Motor(0, false);
125+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
126126
int result = motor->GetEncoderCounter();
127127

128128
EXPECT_EQ(42, result) << "GetEncoderCounter should return encoder value";
@@ -132,7 +132,7 @@ TEST_F(MotorTest, GetEncoderCounter) {
132132
TEST_F(MotorTest, GetEncoderCounterError) {
133133
EXPECT_CALL(GetMockRCEncoder(), read(0)).WillOnce(::testing::Return(-1));
134134

135-
motor = new Motor(0, false);
135+
motor = new Motor(0, false, {1.5f, 0.056f, 1.5f});
136136
int result = motor->GetEncoderCounter();
137137

138138
EXPECT_EQ(-1, result) << "GetEncoderCounter should return error";

src/kpi_rover_ecu/tests/test_protocol.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ class ProtocolTest : public ::testing::Test {
4848
EXPECT_CALL(GetMockRCEncoder(), init()).WillOnce(::testing::Return(0));
4949

5050
// Initialize with the same configuration as in main.cpp
51-
std::vector<MotorConfig> chassis_config = {MotorConfig(1, false), MotorConfig(2, false), MotorConfig(3, true),
52-
MotorConfig(4, true)};
51+
std::vector<MotorConfig> chassis_config = {MotorConfig(1, false, {1.5f, 0.056f, 1.5f}), MotorConfig(2, false, {1.5f, 0.056f, 1.5f}), MotorConfig(3, true, {1.5f, 0.056f, 1.5f}),
52+
MotorConfig(4, true, {1.5f, 0.056f, 1.5f})};
5353

5454
motors_processor.Init(chassis_config, kMotorNumber);
5555
protocol_handler = new ProtocolHanlder(&motors_processor);

0 commit comments

Comments
 (0)