forked from nobleo/path_tracking_pid
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
249 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# How to discretize a integral filter with Tustin's method\n", | ||
"First a continous time filter is constructed. This filter will be discretized with Tustin's method and converted into C++ code." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from sympy import *" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s, T, z = symbols('s,T,z')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"First our continous time system" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"sys = 1 / s" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Translate to discrete" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/latex": [ | ||
"$\\displaystyle \\frac{T \\left(z + 1\\right)}{2 \\left(z - 1\\right)}$" | ||
], | ||
"text/plain": [ | ||
"T*(z + 1)/(2*(z - 1))" | ||
] | ||
}, | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"sys = sys.subs(s, 2 / T * (z - 1) / (z + 1))\n", | ||
"sys" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Translate that to C++" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"```\n", | ||
"H = y/u = T / 2 * (z + 1)/(z - 1)\n", | ||
"\n", | ||
"u * T / 2 * (z + 1) = y * (z - 1)\n", | ||
"u * T / 2 * (1 + z^-1) = y * (1 - z^-1)\n", | ||
"T / 2 * (u[0] + u[1]) = y[0] - y[1]\n", | ||
"y[0] = T / 2 * (u[0] + u[1]) + y[1]\n", | ||
"```\n", | ||
"\n", | ||
"```c++\n", | ||
"y[0] = T / 2 * (u[0] + u[1]) + y[1]\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.8.10" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#pragma once | ||
|
||
#include <path_tracking_pid/details/fifo_array.hpp> | ||
|
||
namespace path_tracking_pid::details | ||
{ | ||
/** | ||
* @brief Discrete time integral filter | ||
*/ | ||
class Integral | ||
{ | ||
constexpr static auto NaN = std::numeric_limits<double>::quiet_NaN(); | ||
|
||
public: | ||
Integral() = default; | ||
|
||
/** | ||
* @brief Construct an integral filter | ||
* @param windup_limit Integral windup limit | ||
*/ | ||
explicit Integral(double windup_limit); | ||
|
||
/** | ||
* @brief Change the parameters of the filter | ||
* @param windup_limit Integral windup limit | ||
*/ | ||
void configure(double windup_limit); | ||
|
||
/** | ||
* @brief Filter one sample of a signal | ||
* @param u Signal to be filtered | ||
* @param step_size Time step from previous sample | ||
* @return Integral of the signal | ||
*/ | ||
double filter(double u, double step_size); | ||
|
||
/** | ||
* @brief Reset the signal buffers | ||
*/ | ||
void reset(); | ||
|
||
private: | ||
FifoArray<double, 2> u_ = {}; | ||
FifoArray<double, 2> y_ = {}; | ||
double windup_limit_ = NaN; | ||
}; | ||
|
||
} // namespace path_tracking_pid::details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#include <path_tracking_pid/details/integral.hpp> | ||
|
||
namespace path_tracking_pid::details | ||
{ | ||
Integral::Integral(double windup_limit) : windup_limit_(windup_limit) {} | ||
|
||
void Integral::configure(double windup_limit) { windup_limit_ = windup_limit; } | ||
|
||
double Integral::filter(double u, double step_size) | ||
{ | ||
// save history | ||
u_.push(u); | ||
y_.push(u); // increase index so the math below looks correct | ||
|
||
// A continous time integrator was discretized with Tustin's method. For a mathematical | ||
// explanation, see doc/integral_tustin.ipynb | ||
auto T = step_size; | ||
y_[0] = T / 2 * (u_[0] + u_[1]) + y_[1]; | ||
y_[0] = std::clamp(y_[0], -windup_limit_, windup_limit_); | ||
return y_[0]; | ||
} | ||
|
||
void Integral::reset() | ||
{ | ||
u_ = {}; | ||
y_ = {}; | ||
} | ||
} // namespace path_tracking_pid::details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include <gtest/gtest.h> | ||
|
||
#include <path_tracking_pid/details/integral.hpp> | ||
#include <vector> | ||
|
||
using path_tracking_pid::details::Integral; | ||
|
||
constexpr double eps = 1e-6; | ||
|
||
TEST(Integral, StepResponse) | ||
{ | ||
double dt = 0.1; | ||
double windup_limit = 0.5; | ||
|
||
Integral filter{windup_limit}; | ||
|
||
std::vector<double> expected_response = {0.05, 0.15, 0.25, 0.35, 0.45, 0.5, 0.5}; | ||
for (int i = 0; i < static_cast<int>(expected_response.size()); ++i) { | ||
SCOPED_TRACE(i); | ||
|
||
auto result = filter.filter(1, dt); | ||
EXPECT_NEAR(result, expected_response[i], eps); | ||
} | ||
} |