Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 1:ceee5a608e7c, committed 2019-03-28
- Comitter:
- alexpirciu
- Date:
- Thu Mar 28 07:44:42 2019 +0000
- Parent:
- 0:c3e774091195
- Commit message:
- assa
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/BezierCurve/beziercurve.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,68 @@
+/**
+ ******************************************************************************
+ * @file BezierCurve.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the Bezier Curve
+ * methods.
+ ******************************************************************************
+ */
+
+/* include guard */
+#ifndef BEZIERCURVE_HPP
+#define BEZIERCURVE_HPP
+
+/* complex numbers in cartesian form and several functions and overloads to operate with them */
+#include <complex>
+#include <BezierCurve/PolynomialFunction.hpp>
+
+#define BEZIER_ORDER 3
+
+namespace math{
+ /**
+ * @brief It implements the functionality of a Bezier curve. The points on the curve are represented by complex numbers and the input value of the curve have to belong to the interval [0,1].
+ *
+ * @tparam T The type of the Bezier curve.
+ */
+ template<class T>
+ class BezierCurve
+ {
+ public:
+ /* Constructors */
+ BezierCurve();
+ BezierCurve(std::complex<T> points[BEZIER_ORDER+1]);
+ BezierCurve(std::complex<T> a,std::complex<T> b,std::complex<T> c,std::complex<T> d);
+ /* Destructor */
+ virtual ~BezierCurve();
+ /* Set curve */
+ void setBezierCurve(std::complex<T> a,std::complex<T> b,std::complex<T> c,std::complex<T> d);
+ /* Get value */
+ std::complex<T> getValue(float input_value);
+ /* First order derivate value */
+ std::complex<T> get_FO_DerivateValue(float input_value);
+ /* Second order derivate value */
+ std::complex<T> get_SO_DerivateValue(float input_value);
+
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER > getBezierCurve();
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-1> getFODerivate();
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-2> getSODerivate();
+
+ protected:
+
+ private:
+ // PRIVATE FUNCTIONS
+ // Convert the complex points to polynomial function
+ math::PolynomialFunction<std::complex<float>,BEZIER_ORDER> CP2PF();
+
+ // PRIVATE PARAMETERS
+ std::complex<T> points[BEZIER_ORDER+1];
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER> bezierCurve;
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-1> FOder_bezierCurve;
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-2> SOder_bezierCurve;
+ };
+};//namespace math
+#include "beziercurve.inl"
+
+#endif // BEZIERCURVE_HPP
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/BezierCurve/beziercurve.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,167 @@
+
+namespace math{
+
+ /**
+ * @brief Construct a new Bezier Curve< T>:: Bezier Curve object
+ *
+ */
+ template<class T>
+ BezierCurve<T>::BezierCurve(){
+ }
+
+ /**
+ * @brief Construct a new Bezier Curve< T>:: Bezier Curve object
+ *
+ * @param a point A
+ * @param b point B
+ * @param c point C
+ * @param d point D
+ */
+ template<class T>
+ BezierCurve<T>::BezierCurve(std::complex<T> a,std::complex<T> b,std::complex<T> c,std::complex<T> d){
+ this->points[0]=a;
+ this->points[1]=b;
+ this->points[2]=c;
+ this->points[3]=d;
+
+ this->bezierCurve=this->CP2PF();
+ this->FOder_bezierCurve=this->bezierCurve.derivateFO();
+ this->SOder_bezierCurve=this->FOder_bezierCurve.derivateFO();
+ }
+
+ /**
+ * @brief Construct a new Bezier Curve< T>:: Bezier Curve object
+ *
+ * @param points Array of points
+ */
+ template<class T>
+ BezierCurve<T>::BezierCurve(std::complex<T> points[BEZIER_ORDER+1])
+ {
+ for(int32_t i=0;i<=BEZIER_ORDER;++i){
+ this->points[i]=points[i];
+ }
+ this->bezierCurve=this->CP2PF();
+ this->FOder_bezierCurve=this->bezierCurve.derivateFO();
+ this->SOder_bezierCurve=this->FOder_bezierCurve.derivateFO();
+ }
+
+ /**
+ * @brief Destroy the Bezier Curve< T>:: Bezier Curve object
+ *
+ */
+ template<class T>
+ BezierCurve<T>::~BezierCurve()
+ {
+ //dtor
+ }
+
+ /**
+ * @brief This metohd create a new polynomial function based on the complex points.
+ *
+ * @return The result polynomial function represent the Bezier curve.
+ */
+ template<class T>
+ math::PolynomialFunction<std::complex<float>,BEZIER_ORDER> BezierCurve<T>::CP2PF(){
+ math::PolynomialFunction<std::complex<float>,BEZIER_ORDER> pf;
+
+ const std::complex<T> temp_cst_3(3,0);
+ const std::complex<T> temp_cst_2(2,0);
+
+ std::complex<T> coef1=temp_cst_3*(this->points[1]-this->points[0]);
+ std::complex<T> coef2=temp_cst_3*(this->points[0]-temp_cst_2*this->points[1]+this->points[2]);
+ std::complex<T> coef3=temp_cst_3*(this->points[1]-this->points[2])+this->points[3]-this->points[0];
+ pf.setCoefficientValue(0,this->points[0]);
+ pf.setCoefficientValue(1,coef1);
+ pf.setCoefficientValue(2,coef2);
+ pf.setCoefficientValue(3,coef3);
+ return pf;
+ }
+
+ /**
+ * @brief Get the point on the bezier curve.
+ *
+ * @param input_value The input value, it must belong to interval [0,1].
+ * @return The point as complex number
+ */
+ template<class T>
+ std::complex<T> BezierCurve<T>::getValue(float input_value){
+ T input_value_T=static_cast<T>(input_value);
+ return this->bezierCurve.calculateValue(input_value);
+ }
+
+ template<class T>
+ /**
+ * @brief Get the value of the first order derivative of Bezier curve
+ *
+ * @param input_value The input value [0,1]
+ * @return The point as a complex number.
+ *
+ */
+ std::complex<T> BezierCurve<T>::get_FO_DerivateValue(float input_value){
+ T input_value_T=static_cast<T>(input_value);
+ return this->FOder_bezierCurve.calculateValue(input_value_T);
+ }
+
+ /**
+ * @brief Get the value of the second order derivative of Bezier Curve.
+ *
+ * @param input_value The input value of the function have to belong to interval [0,1]
+ * @return The resulted value as a complex number.
+ */
+ template<class T>
+ std::complex<T> BezierCurve<T>::get_SO_DerivateValue(float input_value){
+ T input_value_T=static_cast<T>(input_value);
+
+ return this->SOder_bezierCurve.calculateValue(input_value_T);
+ }
+
+ /**
+ * @brief Get the polynomial function, which respresents the Bezier curve.
+ *
+ */
+ template<class T>
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER> BezierCurve<T>::getBezierCurve(){
+ return this->bezierCurve;
+ }
+
+ /**
+ * @brief Get resulted polynomial function of the first order derivative
+ *
+ * @return math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-1>
+ */
+ template<class T>
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-1> BezierCurve<T>::getFODerivate(){
+ return this->FOder_bezierCurve;
+ }
+
+ template<class T>
+ /**
+ * @brief Get resulted polynomial function of the second order derivative
+ *
+ * @return math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-2>
+ */
+ math::PolynomialFunction<std::complex<T>,BEZIER_ORDER-2> BezierCurve<T>::getSODerivate(){
+ return this->SOder_bezierCurve;
+ }
+
+ template<class T>
+ /**
+ * @brief Set the points for creating a new Bezier curve
+ *
+ * @param a point A
+ * @param b point B
+ * @param c point C
+ * @param d point D
+ */
+ void BezierCurve<T>::setBezierCurve(std::complex<T> a,std::complex<T> b,std::complex<T> c,std::complex<T> d){
+ this->points[0]=a;
+ this->points[1]=b;
+ this->points[2]=c;
+ this->points[3]=d;
+
+ this->bezierCurve=this->CP2PF();
+ this->FOder_bezierCurve=this->bezierCurve.derivateFO();
+ this->SOder_bezierCurve=this->FOder_bezierCurve.derivateFO();
+ }
+
+}; // namespace math
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/BezierCurve/polynomialfunction.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,67 @@
+/**
+ ******************************************************************************
+ * @file PolynomialFunction.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the Plynomial Function
+ * methods.
+ ******************************************************************************
+ */
+
+/* include guard */
+#ifndef POLYNOMIALFUNCTION_HPP
+#define POLYNOMIALFUNCTION_HPP
+
+#include <stdint.h>
+#include <math.h>
+#include <iostream>
+
+
+namespace math{
+ /**
+ * @brief It represents a one dimensional polynomial function
+ *
+ * @tparam T The type of the Polynomial function
+ * @tparam N The degree of the polynom.
+ */
+ template <class T,int32_t N>
+ class PolynomialFunction
+ {
+ public:
+ /* Constructors */
+ PolynomialFunction();
+ PolynomialFunction(T coefficients[N+1]);
+ /* Destructors */
+ virtual ~PolynomialFunction();
+
+ // template<int32_t N2> void add(PolynomialFunction<T,N2> poli);
+ /* Add */
+ template<int32_t N2> math::PolynomialFunction<T,(N2<N?N:N2)> add(PolynomialFunction<T,N2> b);
+ /* Multiply */
+ template<int32_t N2> math::PolynomialFunction<T,(N2+N)> multip(PolynomialFunction<T,N2> b);
+ /* Calculate value */
+ T calculateValue(T input_value);
+ /* First order derivate */
+ math::PolynomialFunction<T,N-1> derivateFO();
+ /* Get degree */
+ int32_t getDegree();
+ /* Get coefficient value */
+ T getCoefficientValue(int32_t index);
+ /* Set coefficient value */
+ void setCoefficientValue(int32_t index,T value );
+ private:
+ /* Coefficients array */
+ /**
+ * @brief The list of the coeffients.
+ *
+ */
+ T coefficients[N+1];
+ };
+
+}; // namepace math
+
+#include "polynomialfunction.inl"
+
+#endif // POLYNOMIALFUNCTION_HPP
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/BezierCurve/polynomialfunction.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,144 @@
+
+namespace math{
+
+/**
+ * @brief Construct a new Polynomial Function< T, N>:: Polynomial Function object
+ *
+ */
+template<class T,int32_t N>
+PolynomialFunction<T,N>::PolynomialFunction()
+{
+ for(int i=0;i<=N;++i){
+ this->coefficients[i]=static_cast<T>(0);
+ }
+}
+
+/**
+ * @brief Construct a new Polynomial Function< T, N>:: Polynomial Function object
+ *
+ * @param coefficients The list of the coefficients for the polynomial function.
+ */
+template<class T,int32_t N>
+PolynomialFunction<T,N>::PolynomialFunction(T coefficients[N+1])
+{
+ for(int i=0;i<=N;++i){
+ this->coefficients[i]=coefficients[i];
+ }
+}
+
+/**
+ * @brief Destroy the Polynomial Function< T, N>:: Polynomial Function object
+ *
+ */
+template<class T,int32_t N>
+PolynomialFunction<T,N>::~PolynomialFunction()
+{
+}
+
+/**
+ * @brief Get the degree of the polynomial function
+ *
+ * @return The degree of the polynom
+ */
+template<class T,int32_t N>
+int32_t PolynomialFunction<T,N>::getDegree()
+{
+ return N;
+}
+
+/**
+ * @brief Get coefficient value
+ *
+ * @param index The index of the coefficient
+ * @return The value of the coefficient
+ */
+template<class T,int32_t N>
+T PolynomialFunction<T,N>::getCoefficientValue(int32_t index)
+{
+ if(index>N || index<0) return static_cast<T>(0);
+ return this->coefficients[index];
+}
+
+/**
+ * @brief Set the value of the coefficient
+ *
+ * @param index The index of the coefficient
+ * @param value The new value of the coefficient
+ */
+template<class T,int32_t N>
+void PolynomialFunction<T,N>::setCoefficientValue(int32_t index, T value ){
+ if(index<=N){
+ this->coefficients[index]=value;
+ }
+}
+
+/**
+ * @brief It sums the polynom with the input polynom and return a result in the new polynom.
+ *
+ * @param b The input polynom.
+ * @return The result polynom.
+ */
+template<class T,int32_t N>
+template<int32_t N2>
+math::PolynomialFunction<T,(N2<N?N:N2)> PolynomialFunction<T,N>::add(PolynomialFunction<T,N2> b){
+ math::PolynomialFunction<T,N2<N?N:N2> p;
+ for(int i=0;i<=N2 || i<=N;++i){
+ p.setCoefficientValue(i,this->getCoefficientValue(i)+b.getCoefficientValue(i));
+ }
+ return p;
+}
+
+
+template<class T,int32_t N>
+template<int32_t N2>
+/**
+ * @brief It multiply the polynom with the given polynom and return the result polynom.
+ *
+ * @param b The input polynom
+ * @return The result polynom
+ */
+math::PolynomialFunction<T,(N2+N)> PolynomialFunction<T,N>::multip(PolynomialFunction<T,N2> b){
+ math::PolynomialFunction<T,(N2+N)> result;
+ for(int32_t i=0;i<=N2+N;++i){
+ T sum=static_cast<T>(0);
+ for(int32_t j=0;j<=i;++j){
+ sum+=this->getCoefficientValue(j)*b.getCoefficientValue(i-j);
+ }
+ result.setCoefficientValue(i,sum);
+ }
+
+ return result;
+}
+
+template<class T,int32_t N>
+/**
+ * @brief Calculate the polynom value
+ *
+ * @param input_value The given value
+ * @return The result value of the polynom.
+ */
+T PolynomialFunction<T,N>::calculateValue(T input_value){
+ T output_value=static_cast<T>(0);
+ for(int32_t i=0;i<=N;++i){
+ output_value+=this->coefficients[i]*static_cast<T>(pow(input_value,i));
+ }
+// std::cout<<"OOO"<<output_value<<std::endl;
+ return output_value;
+}
+
+template<class T, int32_t N>
+/**
+ * @brief It calcutes the first derivate of the polinom and return it by creating a new polynomial function object.
+ *
+ * @return The result polynom.
+ */
+math::PolynomialFunction<T,N-1> PolynomialFunction<T,N>::derivateFO(){
+ math::PolynomialFunction<T,N-1> derivate;
+ for(int32_t i=0;i<N;++i){
+ T coeff=static_cast<T>(i+1);
+ derivate.setCoefficientValue(i,coeff*this->getCoefficientValue(i+1));
+ }
+ return derivate;
+};
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/BezierMotionPlanner/beziermotionplanner.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,86 @@
+/**
+ ******************************************************************************
+ * @file BezierMotionPlanner.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the Bezier Motion
+ * Planner methods.
+ ******************************************************************************
+ */
+
+/* include guard */
+#ifndef MOTIONPLANNER_HPP
+#define MOTIONPLANNER_HPP
+
+#include <complex>
+#include <utility>
+#include <math.h>
+#include <BezierCurve/BezierCurve.hpp>
+
+/* Module defines */
+#define WHEELBASE 0.265
+
+namespace planner{
+
+ /** CBezierMotionPlanner class.
+ * @brief This class implements the functionality of planner to keep the robot on the given Bezier curve.
+ *
+ */
+ class CBezierMotionPlanner
+ {
+ public:
+ /* Constructor */
+ CBezierMotionPlanner();
+ /* Constructor */
+ CBezierMotionPlanner(bool isForward,
+ std::complex<float> a,
+ std::complex<float> b,
+ std::complex<float> c,
+ std::complex<float> d,
+ float motion_duration_i,
+ float timestep_i);
+ /* Set parameters */
+ void setMotionPlannerParameters(bool isForward,
+ std::complex<float> a,
+ std::complex<float> b,
+ std::complex<float> c,
+ std::complex<float> d,
+ float motion_duration_i,
+ float timestep_i);
+ /* Destructor */
+ virtual ~CBezierMotionPlanner();
+ /* Get Bezier Curve */
+ math::BezierCurve<float> getBezierCurve();
+ // Velocity longitudinal and angular
+ /* Get next velocity value */
+ std::pair<float,float> getNextVelocity();
+ // Velocity longitudinal and angular, Input value [0,1]
+ /* Get velocity value */
+ std::pair<float,float> getVelocity(float input_value);
+ /* Next value valid */
+ bool hasValidValue();
+ /* Is movement forward */
+ bool getForward();
+
+ private:
+ /* forward movement indicator */
+ bool isForward;
+ /* Bezier Curve object */
+ math::BezierCurve<float> bezierCurve;
+ /* motion duration */
+ float motion_duration;
+ /* time step */
+ float time_step;
+ /* Bezier value input step */
+ float bezierValueInput_step;
+ /* next Bezier value */
+ float next_bezierValueInput;
+ /* intialization indicator */
+ bool isInitialized;
+ };
+
+}; // namespace planner
+
+#endif // CMotionPlanner_HPP
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/CommandInterpreter/commandinterpreter.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,52 @@
+/**
+ ******************************************************************************
+ * @file CommandInterpreter.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the command interpreter
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef COMMAND_INTERPRETER_HPP
+#define COMMAND_INTERPRETER_HPP
+
+/* The mbed library */
+#include <mbed.h>
+#include <Move/move.hpp>
+#include <Queue/queue.hpp>
+
+//! CTimer class.
+/*!
+ * It is used for implementing the interpreter of commands received by Nucleo.
+ * */
+class CCommandInterpreter
+{
+public:
+ /* Constuctor */
+ CCommandInterpreter(Move& f_car);
+ /* Interpret character */
+ inline void interpretChar(unsigned char f_c);
+ /* Execute command */
+ inline void executeCommand();
+private:
+ /* Reset */
+ inline void reset();
+ /* Interpret command */
+ inline void intepretCommand();
+ /* buffer */
+ CQueue<unsigned char, 7> m_buffer;
+ /* reference to MOVE object */
+ Move& m_car;
+ unsigned char m_commandID;
+ /* command value */
+ float m_commandValue;
+ /* speed value */
+ float m_speedValue;
+ /* angle value */
+ float m_angleValue;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Controllers/controller.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,83 @@
+/**
+ ******************************************************************************
+ * @file Controller.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the controller
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+
+#ifndef CONTROLLER_HPP
+#define CONTROLLER_HPP
+#include<cmath>
+#include<Controllers/pidcontroller.hpp>
+
+#include <Encoders/encoderinterface.hpp>
+#include <Controllers/converters.hpp>
+
+#include <mbed.h>
+
+namespace controllers
+{
+
+ /** CControllerSiso class
+ * @brief It implements a controller with a single input and a single output. It needs an encoder getter interface to get the measured values, a controller to calculate the control signal. It can be completed with a converter to convert the measaurment unit of the control signal.
+ *
+ */
+ class CControllerSiso
+ {
+ /* PID controller declaration*/
+ template <class T>
+ using ControllerType=siso::IController<T>;
+
+ public:
+ /* Construnctor */
+ CControllerSiso(encoders::IEncoderGetter& f_encoder
+ ,ControllerType<double>& f_pid
+ ,controllers::IConverter* f_converter=NULL);
+ /* Set controller reference value */
+ void setRef(double f_RefRps);
+ /* Get controller reference value */
+ double getRef();
+ /* Get control value */
+ double get();
+ /* Get error */
+ double getError();
+ /* Clear PID parameters */
+ void clear();
+ /* Control action */
+ bool control();
+
+ private:
+ /* PWM onverter */
+ double converter(double f_u);
+
+ /* Enconder object reference */
+ encoders::IEncoderGetter& m_encoder;
+ /* PID object reference */
+ ControllerType<double>& m_pid;
+ /* Controller reference */
+ double m_RefRps;
+ /* Control value */
+ double m_u;
+ /* Error */
+ double m_error;
+ /* Converter */
+ controllers::IConverter* m_converter;
+ /* Scaled PWM control signal limits */
+ const float m_control_sup;
+ const float m_control_inf;
+ /* Inferior limit of absolut reference */
+ const float m_ref_abs_inf;
+ /* Inferior and superior limits of absolute speed measurment for standing state */
+ const float m_mes_abs_inf;
+ const float m_mes_abs_sup;
+
+ };
+}; // namespace controllers
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Controllers/converters.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,74 @@
+/**
+******************************************************************************
+* @file converters.hpp
+* @author RBRO/PJ-IU
+* @version V1.0.0
+* @date 2018-10-29
+* @brief
+******************************************************************************
+*/
+#ifndef CONVERTERS_H
+#define CONVERTERS_H
+
+#include<cmath>
+#include<stdint.h>
+#include<array>
+
+namespace controllers{
+ /**
+ * @brief Converter interface with single input and single output
+ *
+ */
+ class IConverter{
+ public:
+ virtual float operator()(float) = 0;
+ };
+
+ /**
+ * @brief Polynomial converter.
+ *
+ * @tparam NOrd The degree of the polynomial converter
+ */
+ template<uint8_t NOrd>
+ class CConverterPolynom:public IConverter
+ {
+ public:
+ CConverterPolynom(std::array<float,NOrd+1>);
+ float operator()(float);
+
+ private:
+ std::array<float,NOrd+1> m_coeff;
+ };
+
+ /**
+ * @brief A converter based on the set of break point and the multiple polynomial function.
+ *
+ * @tparam NrBreak Number of the break.
+ * @tparam NOrd Degree of the polynomial converter.
+ */
+ template<uint8_t NrBreak,uint8_t NOrd>
+ class CConverterSpline:public IConverter
+ {
+ public:
+ using CCoeffContainerType = std::array<float,NOrd+1>;
+ using CSplineContainerType = std::array<CCoeffContainerType,NrBreak+1>;
+ using CBreakContainerType = std::array<float,NrBreak>;
+
+
+ CConverterSpline(CBreakContainerType f_breaks,CSplineContainerType f_splines);
+ float operator()(float);
+ private:
+ float splineValue( CCoeffContainerType,float);
+
+ CBreakContainerType m_breaks;
+ CSplineContainerType m_splines;
+
+ };
+
+ #include "converters.inl"
+}; //namespace controllers
+
+
+
+#endif // CONVERTERS_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Controllers/converters.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,77 @@
+
+
+/**
+ * @brief Construct a new CConverterPolynom<NOrd>::CConverterPolynom object
+ *
+ * @param f_coeff The list of the coeffience.
+ */
+template<uint8_t NOrd>
+CConverterPolynom<NOrd>::CConverterPolynom(std::array<float,NOrd+1> f_coeff)
+:m_coeff(f_coeff)
+{
+}
+
+
+/**
+ * @brief Convert the input value.
+ *
+ */
+template<uint8_t NOrd>
+float CConverterPolynom<NOrd>::operator()(float f_v){
+ float l_res = m_coeff[NOrd];
+ for (uint8_t i = 0;i<NOrd;++i){
+ l_res += std::pow(f_v, NOrd-i)*m_coeff[i];
+ }
+ return l_res;
+}
+
+
+/**
+ * @brief Construct a new CConverterSpline<NrBreak, NOrd>::CConverterSpline object
+ *
+ * @tparam NrBreak
+ * @tparam NOrd
+ * @param f_breaks The list of the break points.
+ * @param f_splines The list of the polynomial function.
+ */
+template <uint8_t NrBreak, uint8_t NOrd>
+CConverterSpline<NrBreak, NOrd>::CConverterSpline(CConverterSpline<NrBreak, NOrd>::CBreakContainerType f_breaks,CConverterSpline<NrBreak, NOrd>::CSplineContainerType f_splines)
+:m_breaks(f_breaks)
+,m_splines(f_splines)
+{
+}
+
+/**
+ * @brief Convert the input value.
+ *
+ */
+template <uint8_t NrBreak, uint8_t NOrd>
+float CConverterSpline<NrBreak, NOrd>::operator()(float f_value){
+ typename CConverterSpline<NrBreak, NOrd>::CBreakContainerType::iterator it_breaks0=NULL,it_breaks1=NULL;
+ typename CConverterSpline<NrBreak, NOrd>::CSplineContainerType::iterator it_spline = m_splines.begin();
+ for (it_breaks1 = m_breaks.begin();it_breaks1 != m_breaks.end();){
+ if((it_breaks0==NULL || (it_breaks0!=NULL && (*it_breaks0)<f_value)) && f_value<=(*it_breaks1)){
+ break;
+ }
+ it_breaks0 = it_breaks1;
+ ++it_breaks1;
+ ++it_spline;
+ }
+ return this->splineValue(*it_spline, f_value);
+}
+
+/**
+ * @brief Convert the given value, by using the given polynom.
+ *
+ * @param f_coeff The coeffiences of the polynom
+ * @param f_value The input value.
+ */
+template <uint8_t NrBreak, uint8_t NOrd>
+float CConverterSpline<NrBreak, NOrd>::splineValue( CCoeffContainerType f_coeff,float f_value){
+ float l_res = f_coeff[NOrd];
+ for (uint8_t i = 0;i<NOrd;++i)
+ {
+ l_res+=std::pow(f_value,NOrd-i)*f_coeff[i];
+ }
+ return l_res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Controllers/pidcontroller.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,82 @@
+#ifndef PID_CONTROLLER_H
+#define PID_CONTROLLER_H
+
+#include <cstdio>
+#include <Linalg/linalg.h>
+#include <SystemModels/systemmodels.hpp>
+#include <mbed.h>
+
+namespace controllers
+{
+ namespace siso
+ {
+
+ /**
+ * @brief General interface class for the controller
+ *
+ * @tparam T type of the variables (float, double)
+ */
+ template<class T>
+ class IController{
+ public:
+ virtual T calculateControl(const T&)=0;
+ virtual void clear()=0;
+ };
+
+ /**
+ * @brief It generates a discrete transferfunction for realizing a proportional–integral–derivative controller, which is discretized by the Euler’s method.
+ *
+ * @tparam T type of the variables (float, double)
+ */
+ template<class T>
+ class CPidController:public IController<T>
+ {
+ public:
+ /* Discrete transfer function type */
+ using CPidSystemmodelType = systemmodels::lti::siso::CDiscreteTransferFucntion<T,3,3>;
+
+ /* Constructor */
+ CPidController(T f_kp
+ ,T f_ki
+ ,T f_kd
+ ,T f_tf
+ ,T f_dt);
+ CPidController(CPidSystemmodelType f_pid,T f_dt);
+
+ /* Overloaded operator */
+ T calculateControl(const T& f_input);
+ /* Serial callback */
+ static void staticSerialCallback(void* obj,char const * a, char * b);
+ /* Initialization */
+ void clear();
+ private:
+ #ifdef CONTROL_TEST_HPP
+ FRIEND_TEST(PidControlTest,Initialization);
+ FRIEND_TEST(PidControlTest,Setter);
+ #endif
+ /* Controller setting */
+ void setController(T f_kp
+ ,T f_ki
+ ,T f_kd
+ ,T f_tf);
+ /* Serial callback implementation */
+ void serialCallback(char const * a, char * b);
+
+
+
+ /* Discrete transfer function */
+ CPidSystemmodelType m_pidTf;
+
+
+ /* delta-time term */
+ T m_dt;
+
+ };
+ /* Include function definitions */
+ #include "PidController.inl"
+ }; // namespace siso
+}; // namespace controllers
+
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Controllers/pidcontroller.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,114 @@
+/** @brief Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_kp proportional factor
+ * @param f_ki integral factor
+ * @param f_kd derivative factor
+ * @param f_tf derivative time filter constant
+ * @param f_dt sample time
+ */
+template<class T>
+CPidController<T>::CPidController(T f_kp
+ ,T f_ki
+ ,T f_kd
+ ,T f_tf
+ ,T f_dt)
+ :m_pidTf()
+ ,m_dt(f_dt)
+{
+ linalg::CMatrix<T,1,3> l_numPid({ (f_kd+f_tf*f_kp)/f_tf , (f_tf*f_dt*f_ki+f_dt*f_kp-2*f_tf*f_kp-2*f_kd)/f_tf , (f_kd+f_tf*f_kp+f_dt*f_dt*f_ki-f_dt*f_tf*f_ki-f_dt*f_kp)/f_tf});
+ linalg::CMatrix<T,1,3> l_denPid({ 1.0,-(2*f_tf-f_dt)/f_tf,(f_tf-f_dt)/f_tf });
+
+ m_pidTf.setNum(l_numPid.transpose());
+ m_pidTf.setDen(l_denPid.transpose());
+}
+
+// template<class T>
+// CPidController<T>::CPidController( CPidSystemmodelType f_pid
+// ,T f_dt)
+// :m_pidTf(f_pid)
+// ,m_dt(f_dt){
+
+// }
+
+
+/** @brief Operator
+ *
+ * @param f_input input function
+ * \return control value
+ */
+template<class T>
+T CPidController<T>::calculateControl(const T& f_input)
+{
+ return m_pidTf(f_input);
+}
+
+/** @brief Serial callback method
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ * \return None
+ */
+template<class T>
+void CPidController<T>::staticSerialCallback(void* obj,char const * a, char * b)
+{
+ CPidController* self = static_cast<CPidController*>(obj);
+ self->serialCallback(a,b);
+}
+
+/** @brief Reset to zero all memory of the controller.
+ *
+ */
+template<class T>
+void CPidController<T>::clear()
+{
+ m_pidTf.clearMemmory();
+}
+
+/** @brief Set the parameter of the controller
+ *
+ *
+ * @param f_kp proportional factor
+ * @param f_ki integral factor
+ * @param f_kd derivative factor
+ * @param f_tf derivative time filter constant
+ */
+template<class T>
+void CPidController<T>::setController(
+ T f_kp,
+ T f_ki,
+ T f_kd,
+ T f_tf)
+{
+ linalg::CMatrix<T,1,3> l_numPid({ (f_kd+f_tf*f_kp)/f_tf , (f_tf*m_dt*f_ki+m_dt*f_kp-2*f_tf*f_kp-2*f_kd)/f_tf , (f_kd+f_tf*f_kp+m_dt*m_dt*f_ki-m_dt*f_tf*f_ki-m_dt*f_kp)/f_tf });
+ linalg::CMatrix<T,1,3> l_denPid({ 1,-(2*f_tf-m_dt)/f_tf,(f_tf-m_dt)/f_tf });
+
+ m_pidTf.setNum(l_numPid.transpose());
+ m_pidTf.setDen(l_denPid.transpose());
+}
+
+/** @brief Serial callback method setting controller to values received
+ *
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ */
+template<class T>
+void CPidController<T>::serialCallback(char const * a, char * b)
+{
+ float l_kp,l_ki,l_kd,l_tf;
+ uint32_t l_res = sscanf(a,"%f;%f;%f;%f;",&l_kp,&l_ki,&l_kd,&l_tf);
+ if (4 == l_res)
+ {
+ setController(l_kp,l_ki,l_kd,l_tf);
+ sprintf(b,"ack;;%2.5f;%2.5f;%2.5f;%2.5f;",l_kp,l_ki,l_kd,l_tf);
+ }
+ else
+ {
+ sprintf(b,"sintax error;;");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Drivers/servo.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,44 @@
+/**
+ ******************************************************************************
+ * @file SERVO.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the steering SERVO
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef SERVO_HPP
+#define SERVO_HPP
+
+#include <mbed.h>
+
+
+namespace drivers{
+ /**
+ * @brief It is used for implementing SERVO functionality.
+ *
+ */
+ class SERVO
+ {
+ public:
+ /* Constructor */
+ SERVO(PinName _pwm);
+ /* Destructor */
+ ~SERVO();
+ /* Set angle */
+ void SetAngle(float angle); //-25 to 25 degr
+ private:
+ /* convert angle to duty cycle */
+ float conversion(float angle); //angle to duty cycle
+ /* PWM value */
+ PwmOut pwm;
+ /* Current angle */
+ float current_angle;
+ };
+}; // namespace drivers
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Drivers/vnh.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,82 @@
+/**
+ ******************************************************************************
+ * @file VNH.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the VNH Bridge Driver
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef VNH_HPP
+#define VNH_HPP
+
+/* The mbed library */
+#include <mbed.h>
+/* Functions to compute common mathematical operations and transformations */
+#include <cmath>
+
+namespace drivers{
+ // ! Current getter interface
+ class ICurrentGetter{
+ public:
+ virtual float GetCurrent(void)=0;
+ };
+
+ /**
+ * @brief Command setter interface.
+ *
+ */
+ class ICommandSetter{
+ public:
+ virtual void Run(float pwm);
+ };
+
+ //! VNH class.
+ /*!
+ * It is used for implementing motor bridge control.
+ * */
+ class VNH:public ICurrentGetter, public ICommandSetter
+ {
+ public:
+ /* Constructor */
+ VNH(PinName, PinName, PinName, PinName);
+ /* Destructor */
+ ~VNH();
+ /* Start */
+ void Start(void);
+ /* Stop */
+ void Stop(void);
+ /* Run */
+ void Run(float speed);
+ /* Brake */
+ void Brake();
+ /* Inverse */
+ void Inverse(float f_speed);
+ /* Get current */
+ float GetCurrent(void);
+
+ private:
+ /* Go current */
+ void Go(float speed);
+ /* increment member */
+ float increment;
+ /* current speed member */
+ float current_speed;
+ /* PWM */
+ PwmOut pwm;
+ /* pin A */
+ DigitalOut ina;
+ /* pin B */
+ DigitalOut inb;
+ /* current value */
+ AnalogIn current;
+ };
+
+
+}; // namespace drivers
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Encoders/encoder.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,107 @@
+/**
+ ******************************************************************************
+ * @file Encoder.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the encoder
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef MAG_ENCODER_HPP
+#define MAG_ENCODER_HPP
+
+#include <mbed.h>
+#include<TaskManager/taskmanager.hpp>
+#include<Encoders/encoderinterface.hpp>
+
+//! CCounter class.
+/*!
+ * It is used for counting encoder steps.
+ */
+class CCounter
+{
+ public:
+ /* Constructor */
+ CCounter(PinName f_pin);
+ /* Reset method */
+ void reset();
+ /* Increment method */
+ void increment();
+ /* Get counts method */
+ int32_t getCount();
+ /* Increment */
+ static void staticIncrement(void* obj);
+ private:
+ /* Interrupt object */
+ InterruptIn m_interrupt;
+ /* Counts member */
+ volatile int32_t m_count;
+};
+
+//! CEncoder class.
+/*!
+ * It inherits class task::CTask.
+ * It is used for computing revolustions per second.
+ */
+class CEncoder: public task::CTask, public:: encoders::IEncoderGetter
+{
+ public:
+ /* Constructor */
+ CEncoder(uint32_t f_period
+ ,float f_period_sec
+ ,uint32_t f_cpr
+ ,PinName f_pinName);
+ /* Get rotations per second */
+ virtual float getSpeedRps();
+ virtual int16_t getCount();
+ virtual bool isAbs(){return true;}
+
+ protected:
+ /* Run method */
+ virtual void _run();
+
+ /* Counter values */
+ CCounter m_counter;
+ /* Period in seconds */
+ const float m_period_sec;
+ /* Value of counts per revolution */
+ const uint32_t m_cpr;//count per revolution (rise and fall edges)
+ /* Value of rotation per second */
+ float m_rps;
+};
+
+//! CMagEncoderTime class.
+/*!
+ * It is used for computing high/low periods.
+ */
+class CMagEncoderTime
+{
+ public:
+ /* Constructor */
+ CMagEncoderTime(PinName f_pin);
+ /* Callback for rising edge interrupt */
+ void riseCallback();
+ /* Callback for falling edge interrupt */
+ void fallCallback();
+ /* Callback for rising edge interrupt attached to pbject */
+ static void staticRise(void* obj);
+ /* Callback for falling edge interrupt attached to pbject */
+ static void staticFall(void* obj);
+ /* Get high time */
+ float getHighTime();
+ /* Get low time */
+ float getLowTime();
+ private:
+ /* General purpose timer */
+ Timer m_Timer,m_fallTimer;
+ /* Digital interrupt input */
+ InterruptIn m_interrupt;
+ /* High time */
+ volatile float m_highTime;
+ /* Low time */
+ volatile float m_lowTime;
+};
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Encoders/encoderfilter.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,49 @@
+/**
+ ******************************************************************************
+ * @file EncoderFilter.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the encoder filter
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef ENCODER_FILTER_HPP
+#define ENCODER_FILTER_HPP
+#include <Encoders/encoder.hpp>
+#include <Filter/filter.hpp>
+
+//! CEncoderFilter class.
+/*!
+ * It inherits class CEncoder.
+ * It is used for obtaining filtered encoder output.
+ */
+class CEncoderFilter:public CEncoder
+{
+ /* Filter object */
+ template <class T>
+ using CFilterFunction = filter::CFilterFunction<T>;
+ public:
+ /* Constructor */
+ CEncoderFilter (uint32_t f_period
+ ,float f_period_sec
+ ,uint32_t f_cpr
+ ,PinName f_pinName
+ ,CFilterFunction<float>& f_filter);
+
+ virtual float getSpeedRps();
+ virtual int16_t getCount() = 0;
+ protected:
+ /* Run method */
+ virtual void _run();
+
+ private:
+ /* Filter member */
+ CFilterFunction<float>& m_filter;
+ /* Value of filtered rotations per second */
+ float m_filteredRps;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Encoders/encoderinterface.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,43 @@
+/**
+ * @file encoderinterface.hpp
+ * @author RBRO/PJ-IU
+ * @brief
+ * @version 0.1
+ * @date 2018-10-24
+ *
+ * @copyright Copyright (c) 2018
+ *
+ */
+#ifndef ENDOCER_INTERFACE_HPP
+#define ENDOCER_INTERFACE_HPP
+
+#include <stdint.h>
+namespace encoders{
+ /**
+ * @brief Rotary encoder interface class
+ *
+ */
+ class IEncoderGetter{
+ public:
+ /**
+ * @brief Get the Count value
+ *
+ * @return int16_t
+ */
+ virtual int16_t getCount() = 0;
+ /**
+ * @brief Get the Speed Rps
+ *
+ * @return float
+ */
+ virtual float getSpeedRps() = 0;
+ /**
+ * @brief Get the encoder capability. If it's true, than the encoder can give the oriantation, else it returns the absolute value of the rotation without the oriantation.
+ *
+ * @return bool
+ */
+ virtual bool isAbs() = 0;
+ };
+}; // namepsace encoders;
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Encoders/quadratureencoder.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,63 @@
+/**
+ * @file quadratureencoder.hpp
+ * @author RBRO/PJ-IU
+ * @brief
+ * @version 0.1
+ * @date 2018-10-23
+ *
+ * @copyright Copyright (c) 2018
+ *
+ */
+
+#ifndef Quadrature_ENCODER_HPP
+#define Quadrature_ENCODER_HPP
+
+#include <mbed.h>
+
+namespace encoders{
+/**
+ * @brief It an interface for accessing the encoder position. It can be used to get and to reset the position of the encoder.
+ *
+ */
+class CQuadratureEncoder_TIMX{
+ public:
+ virtual int16_t getCount() = 0;
+ virtual void reset() = 0;
+};
+
+/**
+ * @brief It's a singleton class for receiving and decoding the Quadrature signal by using the timer TIM4. It can get the direction of the rotation.
+ *
+ */
+class CQuadratureEncoder_TIM4:public CQuadratureEncoder_TIMX{
+ /**
+ * @brief It uses to destroy the singleton class.
+ *
+ */
+ class CQuadratureEncoder_TIM4_Destroyer{
+ public:
+ CQuadratureEncoder_TIM4_Destroyer(){}
+ ~CQuadratureEncoder_TIM4_Destroyer();
+ void SetSingleton(CQuadratureEncoder_TIM4* s);
+ private:
+ CQuadratureEncoder_TIM4* m_singleton;
+ };
+
+ public:
+ static CQuadratureEncoder_TIM4 *Instance();
+ int16_t getCount();
+ void reset();
+ virtual ~CQuadratureEncoder_TIM4() {}
+ protected:
+ CQuadratureEncoder_TIM4() {}
+
+ private:
+ void initialize();
+ static CQuadratureEncoder_TIM4* m_instance;
+ static CQuadratureEncoder_TIM4_Destroyer m_destroyer;
+};
+
+};// namepsace drivers
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Encoders/quadratureencodertask.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,75 @@
+/**
+ * @file quadratureencodertask.hpp
+ * @author RBRO/PJ-IU
+ * @brief
+ * @version 0.1
+ * @date 2018-10-23
+ *
+ * @copyright Copyright (c) 2018
+ *
+ */
+#ifndef QUADRATURE_ENCODER_TASK_HPP
+#define QUADRATURE_ENCODER_TASK_HPP
+
+#include <Encoders/encoderinterface.hpp>
+#include <Encoders/QuadratureEncoder.hpp>
+#include <Filter/Filter.hpp>
+
+#include <rtos.h>
+
+namespace encoders{
+
+/**
+ * @brief Rotary encoder with filter interface class
+ *
+ */
+class CQuadratureEncoderNonFilteredGetterInterface{
+ public:
+ virtual int16_t getNonFilteredCount()=0;
+ virtual float getNonFilteredSpeedRps() = 0;
+};
+
+/**
+ * @brief It implements a periodic task, which get the value from the counter and reset it to zero.
+ *
+ */
+class CQuadratureEncoderTask:public IEncoderGetter{
+ public:
+ CQuadratureEncoderTask(float,encoders::CQuadratureEncoder_TIMX*,uint16_t);
+ static void static_callback(void* obj);
+
+ void startTimer();
+ protected:
+ virtual void _run();
+ virtual int16_t getCount();
+ virtual float getSpeedRps();
+ virtual bool isAbs(){return false;}
+ protected:
+ encoders::CQuadratureEncoder_TIMX *m_Quadratureencoder;
+ int16_t m_encoderCnt;
+ const float m_taskperiod_s;
+ const uint16_t m_resolution;
+ RtosTimer m_timer;
+};
+
+/**
+ * @brief It implements the same functionality than CQuadratureEncoderTask class, but in additional it can filter the values.
+ *
+ */
+class CQuadratureEncoderWithFilterTask: public CQuadratureEncoderTask, public CQuadratureEncoderNonFilteredGetterInterface{
+ public:
+ CQuadratureEncoderWithFilterTask(float,encoders::CQuadratureEncoder_TIMX *, uint16_t,filter::CFilterFunction<float>&);
+ virtual void _run();
+ virtual int16_t getCount();
+ virtual float getSpeedRps();
+ virtual int16_t getNonFilteredCount();
+ virtual float getNonFilteredSpeedRps();
+ protected:
+ double m_encoderCntFiltered;
+ filter::CFilterFunction<float>& m_filter;
+
+};
+
+}; // namespace encoders
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/Filter/ekf_am.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,48 @@
+/**
+ ******************************************************************************
+ * @file Ekf_am.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the Ackermann model example
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef EKF_AM_HPP
+#define EKF_AM_HPP
+
+#include <Filter/filter.hpp>
+#include <Examples/SystemModels/ackermannmodel.hpp>
+
+namespace examples
+{
+ namespace filter
+ {
+ /* Extended Kalman Filter */
+ template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+ using CEKF = ::filter::ltv::mimo::CEKF<T,NA,NB,NC>;
+ //! CEKF_AM class.
+ /*!
+ * It inherits class CEKF.
+ * Extended Kalman Filter aplied on the Ackermann Model.
+ */
+ class CEKF_AM:public CEKF<double,2,10,5>
+ {
+ private:
+ /* Ackermann model*/
+ using CAckermannModel = ::examples::systemmodels::ackermannmodel::CAckermannModel;
+ /* Ackermann model Jacobian Matrix */
+ using CJMAckermannModel = ::examples::systemmodels::ackermannmodel::CJMAckermannModel;
+ public:
+ /* Constructor */
+ CEKF_AM(CAckermannModel& f_ackermannModel
+ ,CJMAckermannModel f_jacobianMatrixCalc
+ ,const CJMTransitionType& f_Q
+ ,const CObservationNoiseType& f_R);
+ };
+ };
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/Sensors/sensorpublisher.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ * @file SensorPublisher.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the sensor publisher
+ * functionality. Because template classes are used, the code was
+ * placed in a corresponding .inl file and not in a .cpp one.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef SENSOR_PUBLISHER_HPP
+#define SENSOR_PUBLISHER_HPP
+
+/* The mbed library */
+#include <mbed.h>
+/* Container that encapsulates fixed size arrays */
+#include <array>
+/* String types, character traits and a set of converting functions */
+#include <string>
+#include<TaskManager/taskmanager.hpp>
+
+
+namespace examples{
+ namespace sensors
+ {
+ //! ProximityPublisher class.
+ /*!
+ * It inherits class task::CTask.
+ * It is used for publishing proximity sensor values.
+ */
+ template <class C_Sensor,uint Nr_Senrsor>
+ class ProximityPublisher:public task::CTask
+ {
+ public:
+ /* Sensor array */
+ using SensorArrayT = std::array<C_Sensor*,Nr_Senrsor>;
+ /* Constructor */
+ ProximityPublisher(uint32_t,SensorArrayT,Serial&);
+ /* Serial callback attached to object */
+ static void staticSerialCallback(void* obj,char const * a, char * b);
+ protected:
+ /* Run method */
+ void _run();
+ /* Serial callback */
+ void serialCallback(char const * a, char * b);
+ private:
+ /* Sensor array */
+ SensorArrayT m_sensors;
+ /* Reference to serial object */
+ Serial& m_serial;
+ /* Active flag */
+ bool m_isActivate;
+ };
+ }; // namespace sensors
+}; // namespace examples
+
+#include "sensorpublisher.inl"
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/Sensors/sensorpublisher.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,78 @@
+namespace examples{
+ namespace sensors{
+ /** \brief Constructor for the CEncoderFilter class
+ *
+ * Constructor method
+ *
+ * @param f_period period value
+ * @param f_sensors sensor array
+ * @param f_serial reference to the serial object
+ */
+ template <class C_Sensor,uint Nr_Senrsor>
+ ProximityPublisher<C_Sensor,Nr_Senrsor>::ProximityPublisher(uint32_t f_period
+ ,SensorArrayT f_sensors
+ ,Serial& f_serial)
+ :CTask(f_period)
+ ,m_sensors(f_sensors)
+ ,m_serial(f_serial)
+ ,m_isActivate(false)
+ {
+ }
+
+ /** \brief Serial callback method
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+ template <class C_Sensor,uint Nr_Senrsor>
+ void ProximityPublisher<C_Sensor,Nr_Senrsor>::staticSerialCallback(void* obj,char const * a, char * b)
+ {
+ ProximityPublisher* self = static_cast<ProximityPublisher*>(obj);
+ self->serialCallback(a,b);
+ }
+
+ /** \brief Serial callback actions
+ *
+ * Serial callback
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+ template <class C_Sensor,uint Nr_Senrsor>
+ void ProximityPublisher<C_Sensor,Nr_Senrsor>::serialCallback(char const * a, char * b){
+ int l_isActivate=0;
+ uint32_t l_res = sscanf(a,"%d",&l_isActivate);
+ if(l_res==1){
+ m_isActivate=(l_isActivate>=1);
+ sprintf(b,"ack;;");
+ }else{
+ sprintf(b,"sintax error;;");
+ }
+ }
+
+ /** \brief Method called each f_period
+ *
+ *
+ *
+ */
+ template <class C_Sensor,uint Nr_Senrsor>
+ void ProximityPublisher<C_Sensor,Nr_Senrsor>::_run(){
+ if(!m_isActivate) return;
+ char l_buf[100];
+ sprintf(l_buf,"@DSPB:");
+ for(uint8_t i=0;i<Nr_Senrsor;++i){
+
+ sprintf(l_buf,"%s%2.2f;",l_buf,m_sensors[i]->getValue());
+ }
+ sprintf(l_buf,"%s;\n\r",l_buf);
+ m_serial.printf("%s",l_buf);
+
+ }
+ }; // namespace sensors
+}; // namespace examples
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/Sensors/sensortask.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,85 @@
+/**
+ ******************************************************************************
+ * @file SensorTask.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the sensor task
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef SENSOR_TASK_HPP
+#define SENSOR_TASK_HPP
+
+/* Standard C library for basic mathematical operations */
+#include <math.h>
+#include<TaskManager/taskmanager.hpp>
+#include <Drivers/vnh.hpp>
+#include <SerialMonitor/serialmonitor.hpp>
+#include <Controllers/controller.hpp>
+#include <SystemModels/systemmodels.hpp>
+
+#include <Encoders/encoderinterface.hpp>
+
+namespace examples
+{
+
+ namespace sensors{
+
+
+ //! CDISTFTest class.
+ /*!
+ * It inherits class task::CTask.
+ * It is used for testing distance sensors operation.
+ */
+ class CDISTFTest:public task::CTask
+ {
+ public:
+ /* Constructor */
+ CDISTFTest(uint32_t f_period
+ ,Serial& f_serial);
+
+ private:
+ /* Run method */
+ void _run();
+
+ /* Reference to serial object */
+ Serial& m_serial;
+ /* Transfer function */
+ systemmodels::lti::siso::CDiscreteTransferFucntion<float,3,3> m_tf;
+ };
+
+ //! CEncoderSender class.
+ /*!
+ * It inherits class task::CTask.
+ * It is used for sending acquired data.
+ */
+ class CEncoderSender:public task::CTask
+ {
+ public:
+ /* Constructor */
+ CEncoderSender(uint32_t f_period
+ ,encoders::IEncoderGetter& f_encoder
+ ,Serial& f_serial);
+ /* Serial callback */
+ static void staticSerialCallback(void* obj,char const * a, char * b);
+ private:
+ /* Serial callback implementation */
+ void serialCallback(char const * a, char * b);
+ /* Run method */
+ void _run();
+
+ /* Active flag */
+ bool m_isActived;
+ /* Encoder value getter */
+ encoders::IEncoderGetter& m_encoder;
+ /* Serial communication member*/
+ Serial& m_serial;
+ };
+ }; // namespace sensors
+}; // namespace examples
+
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/SystemModels/ackermannmodel.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,182 @@
+
+/**
+ ******************************************************************************
+ * @file AckermannModel.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the Ackermann model.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef ACKERMANN_MODEL_HPP
+#define ACKERMANN_MODEL_HPP
+
+#include <math.h>
+#include <SystemModels/systemmodels.hpp>
+#include <Examples/SystemModels/ackermanntypes.hpp>
+
+/* Definition of PI value */
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846
+#endif
+
+/* Definition of degrees to radians transformation */
+#ifndef DEG2RAD
+ #define DEG2RAD M_PI/180.0
+#endif
+
+namespace examples
+{
+ namespace systemmodels
+ {
+ namespace ackermannmodel
+ {
+ /* System model type */
+ template<class T,uint32_t NA,uint32_t NB,uint32_t NC>
+ using CSystemModelType = ::systemmodels::nlti::mimo::CDiscreteTimeSystemModel<T,NA,NB,NC>;
+ /* Jacobian matrix*/
+ template<class T,uint32_t NA,uint32_t NB,uint32_t NC>
+ using CJacobianMatricesType = ::systemmodels::nlti::mimo::CJacobianMatrices<T,NA,NB,NC>;
+ //! CAckermannModel class.
+ /*!
+ * It inherits class CSystemModelType.
+ */
+ class CAckermannModel:public CSystemModelType<double,2,10,5>
+ {
+ public:
+ /* Constructor */
+ CAckermannModel(const double f_dt
+ ,const double f_gamma
+ ,const double f_wb
+ ,const double f_b
+ ,const double f_J
+ ,const double f_K
+ ,const double f_R
+ ,const double f_L);
+ /* Constructor */
+ CAckermannModel(const CStatesType& f_states
+ ,const double f_dt
+ ,const double f_gamma
+ ,const double f_wb
+ ,const double f_b
+ ,const double f_J
+ ,const double f_K
+ ,const double f_R
+ ,const double f_L);
+ /* Update method */
+ CStatesType update(const CInputType& f_input);
+
+ /* Calculate output method */
+ COutputType calculateOutput(const CInputType& f_input);
+ private:
+ /* gamma=Meter/Rotation */
+ const double m_gamma;
+ /* Wheel base distance in meter */
+ const double m_wb;
+ /* Motor Constants */
+ const double m_bJ,m_KJ,m_KL,m_RL,m_L;
+ };
+
+ //! CJMAckermannModel class.
+ /*!
+ * It inherits class CJacobianMatricesType.
+ */
+ class CJMAckermannModel:public CJacobianMatricesType<double,2,10,5>
+ {
+ public:
+ CJMAckermannModel (double f_dt
+ ,double f_gamma
+ ,double f_wb
+ ,double f_b
+ ,double f_J
+ ,double f_K
+ ,double f_R
+ ,double f_L)
+ :m_dt(f_dt)
+ ,m_gamma(f_gamma)
+ ,m_wb(f_wb)
+ ,m_bJ(f_b/f_J)
+ ,m_KJ(f_K/f_J)
+ ,m_KL(f_K/f_L)
+ ,m_RL(f_R/f_L)
+ {
+ m_ObservationMatrix=initObservationMatrix();
+ }
+
+
+
+ CJMObservationType getJMObservation( const CStatesType& f_states
+ ,const CInputType& f_input){
+ return m_ObservationMatrix;
+ }
+
+ private:
+ linalg::CMatrix<double,5,10> initObservationMatrix(){
+ linalg::CMatrix<double,5,10> l_data;
+ l_data[0][2]=l_data[1][3]=1.f/m_dt;
+ l_data[0][4]=l_data[1][5]=-1.f/m_dt;
+ l_data[2][7]=1.f;
+ l_data[3][8]=m_gamma;
+ l_data[4][9]=1.f;
+ return l_data;
+ }
+
+ inline void setJacobianStateMatrixWithOne(CJMTransitionType& f_matrix){
+ f_matrix[0][0]=f_matrix[1][1]=1;
+ f_matrix[4][2]=f_matrix[5][3]=1;
+ f_matrix[6][6]=1;
+ return;
+ }
+
+ public:
+ CJMTransitionType getJMTransition( const CStatesType& f_states
+ ,const CInputType& f_input){
+
+ CJMTransitionType l_data(CJMTransitionType::zeros());
+ setJacobianStateMatrixWithOne(l_data);
+ CState l_states(f_states);
+ CInput l_input(f_input);
+
+ //Setting values in the jacobian matrix
+ l_data[0][2]=m_dt;
+ l_data[1][3]=m_dt;
+
+ l_data[2][6]=-m_gamma*l_states.omega()*sin(l_states.teta_rad());
+ l_data[2][8]=m_gamma*cos(l_states.teta_rad());
+
+ l_data[3][6]=m_gamma*l_states.omega()*cos(l_states.teta_rad());
+ l_data[3][8]=m_gamma*sin(l_states.teta_rad());
+
+ double l_alpha_rad=l_input.alpha()*DEG2RAD;
+ l_data[7][8]=l_data[6][8]=m_dt*m_gamma*tan(l_alpha_rad)/m_wb;
+ //l_data[7][11]=l_data[6][11]=m_dt*m_gamma*f_state.omega/(m_wb*pow(cos(l_alpha_rad),2));
+
+ l_data[8][8]=(1-m_dt*m_bJ);
+ l_data[8][9]=m_dt*m_KJ;
+ l_data[9][8]=m_dt*m_KL;
+ l_data[9][9]=(1-m_dt*m_RL);
+ //l_data[9][10]=m_dt;
+ return l_data;
+ }
+
+ private:
+ /* Constant values */
+ /* Time step */
+ const double m_dt;
+ /* gamma=Meter/Rotation */
+ const double m_gamma;
+ /* Wheel base distance in meter */
+ const double m_wb;
+ /* Motor Constants */
+ const double m_bJ,m_KJ,m_KL,m_RL;
+ /* Please leave this matrix to be the last member in this class,
+ as it will be initialized */
+ linalg::CMatrix<double,5,10> m_ObservationMatrix;
+ };
+ };
+ };
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/SystemModels/ackermanntypes.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,109 @@
+/**
+ ******************************************************************************
+ * @file AckermannTypes.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration and implementation for the
+ Ackermann types.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef ACKERMANN_TYPES_HPP
+#define ACKERMANN_TYPES_HPP
+
+#include <Linalg/linalg.h>
+
+namespace examples
+{
+ namespace systemmodels
+ {
+ namespace ackermannmodel
+ {
+ class CState: public linalg::CMatrix<double,10,1>
+ {
+ public:
+ CState():linalg::CMatrix<double,10,1>(){}
+ CState(const linalg::CMatrix<double,10,1>& f_matrix):linalg::CMatrix<double,10,1>(f_matrix){}
+ double& x(){return m_data[0][0];}
+ const double& x() const {return m_data[0][0];}
+
+ double& y(){return m_data[1][0];}
+ const double& y() const {return m_data[1][0];}
+
+ double& x_dot(){return m_data[2][0];}
+ const double& x_dot() const {return m_data[2][0];}
+
+ double& y_dot(){return m_data[3][0];}
+ const double& y_dot() const{return m_data[3][0];}
+
+ double& x_dot_prev(){return m_data[4][0];}
+ const double& x_dot_prev() const{return m_data[4][0];}
+
+ double& y_dot_prev(){return m_data[5][0];}
+ const double& y_dot_prev() const{return m_data[5][0];}
+
+ double& teta_rad(){return m_data[6][0];}
+ const double& teta_rad() const{return m_data[6][0];}
+
+ double& teta_rad_dot(){return m_data[7][0];}
+ const double& teta_rad_dot() const{return m_data[7][0];}
+
+ double& omega(){ return m_data[8][0];}
+ const double& omega() const{return m_data[8][0];}
+
+ double& i(){return m_data[9][0];}
+ const double& i() const{return m_data[9][0];}
+
+ // CState& operator=(const linalg::CMatrix<double,10,1>& f_matrix){
+ // for (uint32_t l_row = 0; l_row < 10; ++l_row)
+ // {
+ // for (uint32_t l_col = 0; l_col < 1; ++l_col)
+ // {
+ // this->m_data[l_row][l_col] = f_matrix[l_row][l_col];
+ // }
+ // }
+ // return *this;
+ // }
+ };
+
+ class CInput:public linalg::CMatrix<double,2,1>
+ {
+ public:
+ CInput():linalg::CMatrix<double,2,1>(){}
+ CInput(const linalg::CMatrix<double,2,1>& f_matrix):linalg::CMatrix<double,2,1>(f_matrix){}
+ double& v(){return m_data[0][0];}
+ const double& v()const{return m_data[0][0];}
+ double& alpha(){return m_data[1][0];}
+ const double& alpha()const{return m_data[1][0];}
+ };
+
+ class COutput:public linalg::CMatrix<double,5,1>
+ {
+ public:
+ COutput():linalg::CMatrix<double,5,1>(){}
+ COutput(const linalg::CMatrix<double,5,1>& f_matrix):linalg::CMatrix<double,5,1>(f_matrix){}
+ double& x_ddot(){return m_data[0][0];}
+ const double& x_ddot() const{return m_data[0][0];}
+ double& y_ddot(){return m_data[1][0];}
+ const double& y_ddot()const {return m_data[1][0];}
+ double& teta_rad_dot(){return m_data[2][0];}
+ const double& teta_rad_dot()const{return m_data[2][0];}
+ double& speed(){return m_data[3][0];}
+ const double& speed()const {return m_data[3][0];}
+
+ // double& alpha(){
+ // return m_data[4][0];
+ // }
+ // const double& alpha()const{
+ // return m_data[4][0];
+ // }
+ double& i(){return m_data[4][0];}
+ const double& i()const{return m_data[4][0];}
+ };
+ };
+ };
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/blinker.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,40 @@
+/**
+ ******************************************************************************
+ * @file Blinker.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the blinker
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef BLINKER_HPP
+#define BLINKER_HPP
+
+/* The mbed library */
+#include <mbed.h>
+#include <TaskManager/taskmanager.hpp>
+
+
+namespace examples{
+
+ /**
+ * @brief It is used for toggling an LED.
+ *
+ */
+ class CBlinker : public task::CTask
+ {
+ public:
+ /* Construnctor */
+ CBlinker(uint32_t f_period, DigitalOut f_led);
+ private:
+ /* Run method */
+ virtual void _run();
+ /* Digital output line connected to a LED */
+ DigitalOut m_led;
+ };
+}; // namespace examples
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Examples/echoer.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,41 @@
+/**
+ ******************************************************************************
+ * @file Echoer.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the serial echoer
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef ECHOER_HPP
+#define ECHOER_HPP
+
+/* The mbed library */
+#include <mbed.h>
+#include <TaskManager/taskmanager.hpp>
+
+
+namespace examples{
+ /**
+ * @brief It is used for echoing messages over UART.
+ *
+ */
+ class CEchoer : public task::CTask
+ {
+ public:
+ /* Construnctor */
+ CEchoer(uint32_t f_period, Serial& f_serialPort);
+ private:
+ /* Run method */
+ virtual void _run();
+
+ /* Serial communication member*/
+ Serial& m_serialPort;
+ };
+
+}; // namespace examples
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Filter/filter.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,318 @@
+/**
+ ******************************************************************************
+ * @file Filter.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the filter
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef FILTER_HPP
+#define FILTER_HPP
+
+#include <Linalg/linalg.h>
+#include <SystemModels/systemmodels.hpp>
+
+namespace filter
+{
+ /**
+ * @brief The filter interface
+ *
+ * @tparam T The type of the input and output signal
+ */
+ template<class T>
+ class CFilterFunction
+ {
+ public:
+ virtual T operator()(T&)=0;
+ };
+
+ namespace lti
+ {
+ namespace siso
+ {
+ /**
+ * @brief Infinite impulse response (IIR) discrete-time filter.
+ *
+ */
+ template <class T, uint32_t NA, uint32_t NB>
+ class CIIRFilter:public CFilterFunction<T>
+ {
+ public:
+ /* Constructor */
+ CIIRFilter(const linalg::CRowVector<T,NA>& f_A,const linalg::CRowVector<T,NB>& f_B);
+ /* Operator */
+ T operator()(T& f_u);
+ private:
+ CIIRFilter(){}
+ linalg::CRowVector<T,NA> m_A;
+ linalg::CRowVector<T,NB> m_B;
+ linalg::CColVector<T,NA> m_Y;
+ linalg::CColVector<T,NB> m_U;
+ };
+
+ /**
+ * @brief Finite impulse response (FIR) discrete-time filter.
+ *
+ */
+ template <class T, uint32_t NB>
+ class CFIRFilter:public CFilterFunction<T>
+ {
+ public:
+ /* Constructor */
+ CFIRFilter(const linalg::CRowVector<T,NB>& f_B);
+ /* Operator */
+ T operator()(T& f_u);
+ private:
+ CFIRFilter() {}
+ linalg::CRowVector<T,NB> m_B;
+ linalg::CColVector<T,NB> m_U;
+ };
+
+ /**
+ * @brief Mean filter
+ *
+ * @tparam T
+ * @tparam NB
+ */
+ template <class T, uint32_t NB>
+ class CMeanFilter:public CFilterFunction<T>
+ {
+ public:
+ /* Constructor */
+ CMeanFilter();
+ /* Operator */
+ virtual T operator()(T& f_u);
+ private:
+ T m_B;
+ linalg::CColVector<T,NB> m_U;
+ };
+ };
+
+ namespace mimo
+ {
+ //! CSSModel class.
+ /*!
+ *
+ * */
+ template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+ class CSSModel
+ {
+ public:
+ using CStateType = linalg::CColVector<T,NA>;
+ using CStateTransitionType = linalg::CMatrix<T,NA,NA>;
+ using CInputType = linalg::CColVector<T,NB>;
+ using CMeasurementType = linalg::CColVector<T,NC>;
+ using CInputMatrixType = linalg::CMatrix<T,NA,NB>;
+ using CMeasurementMatrixType = linalg::CMatrix<T,NC,NA>;
+ using CDirectTransferMatrixType = linalg::CMatrix<T,NC,NB>;
+ /* Constructor */
+ CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix);
+ /* Constructor */
+ CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix,
+ const CDirectTransferMatrixType& f_directTransferMatrix);
+ /* Constructor */
+ CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix,
+ const CDirectTransferMatrixType& f_directTransferMatrix,
+ const CStateType& f_state);
+
+ /* Get state method */
+ const CStateType& state() const {return m_stateVector;}
+ CStateType& state() {return m_stateVector;}
+
+ /* Operator */
+ CMeasurementType operator()(const CInputType& f_inputVector);
+ /* Update state */
+ void updateState(const CInputType& f_inputVector);
+ /* Get output */
+ CMeasurementType getOutput(const CInputType& f_inputVector);
+
+ private:
+ CSSModel() {}
+ /* state vector */
+ CStateType m_stateVector;
+ /* state transition matrix */
+ CStateTransitionType m_stateTransitionMatrix;
+ /* input matrix */
+ CInputMatrixType m_inputMatrix;
+ /* measurement matrix */
+ CMeasurementMatrixType m_measurementMatrix;
+ /* direct transfer matrix */
+ CDirectTransferMatrixType m_directTransferMatrix;
+ };
+
+ //! CKalmanFilter class.
+ /*!
+ *
+ * */
+ template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+ class CKalmanFilter
+ {
+ public:
+ using CStateType = linalg::CVector<T, NA>;
+ using CInputVectorType = linalg::CVector<T, NB>;
+ using COutputVectorType = linalg::CVector<T, NC>;
+ using CInputType = linalg::CMatrix<T, NA, NB>;
+ using CControInputType = linalg::CMatrix<T, NA, NC>;
+ using CModelCovarianceType = linalg::CMatrix<T, NA, NA>;
+ using CMeasurementCovarianceType = linalg::CMatrix<T, NC, NC>;
+ using CStateTransType = linalg::CMatrix<T, NA, NA>;
+ using CMeasurementType = linalg::CMatrix<T, NC, NA>;
+ using CKalmanGainType = linalg::CMatrix<T, NA, NC>;
+
+ /* Constructor */
+ CKalmanFilter(
+ const CStateTransType& f_stateTransitionModel,
+ const CControInputType& f_controlInput,
+ const CMeasurementType& f_observationModel,
+ const CModelCovarianceType& f_covarianceProcessNoise,
+ const CMeasurementCovarianceType& f_observationNoiseCovariance);
+
+ /* Get state method */
+ const CStateType& state() const
+ {
+ return m_posterioriState;
+ }
+ /* Get state method */
+ CStateType& state()
+ {
+ return m_posterioriState;
+ }
+ /* Operator */
+ CMeasurementType operator()(const CInputVectorType& f_input);
+ /* Operator */
+ CMeasurementType operator()();
+ /* Predict */
+ void predict();
+ /* Predict */
+ void predict(const CInputVectorType& f_input);
+ /* Update */
+ const CMeasurementType& update(void);
+
+ private:
+ CKalmanFilter() {}
+
+ CStateType m_previousState; // previous state
+ CStateType m_prioriState; // priori state
+ CStateType m_posterioriState; // posteriori state
+ CControInputType m_controlInput; // control input modelþ
+ CModelCovarianceType m_previousCovariance; // previous covariance estimate // <-
+ CModelCovarianceType m_prioriCovariance; // priori covariance estimate // <-
+ CModelCovarianceType m_posterioriCovariance; // posteriori covariance estimate // <-
+ CStateTransType m_stateTransitionModel; // state transition model
+ CModelCovarianceType m_covarianceProcessNoise; // covariance of process noise // done
+ CMeasurementType m_measurementResidual; // innovation or measurement residual
+ CMeasurementType m_measurement; // observation (or measurement)
+ CMeasurementType m_observationModel; // observation model
+ CMeasurementCovarianceType m_residualCovariance; // innovation or residual covariance // <-
+ CMeasurementCovarianceType m_observationNoiseCovariance; // covariance of observation noise // <-
+ CKalmanGainType m_kalmanGain; // optimal kalman gain
+ };
+
+ };
+ };
+ namespace ltv
+ {
+ namespace mimo
+ {
+ // Extended Kalman Filter
+ // Template parameters:
+ // - T variable type
+ // - NA no. of inputs
+ // - NB no. of states
+ // - NC no. of outputs
+ // Input parameters
+ template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+ class CEKF
+ {
+ public:
+ using CSystemModelType = systemmodels::nlti::mimo::CDiscreteTimeSystemModel<T,NA,NB,NC>;
+ using CJacobianMatricesType = systemmodels::nlti::mimo::CJacobianMatrices<T,NA,NB,NC>;
+ using CStatesType = linalg::CMatrix<T,NB,1>;
+ using CInputType = linalg::CMatrix<T,NA,1>;
+ using COutputType = linalg::CMatrix<T,NC,1>;
+ using CJMTransitionType = linalg::CMatrix<T,NB,NB>;
+ using CJMObservationType = linalg::CMatrix<T,NC,NB>;
+ using CObservationNoiseType = linalg::CMatrix<T,NC,NC>;
+ using CKalmanGainType = linalg::CMatrix<T,NC,NB>;
+
+ /* Constructor */
+ CEKF(CSystemModelType& f_systemModel
+ ,CJacobianMatricesType& f_jbMatrices
+ ,const CJMTransitionType& f_Q
+ ,const CObservationNoiseType& f_R);
+ /* Predict */
+ void predict (const CInputType& f_input);
+ /* Update */
+ void update (const CInputType& f_input
+ ,const COutputType& f_measurement);
+ protected:
+ private:
+ CSystemModelType& m_systemModel;
+ CJacobianMatricesType& m_jbMatrices;
+ //Predicted covariance matrix
+ CJMTransitionType m_covarianceMatrix;
+ //The covariance of the process noise
+ CJMTransitionType m_Q;
+ //The covariance of the observation noise
+ CObservationNoiseType m_R;
+
+ };
+ };
+ };
+
+ namespace nonlinear
+ {
+ namespace siso
+ {
+
+ /**
+ * @brief Median filter
+ *
+ */
+ template <class T, uint32_t N>
+ class CMedianFilter:public CFilterFunction<T>
+ {
+ public:
+ /* Constructor */
+ CMedianFilter();
+ inline T addNewValue(T& f_val);
+ inline T getMedian();
+ inline T operator()(T& f_v);
+
+ private:
+ struct my_structure
+ {
+ T info;
+ my_structure *next;
+ my_structure *prev;
+
+ };
+
+ my_structure *m_median; //pointer to the loist element that represents the median
+ my_structure *m_smallest; //pionter to the smallest element of the list (the first)
+ uint32_t m_new; //index to tyhe newest element in the list
+ uint32_t m_size; //the size of the list/queue
+
+ my_structure m_queue[N];
+ };
+ }
+ }
+};
+
+#include "filter.inl"
+
+#endif // FILTER_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Filter/filter.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,558 @@
+/**
+ ******************************************************************************
+ * @file Filter.inl
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementations for the filter
+ * functionality.
+ ******************************************************************************
+ */
+
+template <class T, uint32_t NC>
+using CMeasurementType = linalg::CColVector<T,NC>;
+
+/******************************************************************************/
+/** @brief CIIRFilter Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_A the feedback filter coefficients
+ * @param f_B the feedforward filter coefficients
+ */
+template <class T, uint32_t NA, uint32_t NB>
+filter::lti::siso::CIIRFilter<T,NA,NB>::CIIRFilter(const linalg::CRowVector<T,NA>& f_A,const linalg::CRowVector<T,NB>& f_B)
+ : m_A(f_A)
+ , m_B(f_B)
+ , m_Y()
+ , m_U()
+{
+}
+
+/** @brief Operator
+ *
+ * @param f_u reference to input data
+ * @return the filtered output data
+ */
+template <class T, uint32_t NA, uint32_t NB>
+T filter::lti::siso::CIIRFilter<T,NA,NB>::operator()(T& f_u)
+{
+ for (uint32_t l_idx = NB-1; l_idx > 0; --l_idx)
+ {
+ m_U[l_idx] = m_U[l_idx-1];
+ }
+ m_U[0][0] = f_u;
+
+ linalg::CMatrix<T,1,1> l_y = m_B*m_U - m_A*m_Y;
+ // T l_y = m_B*m_U - m_A*m_Y;
+
+ for (uint32_t l_idx = NA-1; l_idx > 0 ; --l_idx)
+ {
+ m_Y[l_idx] = m_Y[l_idx-1];
+ }
+ m_Y[0][0] = l_y[0][0];
+
+ return m_Y[0][0];
+}
+
+/******************************************************************************/
+/** @brief CFIRFilter Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_B the feedforward filter coefficients
+ */
+template <class T, uint32_t NB>
+filter::lti::siso::CFIRFilter<T,NB>::CFIRFilter(const linalg::CRowVector<T,NB>& f_B)
+ : m_B(f_B), m_U()
+{
+}
+
+/** @brief Operator
+ *
+ * @param f_u reference to the input data
+ * @return the filtered output data
+ */
+template <class T, uint32_t NB>
+T filter::lti::siso::CFIRFilter<T,NB>::operator()(T& f_u)
+{
+ for (uint32_t l_idx = NB-1; l_idx > 0; --l_idx)
+ {
+ m_U[l_idx] = m_U[l_idx-1];
+ }
+ m_U[0] = f_u;
+
+ linalg::CMatrix<T,1,1> l_y = m_B*m_U;
+
+ return l_y[0][0];
+}
+
+/******************************************************************************/
+/** @brief MeanFilter Class constructor
+ *
+ * Constructor method
+ *
+ *
+ */
+template <class T, uint32_t NB>
+filter::lti::siso::CMeanFilter<T,NB>::CMeanFilter()
+ : m_B(1./NB)
+ , m_U()
+{
+}
+
+/** @brief Operator
+ *
+ * @param f_u reference to the input data
+ * @return the filtered output data
+ */
+template <class T, uint32_t NB>
+T filter::lti::siso::CMeanFilter<T,NB>::operator()(T& f_u)
+{
+ T l_y =0;
+
+ for (uint32_t l_idx = 1; l_idx < NB; ++l_idx)
+ {
+ m_U[l_idx][0] = m_U[l_idx-1][0];
+ l_y += m_U[l_idx][0];
+ }
+ m_U[0][0] = f_u;
+ l_y += m_U[0][0];
+
+ return m_B*l_y;
+}
+
+/******************************************************************************/
+/** @brief CSSModel Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_stateTransitionMatrix
+ * @param f_inputMatrix
+ * @param f_measurementMatrix
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+filter::lti::mimo::CSSModel<T,NA,NB,NC>::CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix)
+ : m_stateVector()
+ , m_stateTransitionMatrix(f_stateTransitionMatrix)
+ , m_inputMatrix(f_inputMatrix)
+ , m_measurementMatrix(f_measurementMatrix)
+ , m_directTransferMatrix()
+{
+ // do nothing
+}
+
+/** @brief CSSModel Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_stateTransitionMatrix
+ * @param f_inputMatrix
+ * @param f_measurementMatrix
+ * @param f_directTransferMatrix
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+filter::lti::mimo::CSSModel<T,NA,NB,NC>::CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix,
+ const CDirectTransferMatrixType& f_directTransferMatrix)
+ : m_stateVector()
+ , m_stateTransitionMatrix(f_stateTransitionMatrix)
+ , m_inputMatrix(f_inputMatrix)
+ , m_measurementMatrix(f_measurementMatrix)
+ , m_directTransferMatrix(f_directTransferMatrix)
+{
+ // do nothing
+}
+
+/** @brief CSSModel Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_stateTransitionMatrix
+ * @param f_inputMatrix
+ * @param f_measurementMatrix
+ * @param f_directTransferMatrix
+ * @param f_state
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+filter::lti::mimo::CSSModel<T,NA,NB,NC>::CSSModel(
+ const CStateTransitionType& f_stateTransitionMatrix,
+ const CInputMatrixType& f_inputMatrix,
+ const CMeasurementMatrixType& f_measurementMatrix,
+ const CDirectTransferMatrixType& f_directTransferMatrix,
+ const CStateType& f_state)
+ : m_stateVector(f_state)
+ , m_stateTransitionMatrix(f_stateTransitionMatrix)
+ , m_inputMatrix(f_inputMatrix)
+ , m_measurementMatrix(f_measurementMatrix)
+ , m_directTransferMatrix(f_directTransferMatrix)
+{
+ // do nothing
+}
+
+/** @brief Operator
+ *
+ * @param f_inputVector reference to input vector
+ * @return the output data from the system model (output vector)
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+CMeasurementType<T,NC> filter::lti::mimo::CSSModel<T,NA,NB,NC>::operator()(const CInputType& f_inputVector)
+{
+ updateState(f_inputVector);
+
+ return getOutput(f_inputVector);
+}
+
+/** @brief Update state method
+ *
+ * @param f_inputVector reference to input vector
+ * @return None
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+void filter::lti::mimo::CSSModel<T,NA,NB,NC>::updateState(const CInputType& f_inputVector)
+{
+ m_stateVector = m_stateTransitionMatrix * m_stateVector + m_inputMatrix * f_inputVector;
+}
+
+/** @brief Get output
+ *
+ * @param f_inputVector reference to input vector
+ * @return the output data from the system model (output vector)
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+CMeasurementType<T,NC> filter::lti::mimo::CSSModel<T,NA,NB,NC>::getOutput(const CInputType& f_inputVector)
+{
+ return m_measurementMatrix * m_stateVector + m_directTransferMatrix * f_inputVector;
+}
+
+/******************************************************************************/
+/** @brief CKalmanFilter Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_stateTransitionModel
+ * @param f_controlInput
+ * @param f_observationModel
+ * @param f_covarianceProcessNoise
+ * @param f_observationNoiseCovariance
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::CKalmanFilter(
+ const CStateTransType& f_stateTransitionModel,
+ const CControInputType& f_controlInput,
+ const CMeasurementType& f_observationModel,
+ const CModelCovarianceType& f_covarianceProcessNoise,
+ const CMeasurementCovarianceType& f_observationNoiseCovariance)
+ : m_stateTransitionModel(f_stateTransitionModel)
+ , m_controlInput(f_controlInput)
+ , m_observationModel(f_observationModel)
+ , m_covarianceProcessNoise(f_covarianceProcessNoise)
+ , m_observationNoiseCovariance(f_observationNoiseCovariance)
+{
+}
+
+/** @brief Operator
+ *
+ * @param f_input reference to input vector
+ * @return Updated (a posteriori) state estimate
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+linalg::CMatrix<T, NC, NA> filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::operator()(const CInputVectorType& f_input)
+{
+ predict(f_input);
+ return update();
+}
+
+/** @brief Operator
+ *
+ *
+ * @return Updated (a posteriori) state estimate
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+linalg::CMatrix<T, NC, NA> filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::operator()()
+{
+ predict();
+ return update();
+}
+
+/** @brief Predict
+ *
+ *
+ *
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+void filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::predict()
+{
+ m_previousState = m_prioriState;
+ m_previousCovariance = m_prioriCovariance;
+ m_prioriState = m_stateTransitionModel * m_previousState;
+ m_prioriCovariance = m_stateTransitionModel * m_previousCovariance * transpose(m_stateTransitionModel) + m_covarianceProcessNoise;
+}
+
+/** @brief Predict
+ *
+ * @param f_input vector input
+ *
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+void filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::predict(const CInputVectorType& f_input)
+{
+ m_previousState = m_prioriState;
+ m_previousCovariance = m_prioriCovariance;
+ m_prioriState = m_stateTransitionModel * m_previousState + m_controlInput * f_input;
+ m_prioriCovariance = m_stateTransitionModel * m_previousCovariance * transpose(m_stateTransitionModel) + m_covarianceProcessNoise;
+}
+
+/** @brief Update
+ *
+ *
+ * @return Measurement residual
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+const linalg::CMatrix<T, NC, NA>& filter::lti::mimo::CKalmanFilter<T,NA,NB,NC>::update(void)
+{
+ m_measurementResidual = m_measurement - m_observationModel * m_prioriState;
+ m_measurement = m_observationModel * m_posterioriState;
+ m_residualCovariance = m_observationModel * m_prioriCovariance * transpose(m_observationModel) + m_observationNoiseCovariance;
+ m_kalmanGain = m_prioriCovariance * transpose(m_observationModel) * m_residualCovariance.inv();
+ m_posterioriState = m_prioriState + m_kalmanGain * m_measurementResidual;
+ m_posterioriCovariance = ( CStateTransType::eye() - m_kalmanGain * m_observationModel ) * m_prioriCovariance;
+ return m_posterioriState;
+}
+
+/******************************************************************************/
+/** @brief CEKF Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_systemModel
+ * @param f_jbMatrices
+ * @param f_Q
+ * @param f_R
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+filter::ltv::mimo::CEKF<T,NA,NB,NC>::CEKF(
+ CSystemModelType& f_systemModel
+ ,CJacobianMatricesType& f_jbMatrices
+ ,const CJMTransitionType& f_Q
+ ,const CObservationNoiseType& f_R)
+ :m_systemModel(f_systemModel)
+ ,m_jbMatrices(f_jbMatrices)
+ ,m_covarianceMatrix(linalg::CMatrix<T,NB,NB>::ones())
+ ,m_Q(f_Q)
+ ,m_R(f_R)
+{
+}
+
+/** @brief Predict
+ *
+ * @param f_input vector input
+ *
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+void filter::ltv::mimo::CEKF<T,NA,NB,NC>::predict(const CInputType& f_input)
+{
+ //Previous updated state
+ CStatesType l_prev_states=m_systemModel.getStates();
+ CJMTransitionType l_JF=m_jbMatrices.getJMTransition(l_prev_states,f_input);
+ //Predicted state estimate X_{k|k-1}
+ CStatesType l_pred_states=m_systemModel.update(f_input);
+ //Predicted covariance estimate
+ m_covarianceMatrix=l_JF*m_covarianceMatrix*l_JF.transpose()+m_Q;
+}
+
+/** @brief Update
+ *
+ * @param f_input vector input
+ * @param f_measurement vector input
+ *
+ */
+template <class T, uint32_t NA, uint32_t NB, uint32_t NC>
+void filter::ltv::mimo::CEKF<T,NA,NB,NC>::update(const CInputType& f_input
+ ,const COutputType& f_measurement)
+{
+ // Estimated system output
+ COutputType l_y_est=m_systemModel.calculateOutput(f_input);
+ // Innovation or measurement residual
+ COutputType l_mes_res=f_measurement-l_y_est;
+ // Innovation (or residual) covariance
+ CStatesType l_states=m_systemModel.getStates();
+ CJMObservationType l_JH=m_jbMatrices.getJMObservation(f_input,l_states);
+ CObservationNoiseType l_s=l_JH*m_covarianceMatrix*l_JH.transpose()+m_R;
+ //Near-optimal Kalman gain
+ CKalmanGainType l_K=m_covarianceMatrix*l_JH.transpose()*l_s.inv();
+ //Updated state estimate
+ CStatesType l_updated_states=l_states+l_K*l_mes_res;
+ m_systemModel.setStates(l_updated_states);
+ //Updated covariance estimate
+ m_covarianceMatrix=(CJMTransitionType::eye()-l_K*l_JH)*m_covarianceMatrix;
+}
+
+/******************************************************************************/
+/** @brief CMedianFilter Class constructor
+ *
+ * Constructor method
+ *
+ *
+ */
+template <class T, uint32_t N>
+filter::nonlinear::siso::CMedianFilter<T,N>::CMedianFilter()
+ :m_median()
+ ,m_smallest()
+ ,m_new(0)
+ ,m_size(N)
+ ,m_queue()
+{
+ // for (unsigned int l_idx = 0; l_idx < N; l_idx++)
+ // {
+ // m_queue[l_idx] = new structura;
+
+ // }
+
+ for (unsigned int l_idx = 0; l_idx < N ; l_idx++)
+ {
+ m_queue[l_idx].info = 0;
+ m_queue[l_idx].next = &(m_queue[(l_idx + 1) % N]);
+ m_queue[l_idx].prev = &(m_queue[(N + l_idx - 1) % N]);
+ }
+
+ m_new = N - 1;
+ m_size = N;
+ m_median = &(m_queue[m_size / 2]);
+ m_smallest =&(m_queue[0]);
+}
+
+/** @brief Operator
+ *
+ * @param f_val the input data
+ * @return filted the data
+ */
+template <class T, uint32_t N>
+T filter::nonlinear::siso::CMedianFilter<T,N>::operator()(T& f_val)
+{
+ m_new = (m_new + 1) % m_size; //shift new index //inca e valoarea veche
+ /* // varianta pentru a decide valoarea mediana eficient-----eficient daca filtrul are dimensiuni mari
+ // ->V2 start remy_structurere EXISTA CAUZE CARE NU SUNT TRATATE CORECT SAU NETRATATE COMPLET!!!!!!!!!!!
+ if ((m_queue[m_new]->info > m_median->info) && (f_val <= m_median->info))
+ {
+ if (f_val > m_median->prev->info)
+ {
+ m_median = m_queue[m_new]; //med=new
+ }
+ else
+ {
+ m_median = m_median->prev; // <-
+ }
+ }
+ else if ((m_queue[m_new]->info < m_median->info) && (f_val > m_median->info))
+ {
+ if (f_val > m_median->next->info)
+ {
+ m_median = m_median->next; // ->
+ }
+ else
+ {
+ m_median = m_queue[m_new]; //med=new
+ }
+ }
+ else if ((m_queue[m_new]->info == m_median->info))
+ {
+ if ((f_val < m_median->info)&&(f_val <= m_median->prev->info))
+ {
+ m_median = m_median->prev; // <-
+ }
+ else if (f_val > m_median->info)
+ {
+ if (f_val <= m_median->next->info)
+ {
+ m_median = m_queue[m_new]; //med=new
+ }
+ else
+ {
+ m_median = m_median->next; // ->
+ }
+ }
+ else
+ {
+ m_median = m_queue[m_new]; //med=new
+ }
+ }
+ */
+ m_queue[m_new ].info = f_val; //suprascrie cea mai veche valoare
+
+ //ordonare dupa valoare
+
+ //elementul new se "scoate" din lista
+ m_queue[m_new].prev->next = m_queue[m_new].next; //5.
+ m_queue[m_new].next->prev = m_queue[m_new].prev; //6.
+
+ //update smallest value
+ my_structure* l_i = m_smallest;
+ if (&(m_queue[m_new]) == m_smallest)
+ {
+ if (m_queue[m_new].info > m_smallest->next->info)
+ {
+ m_smallest = m_smallest->next;
+ l_i = m_smallest;
+ }
+ }
+ else if (m_queue[m_new].info <= m_smallest->info)
+ {
+ l_i = m_smallest;
+ m_smallest = &m_queue[m_new];
+ }
+
+ //cautarea locului unde trebuie sa se amplaseze noul element in lista
+ unsigned int l_cnt = 1;
+ if (&(m_queue[m_new]) == l_i)
+ {
+ l_i = l_i->next;
+ }
+
+ while ((l_i->info < m_queue[m_new].info) && (l_cnt <= m_size - 1))
+ {
+ l_i = l_i->next;
+ l_cnt++;
+ }
+
+ //inserarea elemntului new la locul potrivit
+ l_i->prev->next = &m_queue[m_new]; //1.
+ m_queue[m_new].next = l_i; //2.
+ m_queue[m_new].prev = l_i->prev; //3.
+ l_i->prev = &m_queue[m_new]; //4.
+
+ //varianta ineficienta pentru aflarea medianului cand filtrul are dimensiuni mari
+ m_median=m_smallest;
+ for(uint8_t iddx=0; iddx < m_size/2; ++iddx)
+ {
+ m_median=m_median->next;
+ }
+
+ return getMedian();
+}
+
+/* */
+/** @brief OperGet medianator
+ *
+ *
+ * @return median value
+ */
+template <class T, uint32_t N>
+T filter::nonlinear::siso::CMedianFilter<T, N>::getMedian()
+{
+ T ret_val;
+ if (1 == m_size % 2) // daca filtrul are lungime impara
+ {
+ ret_val = m_median->info;
+ }
+ else // daca filtrul are lungime para
+ {
+ ret_val = 0.5*(m_median->info + m_median->prev->info);
+ }
+ return ret_val;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Linalg/linalg.h Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,473 @@
+#ifndef LINALG_H
+#define LINALG_H
+
+// #include <mbed.h>
+#include <stdint.h>
+#include <array>
+
+namespace linalg
+{
+ template <class T, uint32_t M, uint32_t N>
+ class CMatrix
+ {
+ public:
+ using CThisType = CMatrix<T,M,N>;
+ using CTransposeType = CMatrix<T,N,M>;
+ using CContainerType = std::array<std::array<T,N>,M>;
+ using CDataType =T;
+
+ template <uint32_t P>
+ using CLeftMultipliableType = CMatrix<T,P,M>;
+
+ template <uint32_t P>
+ using CRightMultipliableType = CMatrix<T,N,P>;
+
+ template <uint32_t P>
+ using CLeftMultiplicationResultType = CMatrix<T,P,N>;
+
+ template <uint32_t P>
+ using CRightMultiplicationResultType = CMatrix<T,M,P>;
+
+ friend class CMatrix<T,N,M>;
+
+ CMatrix() : m_data() {}
+ CMatrix(const CThisType& f_matrix) : m_data(f_matrix.m_data) {}
+ CMatrix(const CThisType&& f_matrix) : m_data(f_matrix.m_data) {}
+ CMatrix(const CContainerType& f_data) : m_data(f_data) {}
+ CMatrix(const CContainerType&& f_data) : m_data(f_data) {}
+
+ CThisType& operator=(const CThisType& f_matrix)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] = f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return *this;
+ }
+ CThisType& operator=(const CThisType&& f_matrix)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] = f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return *this;
+ }
+
+ std::array<T,N>& operator[](uint32_t f_row)
+ {
+ return m_data[f_row];
+ }
+
+ CDataType& operator()(uint32_t f_row, uint32_t f_col)
+ {
+ return m_data[f_row][f_col];
+ }
+
+ const std::array<T,N>& operator[](uint32_t f_row) const
+ {
+ return m_data[f_row];
+ }
+
+ const CDataType& operator()(uint32_t f_row, uint32_t f_col) const
+ {
+ return m_data[f_row][f_col];
+ }
+
+ // template<>
+ // CMatrix<T,1,1>::operator CDataType()
+ // {
+ // return m_data[0][0];
+ // }
+
+ CThisType& operator+() {return *this;}
+ CThisType operator-()
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = -this->m_data[l_row][l_col];
+ }
+ }
+ return l_matrix;
+ }
+ CThisType operator+(const CThisType& f_matrix)
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] + f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return l_matrix;
+ }
+ CThisType operator-(const CThisType& f_matrix)
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] - f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return l_matrix;
+ }
+ CThisType& operator+=(const CThisType& f_matrix)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] += f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return *this;
+ }
+ CThisType& operator-=(const CThisType& f_matrix)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] -= f_matrix.m_data[l_row][l_col];
+ }
+ }
+ return *this;
+ }
+
+ CThisType operator+(const CDataType& f_val)
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] + f_val;
+ }
+ }
+ return l_matrix;
+ }
+ CThisType operator-(const CDataType& f_val)
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] - f_val;
+ }
+ }
+ return l_matrix;
+ }
+ CThisType& operator+=(const CDataType& f_val)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] += f_val;
+ }
+ }
+ return *this;
+ }
+ CThisType& operator-=(const CDataType& f_val)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] -= f_val;
+ }
+ }
+ return *this;
+ }
+ CThisType& operator*=(const CDataType& f_val)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] *= f_val;
+ }
+ }
+ return *this;
+ }
+ CThisType& operator*=(const CThisType& f_val)
+ {
+ CThisType& l_thisRef(*this);
+ l_thisRef = l_thisRef * f_val;
+ return l_thisRef;
+ }
+ CThisType& operator/=(const CDataType& f_val)
+ {
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ this->m_data[l_row][l_col] /= f_val;
+ }
+ }
+ return *this;
+ }
+ CThisType operator*(const CDataType& f_val)
+ {
+ CThisType l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_matrix.m_data[l_row][l_col] = this->m_data[l_row][l_col] * f_val;
+ }
+ }
+ return l_matrix;
+ }
+ template <uint32_t P>
+ CRightMultiplicationResultType<P> operator*(const CRightMultipliableType<P>& f_matrix)
+ {
+ CRightMultiplicationResultType<P> l_matrix;
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < P; ++l_col)
+ {
+ l_matrix[l_row][l_col] = 0;
+ for (uint32_t l_idx = 0; l_idx < N; ++l_idx)
+ {
+ l_matrix[l_row][l_col] += this->m_data[l_row][l_idx] * f_matrix[l_idx][l_col];
+ }
+ }
+ }
+ return l_matrix;
+ }
+ CThisType inv();
+
+ CTransposeType transpose()
+ {
+ CTransposeType l_trsp;
+
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_trsp.m_data[l_col][l_row] = this->m_data[l_row][l_col];
+ }
+ }
+
+ return l_trsp;
+ }
+
+ template <uint32_t P>
+ CRightMultiplicationResultType<P> solve(const CRightMultipliableType<P>& f_B)
+ {
+ return CLUDecomposition(*this).solve();
+ }
+
+ static CThisType zeros()
+ {
+ CThisType l_res;
+
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_res[l_row][l_col] = 0;
+ }
+ }
+
+ return l_res;
+ }
+
+ static CThisType ones()
+ {
+ CThisType l_res;
+
+ for (uint32_t l_row = 0; l_row < M; ++l_row)
+ {
+ for (uint32_t l_col = 0; l_col < N; ++l_col)
+ {
+ l_res[l_row][l_col] = 1;
+ }
+ }
+
+ return l_res;
+ }
+
+ static CThisType eye()
+ {
+ CThisType l_res(CThisType::zeros());
+ uint32_t l_minDim = std::min(M,N);
+
+ for (uint32_t l_row = 0; l_row < l_minDim; ++l_row)
+ {
+ l_res[l_row][l_row] = 1;
+ }
+
+ return l_res;
+ }
+
+ protected:
+ std::array<std::array<T,N>,M> m_data;
+ };
+
+ template<class T, uint32_t N>
+ class CLUDecomposition
+ {
+ public:
+ using CThisType = CLUDecomposition<T,N>;
+ using COriginalType = CMatrix<T,N,N>;
+ using CDataType =T;
+
+ template <uint32_t P>
+ using CLeftMultipliableType = CMatrix<T,P,N>;
+
+ template <uint32_t P>
+ using CRightMultipliableType = CMatrix<T,N,P>;
+
+ template <uint32_t P>
+ using CLeftMultiplicationResultType = CMatrix<T,P,N>;
+
+ template <uint32_t P>
+ using CRightMultiplicationResultType = CMatrix<T,N,P>;
+
+ CLUDecomposition(const CThisType& f_decomposition) : m_L(f_decomposition.m_L), m_U(f_decomposition.m_U), m_P(f_decomposition.m_P) {}
+ CLUDecomposition(const CThisType&& f_decomposition) : m_L(f_decomposition.m_L), m_U(f_decomposition.m_U), m_P(f_decomposition.m_P) {}
+ CLUDecomposition(const COriginalType& f_matrix) : m_L(), m_U(), m_P() {decompose(f_matrix);}
+ CLUDecomposition(const COriginalType&& f_matrix) : m_L(), m_U(), m_P() {decompose(f_matrix);}
+
+ operator COriginalType()
+ {
+ return m_L * m_U;
+ }
+
+ COriginalType inv()
+ {
+ return triUInv() * triLInv();
+ }
+
+ COriginalType triLInv()
+ {
+ COriginalType l_invL(m_L);
+
+ for (uint32_t l_jdx = 0; l_jdx < N; ++l_jdx)
+ {
+ l_invL[l_jdx][l_jdx] = 1/l_invL[l_jdx][l_jdx];
+
+ for (uint32_t l_idx = l_jdx+1; l_idx < N; ++l_idx)
+ {
+ l_invL[l_idx][l_jdx] = 0;
+
+ for (uint32_t l_kdx = l_jdx; l_kdx < l_idx; ++l_kdx)
+ {
+ l_invL[l_idx][l_jdx] -= m_L[l_idx][l_kdx]*l_invL[l_kdx][l_jdx];
+ }
+
+ l_invL[l_idx][l_jdx] /= l_invL[l_idx][l_idx];
+ }
+ }
+
+ return l_invL;
+ }
+
+ COriginalType triUInv()
+ {
+ COriginalType l_invU(m_U);
+
+ for (int32_t l_jdx = (N-1); l_jdx >= 0; --l_jdx)
+ {
+ l_invU[l_jdx][l_jdx] = 1/l_invU[l_jdx][l_jdx];
+
+ for (int32_t l_idx = (l_jdx-1); l_idx >= 0; --l_idx)
+ {
+ l_invU[l_idx][l_jdx] = 0;
+
+ for (int32_t l_kdx = (l_idx+1); l_kdx < (l_jdx+1); ++l_kdx)
+ {
+ l_invU[l_idx][l_jdx] -= m_U[l_idx][l_kdx]*l_invU[l_kdx][l_jdx];
+ }
+
+ l_invU[l_idx][l_jdx] /= l_invU[l_idx][l_idx];
+ }
+ }
+
+ return l_invU;
+ }
+
+ template <uint32_t P>
+ CRightMultiplicationResultType<P> solve(const CRightMultipliableType<P>& f_B)
+ {
+ CRightMultipliableType<P> l_B;
+
+ for (uint32_t l_idx = 0; l_idx < N; ++l_idx)
+ {
+ for (uint32_t l_jdx = 0; l_jdx < P; ++l_jdx)
+ {
+ l_B[l_idx][l_jdx] = f_B[m_P[l_idx]][l_jdx];
+ }
+ }
+
+ return sTriL(sTriU(l_B));
+ }
+
+ template <uint32_t P>
+ CRightMultiplicationResultType<P> sTriU(const CRightMultipliableType<P>& f_B)
+ {
+ return triUInv()*f_B;
+ }
+
+ template <uint32_t P>
+ CRightMultiplicationResultType<P> sTriL(const CRightMultipliableType<P>& f_B)
+ {
+ // return triLInv()*f_B;
+ }
+
+
+ // private:
+ void decompose(const CMatrix<T,N,N>& f_matrix)
+ {
+ m_U = f_matrix;
+ for (uint32_t l_kdx = 0; l_kdx < (N-1); ++l_kdx)
+ {
+ m_L[l_kdx][l_kdx] = 1;
+ m_P[l_kdx] = l_kdx;
+
+ for(uint32_t l_idx = l_kdx+1; l_idx < N; ++l_idx)
+ {
+ m_L[l_idx][l_kdx] = m_U[l_idx][l_kdx]/m_U[l_kdx][l_kdx];
+ m_U[l_idx][l_kdx] = 0;
+ for(uint32_t l_jdx = l_kdx+1; l_jdx < N; ++l_jdx)
+ {
+ m_U[l_idx][l_jdx] = m_U[l_idx][l_jdx] - m_L[l_idx][l_kdx]*m_U[l_kdx][l_jdx];
+ }
+ }
+ }
+ m_L[N-1][N-1] = 1;
+ m_P[N-1] = N-1;
+ }
+ CMatrix<T,N,N> m_L;
+ CMatrix<T,N,N> m_U;
+ std::array<uint32_t,N> m_P;
+ };
+
+ template <class T, uint32_t N>
+ using CColVector = CMatrix<T,N,1>;
+
+ template <class T, uint32_t N>
+ using CVector = CColVector<T,N>;
+
+ template <class T, uint32_t N>
+ using CRowVector = CMatrix<T,1,N>;
+};
+
+#include "linalg.inl"
+
+#endif // LINALG_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Linalg/linalg.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,6 @@
+template<class T, uint32_t N,uint32_t M>
+typename linalg::CMatrix<T,N,M>::CThisType linalg::CMatrix<T,N,M>::inv()
+{
+ CThisType l_inv(linalg::CLUDecomposition<T,N>(*this).inv());
+ return l_inv;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/MotionController/motioncontroller.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,136 @@
+/**
+ ******************************************************************************
+ * @file MotionController.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the motion controller
+ * functionality.
+ ******************************************************************************
+ */
+
+#ifndef MOTION_CONTROLLER_HPP
+#define MOTION_CONTROLLER_HPP
+
+/* The mbed library */
+#include <mbed.h>
+#include <TaskManager/taskmanager.hpp>
+#include <Move/move.hpp>
+#include <BezierMotionPlanner/bezierMotionplanner.hpp>
+#include <Controllers/controller.hpp>
+#include <SafetyStop/safetystopfunction.hpp>
+
+#include <rtos.h>
+
+/**
+ * @brief Limit of the pwm command [percentage]
+ *
+ */
+#define MCTL_PWM_COMMAND_LIMIT 75
+/**
+ * @brief Limit of the velocity command [Centimeter per second]
+ *
+ */
+#define MCTL_SPEED_COMMAND_LIMIT 100
+
+//! CMotionController class.
+/*!
+ * It inherits class task::CTask.
+ * It is used for executing move commands.
+ * */
+class CMotionController
+{
+public:
+ CMotionController(
+ float f_period_sec,
+ Serial& f_serialPort,
+ Move& f_car,
+ CSafetyStopFunction* f_safetyStop,
+ controllers::CControllerSiso* f_control = NULL);
+ CMotionController(
+ float f_period_sec,
+ Serial& f_serialPort,
+ Move& f_car,
+ controllers::CControllerSiso* f_control = NULL);
+
+
+ /* Serial callback method for Move command */
+ static void staticSerialCallbackMove(void* obj,char const * a, char * b);
+ /* Serial callback method for BRAKE command */
+ static void staticSerialCallbackBrake(void* obj,char const * a, char * b);
+ /* Serial callback method for hard BRAKE command */
+ static void staticSerialCallbackHardBrake(void* obj,char const * a, char * b) ;
+ /* Serial callback method for PID activation command */
+ static void staticSerialCallbackPID(void* obj,char const * a, char * b);
+ /* Static serial callback for spline command */
+ static void staticSerialCallbackSpline(void* obj,char const * a,char * b );
+ /* Static callback function for run method */
+ static void staticCallbackRun(void* obj);
+ /* Start the Rtos timer for applying run */
+ void startRtosTimer();
+
+ /* Reset method */
+ void reset();
+ /* Get speed method */
+ float getSpeed();
+ /* Get angle method */
+ float getAngle();
+ /* BRAKE callback method */
+ void BrakeCallback();
+ /* Set state method */
+ void setState(int f_state);
+private:
+ /* Run method */
+ virtual void _run();
+ /* Serial callback implementation */
+ void serialCallbackMove(char const * a, char * b);
+ /* BRAKE serial callback */
+ void serialCallbackBrake(char const * a, char * b);
+ /* Hard BRAKE serial callback */
+ void serialCallbackHardBrake(char const * a, char * b);
+ /* PID serial callback */
+ void serialCallbackPID(char const * a, char * b);
+ /* Spline serial callback */
+ void serialCallbackSpline(char const * a, char * b);
+
+
+ /* Static function to convert from linear velocity ( centimeter per second ) of robot to angular velocity ( rotation per second ) of motor */
+ static float Mps2Rps(float f_vel_cmps);
+ // /* Velocity to PWM function */
+ // static float VEL2PWM(float vel);
+
+private:
+ /* reference to Serial object */
+ Serial& m_serialPort;
+ /* reference to MOVE object */
+ Move& m_car;
+ /* Speed */
+ float m_speed;
+ /* Angle */
+ float m_angle;
+ /* PEriod i nseconds */
+ float m_period_sec;
+ /* Spline activation state */
+ bool m_isSplineActivated;
+ /* State machine state */
+ uint8_t m_state;
+ /* PID activation state */
+ bool m_ispidActivated;
+ // 0-none
+ // 1-normal
+ // 2-brake regeneration
+
+ /* motion planner object */
+ planner::CBezierMotionPlanner m_motionPlanner;
+ /* Timeout */
+ Timeout m_hbTimeOut;
+ /* Reference to control object */
+ controllers::CControllerSiso* m_control;
+ /* Reference to safety stop function */
+ CSafetyStopFunction* m_safetyStop;
+ /* Rtos timer for periodically applying */
+ RtosTimer m_timer;
+};
+
+#endif // MOTION_CONTROLLER_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Move/move.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,53 @@
+/**
+ ******************************************************************************
+ * @file MOVE.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the moving
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef MOVE_HPP
+#define MOVE_HPP
+
+#include <Drivers/servo.hpp>
+#include <Drivers/vnh.hpp>
+
+/**
+ * @brief Move class
+ * It is used for executing move commands.
+ *
+ */
+class Move
+{
+public:
+ /* Constructor */
+ Move(PinName, PinName, PinName, PinName, PinName);//A0
+ /* Destructor */
+ ~Move();
+ /* Steer */
+ void Steer(float angle);// -25 to + 25 degrees, - (left), + (right)
+ /* Speed */
+ void Speed(float speed);//-100 to + 100 -(back), + (front)
+ /* Brake */
+ void Brake();
+ /* Inverse */
+ void Inverse(float f_speed);
+ /* Test */
+ void TestCar();
+ /* Reset */
+ void ResetCar();
+ /* Return bridge object */
+ drivers::VNH& getVNH();
+
+private:
+ /* Servo pbject */
+ drivers::SERVO servo;
+ /* Bridge object */
+ drivers::VNH vnh;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Queue/queue.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ * @file Queue.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class declaration for the queue
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef QUEUE_HPP
+#define QUEUE_HPP
+
+
+/**
+ * @brief It is used for executing queue container.
+ *
+ * @tparam T The type of the varieble
+ * @tparam N The size of the queue
+ */
+template <class T, unsigned int N>
+class CQueue
+{
+public:
+ /* Constructor */
+ CQueue();
+ /* Destructor */
+ virtual ~CQueue();
+ /* Is full method */
+ inline bool isFull();
+ /* Is full method */
+ inline bool isEmpty();
+ /* Peek */
+ inline T peek();
+ /* Pop */
+ inline T pop();
+ /* Get queue size */
+ inline unsigned int getSize();
+ /* Push single element */
+ inline void push(T& f_char);
+ /* Push multiple elements */
+ inline void push(T *f_char, unsigned int f_len);
+ /* Empty queue */
+ inline void empty();
+private:
+ /* buffer */
+ volatile T m_buffer[N];
+ /* start */
+ volatile unsigned int m_start;
+ /* end */
+ volatile unsigned int m_end;
+ /* size */
+ volatile unsigned int m_size;
+};
+
+#include "queue.inl"
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Queue/queue.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,153 @@
+/**
+ ******************************************************************************
+ * @file Queue.inl
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the queue
+ * functionality. Inlin eimplementation.
+ ******************************************************************************
+ */
+
+/** @brief Queue Class constructor
+ *
+ * Constructor method
+ *
+ *
+ */
+template <class T, unsigned int N>
+CQueue<T,N>::CQueue()
+ : m_buffer()
+ , m_start(0)
+ , m_end(N-1)
+ , m_size(0)
+{
+}
+
+/** @brief Queue Class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+template <class T, unsigned int N>
+CQueue<T,N>::~CQueue()
+{
+}
+
+/** @brief Is full method
+ *
+ *
+ * @return True if Queue FULL
+ */
+template <class T, unsigned int N>
+bool CQueue<T,N>::isFull()
+{
+ return (m_start + 1)%N == m_end;
+}
+
+/** @brief Is empty method
+ *
+ *
+ * @return True if Queue EMPTY
+ */
+template <class T, unsigned int N>
+bool CQueue<T,N>::isEmpty()
+{
+ return (m_end + 1)%N == m_start;
+}
+
+/** @brief Peek method
+ *
+ *
+ * @return Value on top of queue
+ */
+template <class T, unsigned int N>
+T CQueue<T,N>::peek()
+{
+ return m_buffer[(m_end+1) % N];
+}
+
+/** @brief Pop method
+ *
+ * Method for removing the item on top of the queue and returning it
+ *
+ *
+ * @return Element at top of the queue
+ */
+template <class T, unsigned int N>
+T CQueue<T,N>::pop()
+{
+ if(!isEmpty())
+ {
+ m_end = (m_end+1) % N;
+ T l_char = m_buffer[m_end];
+ m_size--;
+ return l_char;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/** @brief Push method
+ *
+ * Method for inserting an item on top of the queue
+ *
+ * @param f_char element to be added to the queue
+ * @return None
+ */
+template <class T, unsigned int N>
+void CQueue<T,N>::push(T& f_char)
+{
+ if (!isFull())
+ {
+ m_buffer[m_start] = f_char;
+ m_start = (m_start+1) % N;
+ m_size++;
+ }
+}
+
+/** @brief Push method
+ *
+ * Method for inserting a sequence of items on top of the queue
+ *
+ * @param f_char pointer to element to be added to the queue
+ * @param f_len number of elements to be added
+ * @return None
+ */
+template <class T, unsigned int N>
+inline void CQueue<T,N>::push(T *f_char, unsigned int f_len)
+{
+ for ( unsigned int l_idx = 0; l_idx < f_len; ++l_idx)
+ {
+ push(f_char[l_idx]);
+ }
+}
+
+/** @brief Get size method
+ *
+ * Returns the size of the queue
+ *
+ *
+ * @return Queue size
+ */
+template <class T, unsigned int N>
+unsigned int CQueue<T,N>::getSize()
+{
+ return m_size;
+}
+
+/** @brief Empty queue method
+ *
+ *
+ * @return None
+ */
+template <class T, unsigned int N>
+inline void CQueue<T,N>::empty()
+{
+ m_start = 0;
+ m_end = N-1;
+ m_size = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SHARP_IR_distance/DistanceSensors/distancesensors.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,59 @@
+/**
+ ******************************************************************************
+ * @file DistanceSensors.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date 08-January-2018
+ * @brief This file contains the class definition for the distance sensors read
+ * methods.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef DISTANCESENSORS_HPP
+#define DISTANCESENSORS_HPP
+
+#include <mbed.h>
+#include <array>
+#include <string>
+#include<TaskManager/taskmanager.hpp>
+#include <SHARP_IR_distance\DistanceSensors\distancesensors.hpp>
+using namespace std;
+
+/**
+ * @brief It is used for reading the attached distance sensors.
+ *
+ */
+template<class T>
+class CDistanceSensors: public task::CTask
+{
+private:
+ /* The sensors list */
+ T m_sensor_list;
+ /* Index of current sensor */
+ uint8_t m_index;
+ /* The maximum number of sensors that are used */
+ const uint8_t m_N;
+ /* Flags for enabloing/disabling timeout */
+ Timeout m_disableTimeOut;
+ Timeout m_enableTimeOut;
+ /* Message that contains the read values */
+ string m_message;
+
+public:
+ /* Construnctor */
+ CDistanceSensors(uint32_t f_period,
+ float f_baseTick,
+ T& f_sensor_list);
+ /* Destructor */
+ ~CDistanceSensors();
+ /* Callback for reading sensor value */
+ void ReadCallback(void);
+ /* Run method */
+ void _run(void);
+};
+
+#include "DistanceSensors.inl"
+
+/* Include guard */
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SHARP_IR_distance/DistanceSensors/distancesensors.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,79 @@
+/** @brief Class constructor
+
+
+ @param f_period sensor reading period
+ @param f_baseTick base tick period, in seconds
+ @param f_sensor_list the list of sensor objects
+ */
+template<class T >
+CDistanceSensors<T>::CDistanceSensors(const uint32_t f_period,
+ const float f_baseTick,
+ T& f_sensor_list)
+ : task::CTask(f_period)
+ , m_sensor_list(f_sensor_list)
+ , m_index(0)
+ , m_N(f_sensor_list.size())
+ , m_disableTimeOut()
+ , m_enableTimeOut()
+ , m_message("@IRDS:")
+ // , m_buf("")
+{
+ //static_assert(f_sensor_list.size() * 0.03 < f_period*f_baseTick,
+ //"IR sensor reding period is too small! It must be grater than: number of sensors in \"conflict\" *0.3seconds!");
+}
+
+//static_assert(m_N * 0.03 < f_period*f_baseTick,
+// "IR sensor reding period is too small! It must be grater than: number of sensors in \"conflict\" *0.3seconds!");
+
+/** @brief Class destructor
+
+ Destructor method
+ */
+template<class T >
+CDistanceSensors<T>::~CDistanceSensors(){}
+
+/** @brief Read callback method
+
+ Callback for reading the value of one distance sensor
+
+ */
+template<class T >
+void CDistanceSensors<T>::ReadCallback(){
+ // // buffer for holding message data
+ // char buf [10];
+ // read distance form sensor at position m_index in the sensor list
+ m_sensor_list[m_index]->ReadDistance();
+ // disable sensor at position m_index in the sensor list
+ m_sensor_list[m_index]->disable();
+ //sprintf(buf,"-%d-%3.2f;",m_index, m_sensor_list[m_index]->getValue());/// cu m_index
+ // format value so it can be appended to message
+ // sprintf(buf,"%3.2f;", m_sensor_list[m_index]->getValue()); // standard formatting
+ // // append value from sensor to message
+ // m_message.append(buf);
+ // if the last sensor is read, send message on UART and exit method
+ if(m_index == m_N-1){
+ // m_message=m_message+";\r\n";
+ // m_serial.printf(m_message.c_str());
+ // m_message="@IRDS:";
+ return;
+ }
+ // go to next sensor
+ m_index = m_index+1;
+ // enable next sensor
+ m_sensor_list[m_index]->enable();
+ // disable sensor timeout, read next sensor after 0.03 seconds
+ m_disableTimeOut.attach(callback(this, &CDistanceSensors<T>::ReadCallback), 0.03);
+}
+
+/** @brief Method called each f_period
+ *
+ */
+template<class T >
+void CDistanceSensors<T>::_run(){
+ // start from first sensor
+ m_index=0;
+ // enable first sensor
+ m_sensor_list[m_index]->enable();
+ // read sensor after 0.03 seconds
+ m_disableTimeOut.attach(callback(this, &CDistanceSensors<T>::ReadCallback), 0.03);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SHARP_IR_distance/IR_DistanceSensorDriver/ir_distancesensordriver.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,85 @@
+/**
+ ******************************************************************************
+ * @file IR_DistanceSensorDriver.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date 08-January-2018
+ * @brief This file contains the class definition for the SHARP IR sensor read
+ * methods (driver).
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef IR_DISTANCESENSORDRIVER_HPP
+#define IR_DISTANCESENSORDRIVER_HPP
+
+#include <mbed.h>
+#include <math.h>
+
+/* Module defines */
+#define C_IR_DistanceSensorDriver_A -19057.99103709
+#define C_IR_DistanceSensorDriver_B 42562.72078701
+#define C_IR_DistanceSensorDriver_C -37447.6482552
+#define C_IR_DistanceSensorDriver_D 16482.62217927
+#define C_IR_DistanceSensorDriver_E -3758.54454044
+#define C_IR_DistanceSensorDriver_F 395.72452643
+
+/* //scaling values, variant 1
+a=733.06912872;
+b=-2221.23062859;
+c=2502.20535578;
+d=-1273.63067295;
+e=269.64209866;
+*/
+
+/*
+//scaling values, variant 2, used for obtaining more accurate values
+a=-6144.18274059;
+b=19775.78355498;
+c=-25056.00451678;
+d=15739.05258272;
+e=-4986.65539646;
+f=673.27540402;
+*/
+/*scaling values, variant 3 (media benzii)
+a=-19057.99103709;
+b=42562.72078701;
+c=-37447.6482552;
+d=16482.62217927;
+e=-3758.54454044;
+f=395.72452643;
+*/
+
+/**
+ * @brief It is used for reading SHARP IR distance sensors.
+ *
+ */
+class C_IR_DistanceSensorDriver
+{
+public:
+ /* Construnctor */
+ C_IR_DistanceSensorDriver(AnalogIn ain_pin, DigitalOut en_pin);
+ /* Destrunctor */
+ ~C_IR_DistanceSensorDriver();
+ /* Method for reading distance */
+ float ReadDistance(void);
+ /* Method for enabling sensor */
+ void enable(void);
+ /* Method for disabling sensor */
+ void disable(void);
+ //void setValue(float);
+ /* Method for obtaining read value */
+ float getValue(void);
+
+private:
+
+ /* the analog pin, giving the proportional voltage value */
+ AnalogIn ain_pin;
+ /* enable pin */
+ DigitalOut en_pin;
+ /* distance value */
+ float value;
+};
+
+/* Include guard */
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SHARP_IR_distance/drivertask.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,53 @@
+#ifndef DRIVER_TASK_H
+#define DRIVER_TASK_H
+
+#include <TaskManager.h>
+#include <DistanceDriver.h>
+#include <filter.h>
+
+
+
+
+template<class T>
+class CDriverTask: public task::CTask
+{
+ public:
+ using FilterFunc=filter::CFilterFunction<T>;
+ CDriverTask( uint32_t f_period
+ ,PinName f_pin
+ ,FilterFunc& f_filter
+ ,Serial& f_serial)
+ :CTask(f_period)
+ ,m_filter(f_filter)
+ ,m_distanceDriver(f_pin)
+ ,m_val_brut(0.0)
+ ,m_val_filtrat(0.0)
+ ,m_serial(f_serial)
+ ,idx(0)
+ {
+ }
+
+ T getDistanceFiltered(){
+ return m_val_filtrat;
+ }
+
+ T getDistanceMeasured(){
+ return m_val_brut;
+ }
+
+
+
+ private:
+ virtual void _run(){
+ m_val_brut=m_distanceDriver.ReadDistance();
+ m_val_filtrat=m_filter(m_val_brut);
+ }
+
+ FilterFunc& m_filter;
+ DistanceDriver m_distanceDriver;
+ T m_val_brut;
+ T m_val_filtrat;
+ Serial& m_serial;
+ int idx;
+};
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SafetyStop/safetystopfunction.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,75 @@
+/**
+ ******************************************************************************
+ * @file SafetyStopFunction.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the safety stop activation
+ * methods.
+ ******************************************************************************
+ */
+
+/* Include guard */
+#ifndef SAFETY_STOP_FUNCTION_HPP
+#define SAFETY_STOP_FUNCTION_HPP
+
+/* Required for the use of C_IR_DistanceSensorDriver */
+#include <SHARP_IR_distance\IR_DistanceSensorDriver\ir_distancesensordriver.hpp>
+
+
+/**
+ * @brief It is used for deciding whether to activate safetyu stop depending on
+ * distance sensors reading.
+ *
+ */
+class CSafetyStopFunction{
+public:
+ /* Construnctor */
+ CSafetyStopFunction(C_IR_DistanceSensorDriver& f_senLeftFront
+ , C_IR_DistanceSensorDriver& f_senMidLeftFront
+ , C_IR_DistanceSensorDriver& f_senCenterFront
+ , C_IR_DistanceSensorDriver& f_senMidRightFront
+ , C_IR_DistanceSensorDriver& f_senRightFront
+ // , C_IR_DistanceSensorDriver& f_senLeftBach
+ // , C_IR_DistanceSensorDriver& f_senRightBach
+ );
+
+ /* Destructor */
+ ~CSafetyStopFunction();
+
+ /* Function for activating safety stop */
+ bool isSafetyStopActive(float f_speed, float f_angle);
+ /* Serial callback method */
+ static void staticSerialCallback(void* obj,char const * a, char * b);
+private:
+ /* Serial callback actions */
+ void serialCallback(char const * a, char * b);
+ /* The functionality active state*/
+ bool m_active;
+ /* Current car speed */
+ float m_speed;
+ /* Current steering angle */
+ float m_angle;
+ /* Front sensors */
+ C_IR_DistanceSensorDriver& m_senLeftFront;
+ C_IR_DistanceSensorDriver& m_senMidLeftFront;
+ C_IR_DistanceSensorDriver& m_senCenterFront;
+ C_IR_DistanceSensorDriver& m_senMidRightFront;
+ C_IR_DistanceSensorDriver& m_senRightFront;
+ /* Back sensors */
+ // C_IR_DistanceSensorDriver& m_senLeftBach;
+ // C_IR_DistanceSensorDriver& m_senRightBach;
+ /* Serial communication member */
+ /* USED FOR DEBUG */
+};
+
+/* Include guard */
+#endif
+
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SerialMonitor/serialmonitor.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,70 @@
+/**
+ ******************************************************************************
+ * @file SerialMonitor.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the serial communication
+ * functionality.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef SERIAL_MONITOR_HPP
+#define SERIAL_MONITOR_HPP
+
+/* The mbed library */
+#include <mbed.h>
+#include <map>
+#include <array>
+/* Function objects */
+#include <functional>
+#include<TaskManager/taskmanager.hpp>
+#include <Queue/queue.hpp>
+
+
+namespace serial{
+
+ /**
+ * @brief It is used for implementing serial communciation.
+ *
+ */
+ class CSerialMonitor : public task::CTask
+ {
+ public:
+ typedef mbed::Callback<void(char const *, char *)> FCallback;
+ typedef std::map<string,FCallback> CSerialSubscriberMap;
+
+ /* Constructor */
+ CSerialMonitor(Serial& f_serialPort
+ ,CSerialSubscriberMap f_serialSubscriberMap);
+ private:
+ /* Rx callback */
+ static void RxCallback(void *thisPointer);
+ /* Tx callback */
+ static void TxCallback(void *thisPointer);
+ /* Rx callback actions */
+ void serialRxCallback();
+ /* Tx callback actions */
+ void serialTxCallback();
+ /* Run method */
+ virtual void _run();
+
+ /* Reference to serial object */
+ Serial& m_serialPort;
+ /* Rx buffer */
+ CQueue<char,255> m_RxBuffer;
+ /* Tx buffer */
+ CQueue<char,255> m_TxBuffer;
+ /* Data buffer */
+ array<char,256> m_parseBuffer;
+ /* Parse iterator */
+ array<char,256>::iterator m_parseIt;
+ /* Serial subscriber */
+ CSerialSubscriberMap m_serialSubscriberMap;
+ };
+
+}; // namespace serial
+
+#endif // SERIAL_MONITOR_HPP
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SystemModels/systemmodels.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,155 @@
+/**
+ ******************************************************************************
+ * @file SystemModels/systemmodels.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declarations for system model.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef SYSTEM_MODELS_HPP
+#define SYSTEM_MODELS_HPP
+
+#include <Linalg/linalg.h>
+
+// Discrete System Models
+namespace systemmodels{
+ //Linear time variant models
+ namespace lti{
+ namespace siso{
+ /**
+ * @brief Discrete transfer function
+ *
+ * @tparam T The type of the variable
+ * @tparam NNum The order of the polynomial
+ * @tparam NDen The order of the polynomial
+ */
+ template <class T,uint32_t NNum,uint32_t NDen>
+ class CDiscreteTransferFucntion{
+ public:
+ using CDenType = linalg::CMatrix<T,NDen,1>;
+ using CDenModType = linalg::CMatrix<T,NDen-1,1>;
+ using CNumType = linalg::CMatrix<T,NNum,1>;
+ // using CNumModType = linalg::CMatrix<T,NNum-1,1>;
+ using CInputMem = linalg::CMatrix<T,1,NNum>;
+ using COutputMem = linalg::CMatrix<T,1,NDen-1>;
+ /* Constructor */
+ CDiscreteTransferFucntion();
+
+ CDiscreteTransferFucntion(const CNumType& f_num,const CDenType& f_den);
+
+ /* Clear memory */
+ void clearMemmory();
+ /* Shift memory */
+ template<uint32_t N>
+ void shiftMemory(linalg::CMatrix<T,1,N>& f_mem);
+ /* Operator */
+ T operator()(const T& f_input);
+ /* Set num */
+ void setNum(const CNumType& f_num);
+ /* Set den */
+ void setDen(const CDenType& f_den);
+
+ const CNumType& getNum();
+ const CDenModType& getDen();
+ float getDenCurrent();
+ /* Get output */
+ T getOutput();
+
+ private:
+
+ #ifdef SYSTEMMODEL_TEST_HPP
+ FRIEND_TEST(CDiscreteTransferFucntionTest,Reset);
+ #endif
+
+ /* nominator type */
+ CNumType m_num;
+ // CDenType m_den;
+ /* denominator type */
+ CDenModType m_den;
+ T m_denCoef;
+ /* input memory */
+ CInputMem m_memInput;
+ /* output memory */
+ COutputMem m_memOutput;
+ };
+ }
+
+ };
+ // Nonlinea time invariant models
+ namespace nlti{
+ //Multi-input and multi-output
+ namespace mimo{
+ // Discrete time system model of a system nonlinear time invariant with multi-input and multi-output
+ // T -variable type
+ // NA -number of inputs
+ // NB -number of states
+ // NC -number of outputs
+ template <class T,uint32_t NA, uint32_t NB,uint32_t NC>
+ class CDiscreteTimeSystemModel{
+ public:
+ using CStatesType = linalg::CMatrix<T,NB,1>;
+ using CInputType = linalg::CMatrix<T,NA,1>;
+ using COutputType = linalg::CMatrix<T,NC,1>;
+ /* Constructor */
+ CDiscreteTimeSystemModel(const double f_dt);//:m_states(),m_dt(f_dt){}
+ /* Constructor */
+ CDiscreteTimeSystemModel(const CStatesType& f_states
+ ,const double f_dt);
+ //State transition model
+ //Calculate the system state depending on input, after calculation the relevant class members need to be syncronized.
+ virtual CStatesType update(const CInputType& f_input)=0;
+ //State observation model
+ //Calculate the system output depending on input, after calculation the relevant class members need to be syncronized.
+ virtual COutputType calculateOutput(const CInputType& f_input)=0;
+ // GETTERS
+ // The method returns the current system states
+ CStatesType getStates();//{return m_states;}
+ // The method returns the current system output
+ COutputType getOutput(){return m_outputs;}
+ float getTimeStep(){return m_dt;}
+ // SETTERS
+ void setStates(const CStatesType& f_states){
+ m_states=f_states;
+ }
+ protected:
+ // States
+ CStatesType m_states;
+ // Output
+ COutputType m_outputs;
+ // Time step
+ const double m_dt;
+ private:
+ };
+
+ // the state transition and observation matrices defined by Jacobians
+ // T -variable type
+ // NA -number of inputs
+ // NB -number of states
+ // NC -number of outputs
+ template <class T,uint32_t NA, uint32_t NB,uint32_t NC>
+ class CJacobianMatrices{
+ public:
+ using CStatesType = linalg::CMatrix<T,NB,1>;
+ using CInputType = linalg::CMatrix<T,NA,1>;
+ // using COutputType = linalg::CMatrix<T,NC,1>;
+ using CJMTransitionType = linalg::CMatrix<T,NB,NB>;
+ using CJMObservationType = linalg::CMatrix<T,NC,NB>;
+
+ //The method calculates and returns the states transition matrix
+ virtual CJMTransitionType getJMTransition(const CStatesType& f_states
+ ,const CInputType& f_inputs)=0;
+ // The method calculates and returns the states observation matrix
+ virtual CJMObservationType getJMObservation(const CStatesType& f_states
+ ,const CInputType& f_input)=0;
+ private:
+ };
+ };
+ };
+};
+
+#include "systemmodels.inl"
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SystemModels/systemmodels.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,171 @@
+/******************************************************************************/
+/** \brief CDiscreteTransferFucntion class constructor
+ *
+ * Constructor method
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::CDiscreteTransferFucntion()
+ :m_num(CNumType::zeros())
+ ,m_den(CDenModType::zeros())
+ ,m_denCoef(1)
+ ,m_memInput()
+ ,m_memOutput()
+{
+}
+
+
+template <class T,uint32_t NNum,uint32_t NDen>
+systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::CDiscreteTransferFucntion(const CNumType& f_num,const CDenType& f_den)
+ :m_num(CNumType::zeros())
+ ,m_den(CDenModType::zeros())
+ ,m_denCoef(1)
+ ,m_memInput()
+ ,m_memOutput()
+{
+ this->setNum(f_num);
+ this->setDen(f_den);
+}
+
+
+/** \brief Clear memory
+ *
+ *
+ *
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+void systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::clearMemmory()
+{
+ m_memInput=CInputMem::zeros();
+ m_memOutput=COutputMem::zeros();
+}
+
+/** \brief Clear memory
+ *
+ * @param f_input reference to input
+ * @return l_output
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+T systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::operator()(const T& f_input)
+{
+ shiftMemory<NNum>(m_memInput);
+ m_memInput[0][0]=f_input;
+ T l_output=((m_memInput*m_num-m_memOutput*m_den)[0][0])/m_denCoef;
+ shiftMemory<NDen-1>(m_memOutput);
+ m_memOutput[0][0]=l_output;
+ return l_output;
+}
+
+/** \brief Set num
+ *
+ * @param f_num reference to nominator
+ *
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+void systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::setNum(const CNumType& f_num)
+{
+ for(uint32_t i=0;i<NNum;++i)
+ {
+ m_num[i][0]=f_num[i][0];
+ }
+}
+
+/** \brief Set den
+ *
+ * @param f_den reference to denominator
+ *
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+void systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::setDen(const CDenType& f_den)
+{
+ for(uint32_t i=1;i<NDen;++i)
+ {
+ m_den[i-1][0]=f_den[i][0];
+ }
+ m_denCoef = f_den[0][0];
+}
+
+/** \brief Get output
+ *
+ *
+ * @return Output memory
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+T systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::getOutput()
+{
+ return m_memOutput[0][0];
+}
+
+/** \brief Shift memory
+ *
+ * @param f_mem reference to memory matrix
+ * @return none
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+template<uint32_t N>
+void systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::shiftMemory(linalg::CMatrix<T,1,N>& f_mem)
+{
+ for(uint32_t i=N-1;i>0;--i)
+ {
+ f_mem[0][i]=f_mem[0][i-1];
+ }
+}
+
+/******************************************************************************/
+/** \brief CDiscreteTimeSystemModel class constructor
+ *
+ * Constructor method
+ *
+ * @param f_dt Time step
+ */
+template <class T,uint32_t NA, uint32_t NB,uint32_t NC>
+systemmodels::nlti::mimo::CDiscreteTimeSystemModel<T,NA,NB,NC>::CDiscreteTimeSystemModel(const double f_dt)
+ : m_states()
+ , m_dt(f_dt)
+{
+}
+
+/** \brief CDiscreteTimeSystemModel class constructor
+ *
+ * Constructor method
+ *
+ * @param f_states States
+ * @param f_dt Time step
+ */
+template <class T,uint32_t NA, uint32_t NB,uint32_t NC>
+systemmodels::nlti::mimo::CDiscreteTimeSystemModel<T,NA,NB,NC>::CDiscreteTimeSystemModel(
+ const CStatesType& f_states
+ ,const double f_dt)
+ : m_states(f_states)
+ , m_dt(f_dt)
+{
+}
+
+
+
+/** \brief Getter numitor
+ *
+ * @return const reference to numitor
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+const typename systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::CNumType& systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::getNum(){
+ return m_num;
+}
+
+/** \brief Getter denomitor
+ * Return the denomitor without the first coefficeint.
+ *
+ * @return const reference to denomitor
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+const typename systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::CDenModType& systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::getDen(){
+ return m_den;
+}
+
+/** \brief Getter denomitor first coefficeint
+ *
+ * @return value of the denomitor first coefficeint
+ */
+template <class T,uint32_t NNum,uint32_t NDen>
+float systemmodels::lti::siso::CDiscreteTransferFucntion<T,NNum,NDen>::getDenCurrent(){
+ return m_denCoef;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/TaskManager/taskmanager.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,97 @@
+/**
+ ******************************************************************************
+ * @file TaskManager.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for task manager.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef TASK_MANAGER_HPP
+#define TASK_MANAGER_HPP
+
+#include <mbed.h>
+
+namespace task{
+ /**
+ * @brief It is used for implementing the task functionality.
+ *
+ */
+ class CTask
+ {
+ public:
+ /* Constructor */
+ CTask(uint32_t f_period);
+ /* Destructor */
+ virtual ~CTask();
+ /* Run method */
+ virtual void run();
+ /* Timer callback */
+ void timerCallback()
+ {
+ m_ticks++;
+ if (m_ticks >= m_period)
+ {
+ m_ticks = 0;
+ Trigger();
+ }
+ }
+ /* Trigger */
+ void Trigger()
+ {
+ m_triggered = true;
+ }
+ protected:
+ /* _run methof */
+ virtual void _run() = 0;
+ /* period */
+ const uint32_t m_period;
+ /* ticks */
+ uint32_t m_ticks;
+ /* trigger flag */
+ bool m_triggered;
+ };
+
+ /**
+ * @brief It is used for implementing the task manager functionality.
+ *
+ */
+ class CTaskManager
+ {
+ public:
+ /* Constructor */
+ CTaskManager(CTask** f_taskList, uint32_t f_taskCount, float f_baseFreq);
+ /* Destructor */
+ virtual ~CTaskManager();
+ /* Main callback */
+ inline void mainCallback()
+ {
+ for(uint32_t i = 0; i < m_taskCount; i++)
+ {
+ m_taskList[i]->run();
+ }
+ }
+ /* Timer callback */
+ inline void timerCallback()
+ {
+ for(uint32_t i = 0; i < m_taskCount; i++)
+ {
+ m_taskList[i]->timerCallback();
+ }
+ }
+ private:
+ /* Callback */
+ static void callback(void *thisPointer);
+ /* task list */
+ CTask** m_taskList;
+ /* task count */
+ uint32_t m_taskCount;
+ /* ticker */ /* A Ticker is used to call a function at a recurring interval */
+ Ticker m_ticker;
+ };
+
+}; // namespace task
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Timer/timer.hpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,58 @@
+/**
+ ******************************************************************************
+ * @file Timer.hpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class declaration for the timer functionality.
+ ******************************************************************************
+ */
+
+/* Inclusion guard */
+#ifndef TIMER_HPP
+#define TIMER_HPP
+
+#include <mbed.h>
+
+/**
+ * @brief It is used for implementing timers.
+ *
+ * @tparam N
+ * @tparam 1
+ */
+template <unsigned int N, unsigned int D = 1>
+class CTimer
+{
+public:
+ /* Constructor */
+ CTimer();
+ /* Destructor */
+ virtual ~CTimer();
+ /* Start timer */
+ inline void start();
+ /* Stop timer */
+ inline void stop() ;
+ /* Get timer */
+ inline uint32_t get();
+private:
+ /* Timer callback */
+ static void callback(void *thisPointer);
+ /* Increase milliseconds value */
+ void millisTicker();
+ /* Ticker member */
+ Ticker m_ticker;
+ /* Milliseconds value */
+ volatile uint32_t m_millisValue;
+ /* Flag indicating timer started */
+ bool m_started;
+};
+
+typedef CTimer<1,1000> CTimer_ms;
+typedef CTimer<1,1000000> CTimer_us;
+typedef CTimer<1,10000> CTimer_100us;
+typedef CTimer<60> CTimer_min;
+
+/* Inline implementation */
+#include "timer.inl"
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/Timer/timer.inl Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,95 @@
+/**
+ ******************************************************************************
+ * @file Timer.inl
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for the timer functionality.
+ * Inline implementation.
+ ******************************************************************************
+ */
+
+/** @brief CTimer class constructor
+ *
+ * Constructor method
+ *
+ *
+ */
+template <unsigned int N, unsigned int D>
+CTimer<N,D>::CTimer()
+ : m_ticker()
+ , m_millisValue(0)
+ , m_started(0)
+{
+}
+
+/** @brief CTimer class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+template <unsigned int N, unsigned int D>
+CTimer<N,D>::~CTimer()
+{
+ if (m_started)
+ stop ();
+}
+
+/** @brief Start timer
+ *
+ *
+ *
+ */
+template <unsigned int N, unsigned int D>
+void CTimer<N,D>::start ()
+{
+ m_started = 1;
+ m_ticker.attach (mbed::callback(&CTimer::callback, this), 1.f*N/D);
+}
+
+/** @brief Stop timer
+ *
+ *
+ *
+ */
+template <unsigned int N, unsigned int D>
+void CTimer<N,D>::stop()
+{
+ m_started = 0;
+ m_ticker.detach ();
+}
+
+/** @brief Get timer
+ *
+ *
+ * @return Milliseconds value
+ */
+template <unsigned int N, unsigned int D>
+uint32_t CTimer<N,D>::get()
+{
+ return m_millisValue;
+}
+
+/** @brief Timer callback
+ *
+ * @param thisPointer The object pointer.
+ *
+ */
+template <unsigned int N, unsigned int D>
+void CTimer<N,D>::callback(void *thisPointer)
+{
+ CTimer<N,D>* self = static_cast<CTimer<N,D>*>(thisPointer);
+ self->millisTicker();
+}
+
+/** @brief Increase milliseconds value
+ *
+ *
+ *
+ */
+template <unsigned int N, unsigned int D>
+void CTimer<N,D>::millisTicker()
+{
+ m_millisValue ++;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BezierCurve/beziercurve.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,12 @@ +/** + ****************************************************************************** + * @file BezierCurve.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-year + * @brief This file contains the class implementation for the Bezier Curve + * methods. + ****************************************************************************** + */ + +#include <BezierCurve/BezierCurve.hpp>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BezierCurve/polynomialfunction.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,1 @@ +#include <BezierCurve/PolynomialFunction.hpp>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/BezierMotionPlanner/beziermotionplanner.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,168 @@
+/**
+ ******************************************************************************
+ * @file BezierMotionPlanner.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the Bezier Motion
+ * Planner methods.
+ ******************************************************************************
+ */
+
+#include <iostream>
+#include <BezierMotionPlanner/bezierMotionplanner.hpp>
+
+namespace planner{
+
+ /**
+ * @brief Construct a new CBezierMotionPlanner::CBezierMotionPlanner object
+ *
+ */
+ CBezierMotionPlanner::CBezierMotionPlanner()
+ {
+ this->isInitialized=false;
+ }
+
+ /**
+ * @brief Construct a new CBezierMotionPlanner::CBezierMotionPlanner object
+ *
+ * @param isForward Forward movement flag
+ * @param a Point A
+ * @param b Point B
+ * @param c Point C
+ * @param d Point D
+ * @param motion_duration_i The motion duration in second.
+ * @param timestep_i The base period of the planner. (Sample time)
+ */
+ CBezierMotionPlanner::CBezierMotionPlanner(bool isForward,
+ std::complex<float> a,
+ std::complex<float> b,
+ std::complex<float> c,
+ std::complex<float> d,
+ float motion_duration_i,
+ float timestep_i)
+ : isForward(isForward)
+ , bezierCurve(a,b,c,d)
+ , motion_duration(motion_duration_i)
+ , time_step(timestep_i)
+ {
+ this->bezierValueInput_step=1.0/(int)(this->motion_duration/this->time_step);
+ this->next_bezierValueInput=0.0;
+ this->isInitialized=true;
+ }
+
+
+ /**
+ * @brief Set motion planner parameters
+ *
+ * @param isForward Forward movement flag
+ * @param a Point A
+ * @param b Point B
+ * @param c Point C
+ * @param d Point D
+ * @param motion_duration_i The motion duration in second.
+ * @param timestep_i The base period of the planner. (Sample time)
+ */
+ void CBezierMotionPlanner::setMotionPlannerParameters(bool isForward,
+ std::complex<float> a,
+ std::complex<float> b,
+ std::complex<float> c,
+ std::complex<float> d,
+ float motion_duration_i,
+ float timestep_i)
+ {
+ this->isForward=isForward;
+ this->motion_duration=motion_duration_i;
+ this->time_step=timestep_i;
+ this->bezierCurve.setBezierCurve(a,b,c,d);
+ this->bezierValueInput_step=1.0/(int)(this->motion_duration/this->time_step);
+ this->next_bezierValueInput=0.0;
+ this->isInitialized=true;
+ }
+
+ /**
+ * @brief Destroy the CBezierMotionPlanner::CBezierMotionPlanner object
+ *
+ */
+ CBezierMotionPlanner::~CBezierMotionPlanner()
+ {
+ }
+
+
+ /**
+ * @brief Get the Bezier curve.
+ *
+ */
+ math::BezierCurve<float> CBezierMotionPlanner::getBezierCurve()
+ {
+ return this->bezierCurve;
+ }
+
+ /**
+ * @brief Get the next control parameters. It calculates the velocity and angle, and increase input value.
+ *
+ * @return It returns the next forward velocity and direction angle.
+ */
+ std::pair<float,float> CBezierMotionPlanner::getNextVelocity(){
+ std::pair<float,float> commands=this->getVelocity(next_bezierValueInput);
+ this->next_bezierValueInput+=this->bezierValueInput_step;
+ return commands;
+ }
+
+ /**
+ * @brief Get the forward velocity and steering angle, base on the given input value.
+ *
+ * @param input_value The input value have to belong to interval [0,1].
+ * @return It returns a pair of number, where the fist variable and the second contains the forward velocity and the steering angular, respectively.
+ */
+ std::pair<float,float> CBezierMotionPlanner::getVelocity(float input_value)
+ {
+ if(!this->isInitialized) return std::pair<float,float>(0,0);
+
+ std::complex<float> dS=this->bezierCurve.get_FO_DerivateValue(input_value);
+
+ float dl_absolute=sqrt((dS*std::conj(dS)).real());//[0,1]//Length of the vector
+ float dl_real=dl_absolute/this->motion_duration;
+
+ std::complex<float> ddS=this->bezierCurve.get_SO_DerivateValue(input_value);
+
+ std::complex<float> correctorValue(0,-2);
+ std::complex<float> temp1=(dS*std::conj(ddS)-std::conj(dS)*ddS)/correctorValue;
+ float num=temp1.real();
+ if(dl_absolute==0)
+ {
+ return std::pair<float,float>(dl_real,0);
+ }
+
+ float k=num/pow(dl_absolute,3);
+
+ float angle_rad=atan(k*WHEELBASE);
+ float angle_deg=(180.f/M_PI)*angle_rad;
+
+ std::pair<float,float> commands(dl_real,angle_deg);
+ return commands;
+ }
+
+ /**
+ * @brief Get the state of the planner.
+ *
+ * @return true The planner has valid value.
+ * @return false The planner finished the last given curve, it cannnot get correct parameters.
+ */
+ bool CBezierMotionPlanner::hasValidValue()
+ {
+ return (next_bezierValueInput>=0 && next_bezierValueInput<=1);
+ }
+
+ /** @brief Get the direction of the motion
+ *
+ *
+ * @return true The motion direction is forward.
+ * @return false The motion direction is backward.
+ */
+ bool CBezierMotionPlanner::getForward()
+ {
+ return this->isForward;
+ }
+
+}; // namespace planner
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CommandInterpreter/commandinterpreter.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,180 @@
+/**
+ ******************************************************************************
+ * @file CommandInterpreter.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for the command interpreter
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <CommandInterpreter/commandinterpreter.hpp>
+
+/** \brief CCommandInterpreter Class constructor
+ *
+ * Constructor method
+ *
+ * \param[in] f_car reference to MOVE object
+ */
+CCommandInterpreter::CCommandInterpreter(Move& f_car)
+ : m_buffer()
+ , m_car(f_car)
+ , m_commandValue()
+{
+}
+
+/** \brief Interpret character
+ *
+ * \param[in] f_c character value
+ */
+void CCommandInterpreter::interpretChar(unsigned char f_c)
+{
+ if ((f_c == 'A') || (f_c == 'S'))
+ {
+// led1 = 1;
+ reset();
+ m_buffer.push(f_c);
+ m_commandID = f_c;
+// char s[100];
+// unsigned int l = sprintf(s,"storing command starting with %c, %c stored",f_c, m_buffer.peek());
+// g_rpiWriteBuffer.push(s,l);
+ }
+ else
+ {
+ m_buffer.push(f_c);
+// char s[100];
+// unsigned int l = sprintf(s,"peeked %c, command_ID is %c, size is %d",m_buffer.peek(),m_commandID,m_buffer.getSize());
+// g_rpiWriteBuffer.push(s,l);
+ if (m_buffer.getSize() == 5)
+ {
+// char s[100];
+// unsigned int l = sprintf(s,"interpreting command starting with %c",m_commandID);
+// g_rpiWriteBuffer.push(s,l);
+ intepretCommand();
+ reset();
+ }
+ }
+}
+
+/** \brief Execute command
+ *
+ */
+void CCommandInterpreter::executeCommand()
+{
+ m_car.Steer(m_angleValue);
+ m_car.Speed(m_speedValue);
+// reset();
+}
+
+/** \brief Reset
+ *
+ *
+ *
+ */
+void CCommandInterpreter::reset()
+{
+ m_commandID = 0;
+ m_buffer.empty();
+}
+
+/** \brief Interpret command
+ *
+ *
+ *
+ */
+void CCommandInterpreter::intepretCommand()
+{
+ unsigned char test_char = m_buffer.pop();
+ if (test_char != m_commandID)
+ {
+ reset();
+// led1 = 0;
+// char s[100];
+// unsigned int l = sprintf(s,"interpretation failed at ID. Expected: %c, received: %c",m_commandID,test_char);
+// g_rpiWriteBuffer.push(s,l);
+ }
+ else
+ {
+ float l_sign = 0;
+ if (m_buffer.peek() == '0')
+ {
+ l_sign = 1;
+ }
+ else if (m_buffer.peek() == '1')
+ {
+ l_sign = -1;
+ }
+ else
+ {
+ reset();
+// led1 = 0;
+// char s[100];
+// unsigned int l = sprintf(s,"interpretation failed a sign");
+// g_rpiWriteBuffer.push(s,l);
+ return;
+ }
+ m_buffer.pop();
+ if ((m_buffer.peek() < '0') || (m_buffer.peek() > '9'))
+ {
+ reset();
+// led1 = 0;
+// char s[100];
+// unsigned int l = sprintf(s,"interpretation failed at val 1");
+// g_rpiWriteBuffer.push(s,l);
+ return;
+ }
+ else
+ {
+ m_commandValue = m_buffer.pop() - '0';
+ }
+ if ((m_buffer.peek() < '0') || (m_buffer.peek() > '9'))
+ {
+ reset();
+// led1 = 0;
+// char s[100];
+// unsigned int l = sprintf(s,"interpretation failed at val 2, value is %c",m_buffer.peek());
+// g_rpiWriteBuffer.push(s,l);
+ return;
+ }
+ else
+ {
+ m_commandValue *= 10;
+ m_commandValue += m_buffer.pop() - '0';
+ m_commandValue *= l_sign;
+ }
+ if (m_buffer.pop() != ';')
+ {
+ reset();
+// led1 = 0;
+// char s[100];
+// unsigned int l = sprintf(s,"interpretation failed at terminator");
+// g_rpiWriteBuffer.push(s,l);
+ return;
+ }
+ else
+ {
+ if(m_commandID == 'A')
+ {
+ m_angleValue = m_commandValue;
+// char s[100];
+// unsigned int l = sprintf(s,"set angle to %f\n", m_angleValue);
+// g_rpiWriteBuffer.push(s,l);
+// led1 = 1;
+ reset();
+ return;
+ }
+ if(m_commandID == 'S')
+ {
+ m_speedValue = m_commandValue;
+// char s[100];
+// unsigned int l = sprintf(s,"set speed to %f\n", m_speedValue);
+// g_rpiWriteBuffer.push(s,l);
+// led1 = 1;
+ reset();
+ return;
+ }
+ reset();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Controllers/controller.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,153 @@
+/**
+ ******************************************************************************
+ * @file Controller.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the controller
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Controllers/controller.hpp>
+
+namespace controllers{
+ /**
+ * @brief Construct a new CControllerSiso::CControllerSiso object
+ *
+ * @param f_encoder Reference to the encoder getter interface.
+ * @param f_pid Reference to the controller interface.
+ * @param f_converter [Optional] Pointer to the converter interface.
+ */
+ CControllerSiso::CControllerSiso(encoders::IEncoderGetter& f_encoder
+ ,ControllerType<double>& f_pid
+ ,controllers::IConverter* f_converter)
+ :m_encoder(f_encoder)
+ ,m_pid(f_pid)
+ ,m_converter(f_converter)
+ ,m_control_sup(0.5)
+ ,m_control_inf(-0.5)
+ ,m_ref_abs_inf(10.0)
+ ,m_mes_abs_inf(30.0)
+ ,m_mes_abs_sup(300.0)
+ {
+ }
+
+ /**
+ * @brief Set the reference signal value.
+ *
+ * @param f_RefRps The value of the reference signal
+ */
+ void CControllerSiso::setRef(double f_RefRps)
+ {
+ m_RefRps=f_RefRps;
+ }
+
+ /** \brief Get the value of reference signal.
+ *
+ */
+ double CControllerSiso::getRef()
+ {
+ return m_RefRps;
+ }
+
+ /** @brief Get the value of the control signal calculated last time.
+ *
+ */
+ double CControllerSiso::get()
+ {
+ return m_u;
+ }
+
+ /** @brief Get the value of the error between the measured and reference signal.
+ *
+ */
+ double CControllerSiso::getError()
+ {
+ return m_error;
+ }
+
+ /** @brief Clear the memory of the controller.
+ *
+ */
+ void CControllerSiso::clear()
+ {
+ m_pid.clear();
+ }
+
+
+ /**
+ * @brief It calculates the next value of the control signal, by utilizing the given interfaces.
+ *
+ * @return true control works fine
+ * @return false appeared an error
+ */
+ bool CControllerSiso::control()
+ {
+ // Mesurment speed value
+ float l_MesRps = m_encoder.getSpeedRps();
+ bool l_isAbs = m_encoder.isAbs();
+ float l_ref;
+
+ // Check the measured value and the superior limit for avoid over control state.
+ // In this case deactivete the controller.
+ if(std::abs(l_MesRps) > m_mes_abs_sup){
+ m_RefRps = 0.0;
+ m_u = 0.0;
+ error("@PIDA:CControllerSiso: To high speed!;;\r\n");
+ return false;
+ }
+ // Check the inferior limits of reference signal and measured signal for standing state.
+ // Inactivate the controller
+ if(std::abs(m_RefRps) < m_ref_abs_inf && std::abs(l_MesRps) < m_mes_abs_inf ){
+ m_u = 0.0;
+ m_error = 0.0;
+ return true;
+ }
+
+ // Check measured value is oriantated or absolute
+ if ( l_isAbs ){
+ l_ref = std::abs(m_RefRps);
+ } else{
+ l_ref = m_RefRps;
+ }
+ float l_error=l_ref-l_MesRps;
+ float l_v_control = m_pid.calculateControl(l_error);
+ float l_pwm_control = converter(l_v_control);
+
+ m_u=l_pwm_control;
+ m_error=l_error;
+
+ // Check measured value is oriantated or absolute.
+ if(m_RefRps<0 && l_isAbs)
+ {
+ m_u=m_u*-1.0;
+ }
+ return true;
+ }
+
+ /** @brief
+ *
+ * Apply the converter interface to change the measurment unit.
+ *
+ * @param f_u Input control signal
+ * @return Converted control signal
+ */
+ double CControllerSiso::converter(double f_u)
+ {
+ double l_pwm=f_u;
+ // Convert the control signal from V to PWM
+ if(m_converter!=NULL){
+ l_pwm = (*m_converter)(f_u);
+ }
+
+ // Check the pwm control signal and limits
+ if( l_pwm < m_control_inf ){
+ l_pwm = m_control_inf;
+ } else if( l_pwm > m_control_sup ){
+ l_pwm = m_control_sup;
+ }
+ return l_pwm;
+ }
+
+}; // namespace controllers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Controllers/converters.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,2 @@ +#include <Controllers\converters.hpp> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Controllers/pidcontroller.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,13 @@ +/** + ****************************************************************************** + * @file PidController.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-year + * @brief This file contains the classes implementation for the PID controller + * functionality. Because template classes are used, the code was + * placed in a corresponding .inl file + ****************************************************************************** + */ + +#include <Controllers/pidcontroller.hpp>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Drivers/servo.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,63 @@
+/**
+ ******************************************************************************
+ * @file SERVO.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for the steering SERVO
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Drivers/servo.hpp>
+
+
+namespace drivers{
+ /** @brief SERVO class constructor
+ *
+ * Constructor method
+ *
+ * @param _pwm pin connected to servo input
+ */
+ SERVO::SERVO(PinName _pwm)
+ :pwm(_pwm)
+ {
+ pwm.period_ms(20);
+ // pwm.write(0.075);
+ pwm.write(0.07525);
+ };
+
+ /** @brief SERVO class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+ SERVO::~SERVO()
+ {
+ };
+
+ /** @brief Set angle method
+ *
+ * @param angle angle
+ */
+ void SERVO::SetAngle(float angle)
+ {
+ pwm.write(conversion(angle));
+ };
+
+ /** @brief Conversion method
+ *
+ * @param angle angle
+ * \return duty cycle
+ */
+ float SERVO::conversion(float angle)
+ {
+ //rc-servo-4519
+ //return (0.0010321101 * angle + 0.0725);
+ //fs-5106B
+ // return (0.035 +0.0272+ (angle + 25.f) / 1953.135);
+ //RS2 MG/BB
+ return (0.0009505 * angle + 0.07525);
+ };
+}; // namespace drivers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Drivers/vnh.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,135 @@
+/**
+ ******************************************************************************
+ * @file VNH.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class defoinition for the VNH Bridge Driver
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Drivers/vnh.hpp>
+
+
+namespace drivers{
+
+
+
+ /** @brief VNH class constructor
+ *
+ * Constructor method
+ *
+ * @param _pwm PWM pin
+ * @param _ina pin A
+ * @param _inb pin B
+ * @param _current current analog pin
+ */
+ VNH::VNH(PinName _pwm, PinName _ina, PinName _inb, PinName _current)
+ :pwm(_pwm)
+ ,ina(_ina)
+ ,inb(_inb)
+ ,current(_current)
+ {
+ pwm.period_us(200);
+ increment = 0.01;
+ current_speed = 0;
+ }
+
+ /** @brief VNH class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+ VNH::~VNH()
+ {
+ }
+
+ /** @brief Start method
+ *
+ *
+ *
+ */
+ void VNH::Start(void)
+ {
+ ina = !inb;
+ pwm.write(0);
+ }
+
+ /** @brief Stop method
+ *
+ *
+ *
+ */
+ void VNH::Stop(void)
+ {
+ ina = inb;
+ }
+
+ /** @brief Run method
+ *
+ * @param speed speed value
+ *
+ */
+ void VNH::Run(float speed)
+ {
+ Go(speed);
+ }
+
+ /** @brief Get current method
+ *
+ *
+ * \return Current value
+ */
+ float VNH::GetCurrent(void)
+ {
+ return (current.read()) * 5 / 0.14;
+ }
+
+ /** @brief Go method
+ *
+ * @param speed speed value
+ *
+ */
+ void VNH::Go(float speed)
+ {
+ //pwm.write(abs(speed));
+ if (speed < 0)
+ {
+ ina = 0;
+ inb = 1;
+ }
+ else
+ {
+ ina = 1;
+ inb = 0;
+ }
+ pwm =std::abs(speed);
+ }
+
+ /** @brief Inverse method
+ *
+ * @param f_speed speed value
+ *
+ */
+ void VNH::Inverse(float f_speed)
+ {
+ ina=!ina;
+ inb=!inb;
+ pwm =std::abs(f_speed);
+ }
+
+ /** @brief Brake method
+ *
+ *
+ *
+ */
+ void VNH::Brake()
+ {
+ ina.write(0);
+ inb.write(0);
+ pwm.write(100.0);
+ }
+
+}; // namespace drivers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Encoders/encoder.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,204 @@
+/**
+ ******************************************************************************
+ * @file Encoder.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementations for the encoder
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Encoders/encoder.hpp>
+
+/** \brief Constructor for the CCounter class
+ *
+ * Constructor method
+ *
+ * @param f_pin digital pin connected to encoder output
+ */
+CCounter::CCounter(PinName f_pin)
+ :m_interrupt(f_pin)
+ ,m_count(0)
+{
+ m_interrupt.rise(mbed::callback(CCounter::staticIncrement,this));
+ m_interrupt.fall(mbed::callback(CCounter::staticIncrement,this));
+}
+
+/** \brief Counter reset method
+ *
+ *
+ *
+ */
+void CCounter::reset(){
+ m_count=0;
+}
+
+/** \brief Counter increment method
+ *
+ *
+ *
+ */
+void CCounter::increment(){
+ m_count++;
+}
+
+/** \brief Get counts method
+ *
+ *
+ * @return counts
+ */
+int32_t CCounter::getCount(){
+ return m_count;
+}
+
+/** \brief Get counts method
+ *
+ * Method attaches the increment method to an object.
+ *
+ * @param obj object
+ *
+ */
+void CCounter::staticIncrement(void* obj){
+ CCounter* self=static_cast<CCounter*>(obj);
+ self->increment();
+}
+
+/** \brief Constructor for the CEncoder class
+ *
+ * Constructor method
+ *
+ * @param f_period period value
+ * @param f_period_sec period value in seconds
+ * @param f_cpr counts per revolution (rise and fall edges)
+ * @param f_pinName digital pin connected to encoder output
+ */
+CEncoder::CEncoder(uint32_t f_period
+ ,float f_period_sec
+ ,uint32_t f_cpr
+ ,PinName f_pinName)
+ :task::CTask(f_period)
+ ,m_counter(f_pinName)
+ ,m_period_sec(f_period_sec)
+ ,m_cpr(f_cpr)
+ ,m_rps(0)
+{
+}
+
+/** \brief Get rps method
+ *
+ * Returns the value of the rotations per second value
+ *
+ *
+ * @return rps
+ */
+float CEncoder::getSpeedRps()
+{
+ return m_rps;
+}
+
+/** \brief Get count
+ *
+ * Returns the value of the count
+ *
+ *
+ * @return rps
+ */
+int16_t CEncoder::getCount()
+{
+ return m_rps*m_period_sec*m_cpr;
+}
+
+
+
+/** \brief Run method
+ *
+ * Method executed at predefined time intervals.
+ * Method called each f_period
+ *
+ *
+ */
+void CEncoder::_run()
+{
+ float l_count=m_counter.getCount();
+ m_counter.reset();
+ m_rps=l_count/m_period_sec/m_cpr;
+}
+
+/** \brief Constructor for the CMagEncoderTime class
+ *
+ * Constructor method
+ *
+ * @param f_pin digital pin connected to encoder output
+ */
+CMagEncoderTime::CMagEncoderTime(PinName f_pin)
+ :m_interrupt(f_pin)
+{
+ m_interrupt.rise(mbed::callback(CMagEncoderTime::staticRise,this));
+ // m_interrupt.fall(mbed::callback(CMagEncoderTime::staticFall,this));
+ m_Timer.start();
+}
+
+/** \brief Callback method for rising edge interrupt
+ *
+ *
+ */
+void CMagEncoderTime::riseCallback()
+{
+ m_Timer.stop();
+ m_lowTime=m_Timer.read();
+ m_Timer.reset();
+ m_Timer.start();
+}
+
+/** \brief Callback method for rising edge interrupt
+ *
+ *
+ */
+void CMagEncoderTime::fallCallback()
+{
+ m_Timer.stop();
+ m_highTime=m_Timer.read();
+ m_Timer.reset();
+ m_Timer.start();
+}
+
+/** \brief Callback method for rising edge interrupt attached to pbject
+ *
+ * @param obj object
+ */
+void CMagEncoderTime::staticRise(void* obj)
+{
+ CMagEncoderTime* self=static_cast<CMagEncoderTime*>(obj);
+ self->riseCallback();
+}
+
+/** \brief Callback method for rising edge interrupt attached to pbject
+ *
+ * @param obj object
+ * @return None
+ */
+void CMagEncoderTime::staticFall(void* obj)
+{
+ CMagEncoderTime* self=static_cast<CMagEncoderTime*>(obj);
+ self->fallCallback();
+}
+
+/** \brief Callback method for rising edge interrupt
+ *
+ *
+ * @return High period value
+ */
+float CMagEncoderTime::getHighTime()
+{
+ return m_highTime;
+}
+
+/** \brief Callback method for rising edge interrupt
+ *
+ * @return Low period value
+ */
+float CMagEncoderTime::getLowTime()
+{
+ return m_lowTime;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Encoders/encoderFilter.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,66 @@
+/**
+ ******************************************************************************
+ * @file EncoderFilter.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the encoder filter
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Encoders/encoderFilter.hpp>
+
+/** \brief Constructor for the CEncoderFilter class
+ *
+ * Constructor method
+ *
+ * \param[in] f_period period value
+ * \param[in] f_period_sec period value in seconds
+ * \param[in] f_cpr counts per revolution (rise and fall edges)
+ * \param[in] f_pinName digital pin connected to encoder output
+ * \param[in] f_filter reference to filter object
+ */
+CEncoderFilter::CEncoderFilter(uint32_t f_period
+ ,float f_period_sec
+ ,uint32_t f_cpr
+ ,PinName f_pinName
+ ,CFilterFunction<float>& f_filter)
+ :CEncoder(f_period,f_period_sec,f_cpr,f_pinName)
+ ,m_filter(f_filter)
+{
+}
+
+/** \brief Get filtered rps value
+ *
+ * Method for getting filtererd rotations per second value
+ *
+ * \return filtered rps value
+ */
+float CEncoderFilter::getSpeedRps(){
+ return m_filteredRps;
+}
+
+/**
+ * @brief Getter filtered count value
+ *
+ * @return int16_t
+ */
+int16_t CEncoderFilter::getCount(){
+ return m_filteredRps*m_period_sec*m_cpr;
+}
+
+/** \brief Run method
+ *
+ * Method executed at predefined time intervals.
+ * Method called each f_period
+ *
+ */
+void CEncoderFilter::_run()
+{
+ float l_count=m_counter.getCount();
+ m_counter.reset();
+ m_rps=static_cast<float>(l_count)/m_period_sec/m_cpr;
+ m_filteredRps=m_filter(m_rps);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Encoders/quadratureencoder.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,111 @@
+/**
+ * @file quadratureencoder.cpp
+ * @author RBRO/PJ-IU
+ * @brief
+ * @version 0.1
+ * @date 2018-10-23
+ *
+ * @copyright Copyright (c) 2018
+ *
+ */
+#include <Encoders/Quadratureencoder.hpp>
+
+
+namespace encoders{
+
+
+
+CQuadratureEncoder_TIM4 *CQuadratureEncoder_TIM4::m_instance = 0;
+CQuadratureEncoder_TIM4::CQuadratureEncoder_TIM4_Destroyer CQuadratureEncoder_TIM4::m_destroyer;
+
+
+/**
+ * @brief Setter function.
+ *
+ * @param s singleton object address
+ */
+void CQuadratureEncoder_TIM4::CQuadratureEncoder_TIM4_Destroyer::SetSingleton(CQuadratureEncoder_TIM4* s){
+ m_singleton = s;
+}
+
+/**
+ * @brief Destroy the cQuadratureencoder tim4::cQuadratureencoder tim4 destroyer::cQuadratureencoder tim4 destroyer object
+ *
+ */
+CQuadratureEncoder_TIM4::CQuadratureEncoder_TIM4_Destroyer::~CQuadratureEncoder_TIM4_Destroyer(){
+ delete m_singleton;
+}
+
+
+/**
+ * @brief Constructor function. It verifies the existance of the singleton object and creates it.
+ *
+ * @return The address of the singleton object
+ */
+CQuadratureEncoder_TIM4* CQuadratureEncoder_TIM4::Instance(){
+ if(!CQuadratureEncoder_TIM4::m_instance){
+ CQuadratureEncoder_TIM4::m_instance = new CQuadratureEncoder_TIM4;
+ m_instance->initialize();
+ CQuadratureEncoder_TIM4::m_destroyer.SetSingleton(m_instance);
+ }
+ return CQuadratureEncoder_TIM4::m_instance;
+}
+
+
+/**
+ * @brief Initialize the parameter of the object.
+ *
+ */
+void CQuadratureEncoder_TIM4::initialize(){
+ //PB6 PB7 aka D10 MORPHO_PB7
+ // Enable clock for GPIOA
+ RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
+
+ //stm32f4xx.h
+ GPIOB->MODER |= GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1; //PB6 & PB7 as Alternate Function /*!< GPIO port mode register, Address offset: 0x00 */
+ GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; //PB6 & PB7 as Inputs /*!< GPIO port output type register, Address offset: 0x04 */
+ GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7; //Low speed /*!< GPIO port output speed register, Address offset: 0x08 */
+ GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_1 | GPIO_PUPDR_PUPDR7_1; //Pull Down /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
+ GPIOB->AFR[0] |= 0x22000000; //AF02 for PB6 & PB7 /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
+ GPIOB->AFR[1] |= 0x00000000; //nibbles here refer to gpio8..15 /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
+
+ // configure TIM4 as Encoder input
+ // Enable clock for TIM4
+ // __TIM4_CLK_ENABLE();
+ RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
+
+ TIM4->CR1 = 0x0001; // CEN(Counter ENable)='1' < TIM control register 1
+ TIM4->SMCR = TIM_ENCODERMODE_TI12; // < TIM slave mode control register
+ //TIM_ENCODERMODE_TI1 input 1 edges trigger count
+ //TIM_ENCODERMODE_TI2 input 2 edges trigger count
+ //TIM_ENCODERMODE_TI12 all edges trigger count
+ TIM4->CCMR1 = 0xF1F1; // CC1S='01' CC2S='01' < TIM capture/compare mode register 1
+ //0xF nibble sets up filter
+ TIM4->CCMR2 = 0x0000; // < TIM capture/compare mode register 2
+ TIM4->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; // < TIM capture/compare enable register
+ TIM4->PSC = 0x0000; // Prescaler = (0+1) < TIM prescaler
+ TIM4->ARR = 0xffff; // reload at 0xfffffff < TIM auto-reload register
+
+ TIM4->CNT = 0x0000; //reset the counter before we use it
+}
+/**
+ * @brief Get the position of encoder.
+ *
+ */
+int16_t CQuadratureEncoder_TIM4::getCount(){
+ if(m_instance){
+ return TIM4->CNT;
+ }
+ return 0xffff;
+}
+/**
+ * @brief Reset the value of the counter to zero value.
+ */
+void CQuadratureEncoder_TIM4::reset(){
+ if(m_instance){
+ TIM4->CNT = 0;
+ }
+}
+
+
+}; // namespace drivers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Encoders/quadratureencodertask.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,145 @@
+/**
+ * @file quadratureencodertask.cpp
+ * @author RBRO/PJ-IU
+ * @brief
+ * @version 0.1
+ * @date 2018-10-23
+ *
+ * @copyright Copyright (c) 2018
+ *
+ */
+#include <Encoders/Quadratureencodertask.hpp>
+
+
+namespace encoders{
+
+
+
+/**
+ * @brief Construct a new CQuadratureEncoderTask::CQuadratureEncoderTask object
+ *
+ * @param f_period_sec Period of the task
+ * @param f_Quadratureencoder The counter object
+ * @param f_resolution The resolution of the rotation encoder. (Cpr count per revolution)
+ */
+CQuadratureEncoderTask::CQuadratureEncoderTask( float f_period_sec
+ ,encoders::CQuadratureEncoder_TIMX* f_Quadratureencoder
+ ,uint16_t f_resolution)
+ :m_Quadratureencoder(f_Quadratureencoder)
+ ,m_taskperiod_s(f_period_sec)
+ ,m_resolution(f_resolution)
+ ,m_timer(mbed::callback(CQuadratureEncoderTask::static_callback,this))
+{
+}
+
+
+/**
+ * @brief Start the RosTimer to periodically apply the _run function.
+ *
+ */
+void CQuadratureEncoderTask::startTimer(){
+ m_timer.start(static_cast<int>(m_taskperiod_s*1000));
+}
+
+
+/**
+ * @brief The private run function, which will be applied periodically.
+ *
+ */
+void CQuadratureEncoderTask::_run(){
+ m_encoderCnt = m_Quadratureencoder->getCount();
+ m_Quadratureencoder->reset();
+}
+/**
+ * @brief Static callback function for applying the run function.
+ *
+ * @param obj CQuadratureEncoderTask object
+ */
+void CQuadratureEncoderTask::static_callback(void* obj){
+ CQuadratureEncoderTask* self = static_cast<CQuadratureEncoderTask*>(obj);
+ self->_run();
+}
+
+/**
+ * @brief Getter function for counted value.
+ *
+ * @return int16_t counted impulse
+ */
+int16_t CQuadratureEncoderTask::getCount(){
+ return m_encoderCnt;
+}
+/**
+ * @brief Getter function for the rotation per second
+ *
+ * @return rotation speed (rotation per second)
+ */
+
+float CQuadratureEncoderTask::getSpeedRps(){
+ return static_cast<float>(m_encoderCnt)/ m_resolution / m_taskperiod_s;
+}
+
+/**
+ * @brief Construct a new CQuadratureEncoderWithFilterTask::CQuadratureEncoderWithFilterTask object
+ *
+ * @param f_period_sec Period of the task
+ * @param f_Quadratureencoder The counter object
+ * @param f_resolution The resolution of the rotation encoder. (Cpr count per revolution)
+ * @param f_filter The reference to the filter.
+ */
+CQuadratureEncoderWithFilterTask::CQuadratureEncoderWithFilterTask( float f_period_sec
+ ,encoders::CQuadratureEncoder_TIMX* f_Quadratureencoder
+ ,uint16_t f_resolution
+ ,filter::CFilterFunction<float>& f_filter)
+ :CQuadratureEncoderTask(f_period_sec,f_Quadratureencoder,f_resolution)
+ ,m_filter(f_filter)
+ {
+}
+
+/**
+ * @brief Private run method for getting the value from the counter, reseting it. In the last step it filters the readed values.
+ *
+ */
+void CQuadratureEncoderWithFilterTask::_run(){
+ m_encoderCnt = m_Quadratureencoder->getCount();
+ m_Quadratureencoder->reset();
+ float temp = m_encoderCnt;
+ m_encoderCntFiltered = static_cast<int16_t>(m_filter(temp));
+
+}
+
+/**
+ * @brief Getter function for the last filtered value.
+ *
+ */
+int16_t CQuadratureEncoderWithFilterTask::getCount(){
+ return m_encoderCntFiltered;
+}
+
+/**
+ * @brief Getter function for the last filtered rotation speed.
+ *
+ */
+float CQuadratureEncoderWithFilterTask::getSpeedRps(){
+ return static_cast<double>(m_encoderCntFiltered)/m_resolution / m_taskperiod_s;
+
+}
+
+/**
+ * @brief Getter function for the last non-filtered value.
+ *
+ */
+int16_t CQuadratureEncoderWithFilterTask::getNonFilteredCount(){
+ return m_encoderCntFiltered;
+}
+
+/**
+ * @brief Getter function for the last non-filtered rotation speed.
+ *
+ */
+float CQuadratureEncoderWithFilterTask::getNonFilteredSpeedRps(){
+ return static_cast<double>(m_encoderCntFiltered)/m_resolution / m_taskperiod_s;
+
+}
+
+
+}; // namespace encoders
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Examples/Filter/ekf_am.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,30 @@
+/**
+ ******************************************************************************
+ * @file Ekf_am.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the Ackermann model example
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Examples/Filter/ekf_am.hpp>
+
+/** \brief Constructor for the CEKF_AM class
+ *
+ * Constructor method
+ *
+ * \param[in] f_ackermannModel reference to Ackermann model object
+ * \param[in] f_jacobianMatrixCalc Ackermann model Jacobian matrix
+ * \param[in] f_Q reference to transition type
+ * \param[in] f_R reference to observation noise type
+ */
+examples::filter::CEKF_AM::CEKF_AM(CAckermannModel& f_ackermannModel
+ ,CJMAckermannModel f_jacobianMatrixCalc
+ ,const CJMTransitionType& f_Q
+ ,const CObservationNoiseType& f_R)
+ :CEKF<double,2,10,5>(f_ackermannModel,f_jacobianMatrixCalc,f_Q,f_R)
+{
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Examples/Sensors/sensorpublisher.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,15 @@ +/** + ****************************************************************************** + * @file SensorPublisher.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-year + * @brief This file contains the class implementation for the sensor publisher + * functionality. Because template classes are used, the code was + * placed in a corresponding .inl file. + ****************************************************************************** + */ + +#include <Examples/Sensors/sensorpublisher.hpp> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Examples/Sensors/sensortask.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,115 @@
+/**
+ ******************************************************************************
+ * @file SensorTask.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the sensor task
+ * functionality.
+ ******************************************************************************
+ */
+#include <Examples/Sensors/sensortask.hpp>
+
+namespace examples
+{
+
+ namespace sensors{
+
+
+ /** \brief Constructor for the CCounter class
+ *
+ * Constructor method
+ *
+ * @param f_period period value
+ * @param f_serial reference to the serial object
+ */
+ CDISTFTest::CDISTFTest(uint32_t f_period
+ ,Serial& f_serial)
+ :task::CTask(f_period)
+ ,m_serial(f_serial)
+ ,m_tf()
+ {
+ std::array<std::array<float,1>,3> l_num({std::array<float,1>({3}),std::array<float,1>({-5.897}),std::array<float,1>({2.9})});
+ std::array<std::array<float,1>,3> l_den({std::array<float,1>({1}),std::array<float,1>({-1.949}),std::array<float,1>({0.9512})});
+ m_tf.setNum(l_num);
+ m_tf.setDen(l_den);
+ }
+
+ /** \brief Method called each f_period
+ *
+ *
+ *
+ */
+ void CDISTFTest::_run()
+ {
+ float l_input=1.0;
+ float l_output=m_tf(l_input);
+ m_serial.printf("%.4f\n",l_output);
+ }
+
+ /** \brief Constructor for the CCounter class
+ *
+ * Constructor method
+ *
+ * @param f_period period value
+ * @param f_encoder reference to encoder object
+ * @param f_serial reference to the serial object
+ */
+ CEncoderSender::CEncoderSender(uint32_t f_period
+ ,encoders::IEncoderGetter& f_encoder
+ ,Serial& f_serial)
+ :task::CTask(f_period)
+ ,m_isActived(false)
+ ,m_encoder(f_encoder)
+ ,m_serial(f_serial)
+ {
+ }
+
+ /** \brief Serial callback method
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+ void CEncoderSender::staticSerialCallback(void* obj,char const * a, char * b){
+ examples::sensors::CEncoderSender* self = static_cast<CEncoderSender*>(obj);
+ self->serialCallback(a,b);
+ }
+
+ /** \brief Serial callback actions
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+ void CEncoderSender::serialCallback(char const * a, char * b){
+ int l_isActivate=0;
+ uint32_t l_res = sscanf(a,"%d",&l_isActivate);
+ if(l_res==1){
+ m_isActived=(l_isActivate>=1);
+ sprintf(b,"ack;;");
+ }else{
+ sprintf(b,"sintax error;;");
+ }
+ }
+
+ /** \brief Method called each f_period
+ *
+ *
+ *
+ */
+ void CEncoderSender::_run()
+ {
+ if(!m_isActived) return;
+ float l_filtRps=m_encoder.getSpeedRps();
+ m_serial.printf("@ENPB:%.2f;;\r\n",l_filtRps);
+ }
+
+ }; // namespace sensors
+}; // namespace examples
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Examples/SystemModels/ackermannmodel.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,141 @@
+/**
+ ******************************************************************************
+ * @file AckermannModel.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the Ackermann model.
+ ******************************************************************************
+ */
+
+#include <Examples/SystemModels/ackermannmodel.hpp>
+
+/* Specify model type */
+using ackermannmodeltype = systemmodels::nlti::mimo::CDiscreteTimeSystemModel<double,2,10,5>;
+
+/** \brief Constructor for the CAckermannModel class
+ *
+ * Constructor method
+ *
+ * \param[in] f_states reference to initial system states
+ * \param[in] f_dt sample time
+ * \param[in] f_gamma reduction factor from motor to wheel
+ * \param[in] f_wb wheel base
+ * \param[in] f_b motor viscous friction constant
+ * \param[in] f_J moment of inertia of the rotor
+ * \param[in] f_K motor torque constant
+ * \param[in] f_R electric resistance
+ * \param[in] f_L electric inductance
+ *
+ */
+examples::systemmodels::ackermannmodel::CAckermannModel::CAckermannModel(
+ const CStatesType& f_states
+ ,const double f_dt
+ ,const double f_gamma
+ ,const double f_wb
+ ,const double f_b
+ ,const double f_J
+ ,const double f_K
+ ,const double f_R
+ ,const double f_L)
+ :CSystemModelType<double,2,10,5>(f_states,f_dt)
+ ,m_gamma(f_gamma)
+ ,m_wb(f_wb)
+ ,m_bJ(f_b/f_J)
+ ,m_KJ(f_K/f_J)
+ ,m_KL(f_K/f_L)
+ ,m_RL(f_R/f_L)
+ ,m_L(f_L)
+{
+}
+
+/** \brief Constructor for the CAckermannModel class
+ *
+ * Constructor method
+ *
+ * \param[in] f_dt sample time
+ * \param[in] f_gamma reduction factor from motor to wheel
+ * \param[in] f_wb wheel base
+ * \param[in] f_b motor viscous friction constant
+ * \param[in] f_J moment of inertia of the rotor
+ * \param[in] f_K motor torque constant
+ * \param[in] f_R electric resistance
+ * \param[in] f_L electric inductance
+ *
+ */
+examples::systemmodels::ackermannmodel::CAckermannModel::CAckermannModel(
+ const double f_dt
+ ,const double f_gamma
+ ,const double f_wb
+ ,const double f_b
+ ,const double f_J
+ ,const double f_K
+ ,const double f_R
+ ,const double f_L)
+ :CSystemModelType<double,2,10,5>(f_dt)
+ ,m_gamma(f_gamma)
+ ,m_wb(f_wb)
+ ,m_bJ(f_b/f_J)
+ ,m_KJ(f_K/f_J)
+ ,m_KL(f_K/f_L)
+ ,m_RL(f_R/f_L)
+ ,m_L(f_L)
+{
+}
+
+/** \brief Update method
+ *
+ * Method for updating system states.
+ *
+ * \param[in] f_input reference to input type object
+ * \return system states
+ */
+ackermannmodeltype::CStatesType
+ examples::systemmodels::ackermannmodel::CAckermannModel::update(
+ const CInputType& f_input)
+{
+ CState l_states=m_states;
+ CInput l_input=f_input;
+ l_states.x()+=m_dt*l_states.x_dot();
+ l_states.y()+=m_dt*l_states.y_dot();
+
+ l_states.x_dot_prev()=l_states.x_dot();
+ l_states.y_dot_prev()=l_states.y_dot();
+
+ l_states.x_dot()=m_gamma*l_states.omega()*cos(l_states.teta_rad());
+ l_states.y_dot()=m_gamma*l_states.omega()*sin(l_states.teta_rad());
+
+ double l_alpha_rad=l_input.alpha()*DEG2RAD;
+ l_states.teta_rad_dot()=m_gamma*l_states.omega()*tan(l_alpha_rad)/m_wb;
+ l_states.teta_rad()+=m_dt*l_states.teta_rad_dot();
+
+ double omega_k_1=(1-m_dt*m_bJ)*l_states.omega()+m_dt*m_KJ*l_states.i();//next state of the motor's rotation speed
+ l_states.i()=-1*m_dt*m_KL*l_states.omega()+(1-m_dt*m_RL)*l_states.i()+m_dt*l_input.v()/m_L;
+ l_states.omega()=omega_k_1;
+ m_states=l_states;
+ return l_states;
+}
+
+/** \brief Calculate output method
+ *
+ * Method for calculating output depending on input.
+ *
+ * \param[in] f_input reference to input type object
+ * \return systemoutputs
+ */
+ackermannmodeltype::COutputType
+ examples::systemmodels::ackermannmodel::CAckermannModel::calculateOutput(
+ const CInputType& f_input)
+{
+ CState l_states=m_states;
+ // CInput l_input=f_input;
+ COutput l_outputs(COutputType::zeros());
+ l_outputs.x_ddot()=l_states.x_dot()-l_states.x_dot_prev();
+ l_outputs.y_ddot()=l_states.y_dot()-l_states.y_dot_prev();
+ l_outputs.teta_rad_dot()=l_states.teta_rad_dot();
+ l_outputs.speed()=l_states.omega()*m_gamma;
+ // output.alpha()=f_input.alpha();
+ l_outputs.i()=l_states.i();
+ m_outputs=l_outputs;
+ return l_outputs;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Examples/blinker.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,38 @@
+/**
+ ******************************************************************************
+ * @file Blinker.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the blinker
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Examples/blinker.hpp>
+
+
+namespace examples{
+ /** \brief Class constructor
+ *
+ * Constructor method
+ *
+ * \param f_period LED toggling reading period
+ * \param f_led Digital output line to which the LED is connected
+ */
+ CBlinker::CBlinker(uint32_t f_period, DigitalOut f_led)
+ : task::CTask(f_period)
+ , m_led(f_led)
+ {
+ m_led = 1;
+ }
+
+ /** \brief Method called each f_period
+ *
+ */
+ void CBlinker::_run()
+ {
+ m_led = !m_led;
+ }
+
+}; // namespace examples
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Examples/echoer.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,36 @@
+/**
+ ******************************************************************************
+ * @file Echoer.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class implementation for the serial echoer
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <Examples/echoer.hpp>
+
+namespace examples{
+ /** \brief Class constructor
+ *
+ * Constructor method
+ *
+ * \param f_period echoer execution period
+ * \param f_serialPort Serial communication object
+ */
+ CEchoer::CEchoer(uint32_t f_period, Serial& f_serialPort)
+ : task::CTask(f_period)
+ , m_serialPort(f_serialPort)
+ {
+ }
+
+ /** \brief Method called each f_period
+ *
+ */
+ void CEchoer::_run()
+ {
+ m_serialPort.printf(".\n\r");
+ }
+
+}; // namespace examples
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Filter/filter.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,14 @@ +/** + ****************************************************************************** + * @file Filter.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-year + * @brief This file contains the class implementations for the filter + * functionality. Because tmeplates are used, an .inl file contains the + * actual implementation. + ****************************************************************************** + */ + +#include <Filter/filter.hpp> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Linalg/linalg.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,2 @@ +#include <Linalg/linalg.h> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/MotionController/motioncontroller.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,455 @@
+/**
+ ******************************************************************************
+ * @file MotionController.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the motion controller
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <MotionController/motioncontroller.hpp>
+
+
+/** \brief CMotionController Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_period_sec period for controller execution in seconds
+ * @param f_serialPort reference to serial communication object
+ * @param f_car reference to MOVE object
+ * @param f_safetyStop reference to spline safery stop object
+ * @param f_control reference to controller object
+ */
+CMotionController::CMotionController(
+ float f_period_sec,
+ Serial& f_serialPort,
+ Move& f_car,
+ CSafetyStopFunction* f_safetyStop,
+ controllers::CControllerSiso* f_control)
+ : m_serialPort(f_serialPort)
+ , m_car(f_car)
+ , m_speed()
+ , m_angle()
+ , m_period_sec(f_period_sec)
+ , m_isSplineActivated(false)
+ , m_ispidActivated(false)
+ , m_motionPlanner()
+ , m_hbTimeOut()
+ , m_control(f_control)
+ , m_safetyStop(f_safetyStop)
+ , m_timer(mbed::callback(CMotionController::staticCallbackRun,this))
+{
+}
+
+
+/** \brief CMotionController Class constructor
+ *
+ * Constructor method
+ *
+ * @param f_period_sec period for controller execution in seconds
+ * @param f_serialPort reference to serial communication object
+ * @param f_car reference to MOVE object
+ * @param f_control reference to controller object
+ */
+CMotionController::CMotionController(
+ float f_period_sec,
+ Serial& f_serialPort,
+ Move& f_car,
+ controllers::CControllerSiso* f_control)
+ : m_serialPort(f_serialPort)
+ , m_car(f_car)
+ , m_speed()
+ , m_angle()
+ , m_period_sec(f_period_sec)
+ , m_isSplineActivated(false)
+ , m_ispidActivated(false)
+ , m_motionPlanner()
+ , m_hbTimeOut()
+ , m_control(f_control)
+ , m_safetyStop(NULL)
+ , m_timer(mbed::callback(CMotionController::staticCallbackRun,this))
+{
+}
+
+/** \brief Serial callback method
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::staticSerialCallbackMove(void* obj,char const * a, char * b)
+{
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->serialCallbackMove(a,b);
+}
+
+/** \brief Serial callback method for BRAKE command
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::staticSerialCallbackBrake(void* obj,char const * a, char * b)
+{
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->serialCallbackBrake(a,b);
+}
+
+/** \brief Serial callback method for hard BRAKE command
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::staticSerialCallbackHardBrake(void* obj,char const * a, char * b)
+{
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->serialCallbackHardBrake(a,b);
+}
+
+/** \brief Serial callback method for PID activation command
+ *
+ * Serial callback attaching serial callback to controller object
+ *
+ * @param obj PID controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::staticSerialCallbackPID(void* obj,char const * a, char * b)
+{
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->serialCallbackPID(a,b);
+}
+
+/**
+ * @brief Static seriel callback for spline command
+ *
+ * @param obj object with the serial callback method
+ * @param a string to read data from
+ * @param b string to write data to
+ */
+void CMotionController::staticSerialCallbackSpline(void* obj, char const * a,char * b){
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->serialCallbackSpline(a,b);
+}
+
+/** \brief Reset method
+ *
+ *
+ *
+ */
+void CMotionController::reset()
+{
+ m_speed = 0;
+ m_angle = 0;
+}
+
+/** \brief Get speed method
+ *
+ *
+ * \return Speed
+ */
+float CMotionController::getSpeed()
+{
+ return m_speed;
+}
+
+/** \brief Get angle method
+ *
+ *
+ * \return Angle
+ */
+float CMotionController::getAngle()
+{
+ return m_angle;
+}
+
+/** \brief BrakeCallback method
+ *
+ *
+ *
+ */
+void CMotionController::BrakeCallback(){
+ m_state=2;
+}
+
+/** \brief Set state method
+ *
+ * @param f_state
+ *
+ */
+void CMotionController::setState(int f_state){
+ m_state = f_state;
+}
+
+/** \brief Method called each f_period
+ *
+ *
+ *
+ */
+void CMotionController::_run()
+{
+ if(m_isSplineActivated)
+ {
+ if(m_motionPlanner.hasValidValue())
+ {
+ std::pair<float,float> motion=m_motionPlanner.getNextVelocity();
+ float l_dir=m_motionPlanner.getForward()?1:-1;
+ if(m_ispidActivated)
+ {
+ m_speed=motion.first*l_dir;
+ m_angle=motion.second;
+ }
+ else
+ {
+ //Pid isn't activated. It have to controllered with the robot speed value in meter per second.
+ m_serialPort.printf("@SPLN:Err1;;\r\n");
+ m_state=2;
+ m_isSplineActivated=false;
+ m_speed=0.0;
+ }
+ }
+ else
+ {
+ m_serialPort.printf("@SPLN:Stop;;\r\n");
+ m_speed=0.0;
+ m_state=2;
+ m_isSplineActivated=false;
+ }
+ }
+
+ //safety stop function
+ /**
+ * @brief It's a part of safety stop functionilty. Check if it's actived or created.
+ *
+ */
+ if ((m_state!=2)&&(m_safetyStop!=NULL && m_safetyStop->isSafetyStopActive(m_speed,m_angle)==true))
+ {
+ m_state = 2;
+ }
+
+ switch(m_state)
+ {
+ // Move
+ case 1:
+ m_car.Steer(m_angle);
+ if(m_ispidActivated && m_control!=NULL)
+ {
+ m_control->setRef(CMotionController::Mps2Rps( m_speed ));
+ m_serialPort.printf("%f",CMotionController::Mps2Rps( m_speed ));
+ // Calculate control signal
+ bool l_isCorrect = m_control->control();
+ // Check the correct working of the control method
+ if( !l_isCorrect ){
+ m_car.Brake();
+ m_control->clear();
+ m_state = 2;
+ }
+ m_car.Speed(m_control->get()*100.0);//Y
+ }
+ else
+ {
+ m_car.Speed(m_speed);
+ }
+ break;
+ // Brake
+ case 2:
+ m_car.Steer(m_angle);
+ m_car.Brake();
+ if( m_control!=NULL){
+ m_control->clear();
+ }
+ break;
+ }
+
+}
+
+/** \brief Serial callback actions for MOVE command
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::serialCallbackMove(char const * a, char * b)
+{
+ float l_speed;
+ float l_angle;
+ uint32_t l_res = sscanf(a,"%f;%f",&l_speed,&l_angle);
+ if (2 == l_res)
+ {
+ if( !m_ispidActivated && std::abs(l_speed) > MCTL_PWM_COMMAND_LIMIT ){
+ sprintf(b,"Command is too high;;");
+ return;
+ }if( m_ispidActivated && std::abs(l_speed) > MCTL_SPEED_COMMAND_LIMIT ){
+ sprintf(b,"Command is too high;;");
+ return;
+ }
+
+ m_speed = l_speed;
+ m_angle = l_angle;
+ m_isSplineActivated=false;
+ m_state=1;
+ sprintf(b,"ack;;");
+ }
+ else
+ {
+ sprintf(b,"sintax error;;");
+ }
+}
+
+/** \brief Serial callback actions for BRAKE command
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::serialCallbackBrake(char const * a, char * b)
+{
+ float l_angle;
+ uint32_t l_res = sscanf(a,"%f",&l_angle);
+ if(1 == l_res)
+ {
+ m_speed = 0;
+ m_angle = l_angle;
+ m_state = 2;
+ if( m_control!=NULL){
+ m_control->setRef(0);
+ }
+
+ sprintf(b,"ack;;");
+ }
+ else
+ {
+ sprintf(b,"sintax error;;");
+ }
+}
+
+/** \brief Serial callback actions for hard BRAKE command
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::serialCallbackHardBrake(char const * a, char * b)
+{
+ float l_brake,l_angle;
+ uint32_t l_res = sscanf(a,"%f;%f",&l_brake,&l_angle);
+ if(2 == l_res && m_state!=0)
+ {
+ m_speed=0;
+ m_angle = l_angle;
+ m_car.Inverse(l_brake);
+ m_hbTimeOut.attach(callback(this,&CMotionController::BrakeCallback),0.04);
+ m_state = 0;
+ sprintf(b,"ack;;");
+ }
+ else
+ {
+ sprintf(b,"sintax error;;");
+ }
+}
+
+/** \brief Serial callback actions for hard PID activation command
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CMotionController::serialCallbackPID(char const * a, char * b)
+{
+ int l_isActivate=0;
+ uint32_t l_res = sscanf(a,"%d",&l_isActivate);
+ if(l_res==1)
+ {
+ if(m_control==NULL){
+ sprintf(b,"Control object wans't instances. Cannot be activate pid controller;;");
+ }else{
+ m_ispidActivated=(l_isActivate>=1);
+ m_state = 2;
+ sprintf(b,"ack;;");
+ }
+
+ }else
+ {
+ sprintf(b,"sintax error;;");
+ }
+}
+
+/**
+ * @brief Serial callback actions for bezier spline command
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ */
+void CMotionController::serialCallbackSpline(char const * a, char * b){
+ float a_x,a_y,b_x,b_y,c_x,c_y,d_x,d_y,duration_sec;
+ int isForward=1;
+ int32_t nrData=sscanf(a,"%d;%f;%f;%f;%f;%f;%f;%f;%f;%f",
+ &isForward,
+ &a_x,
+ &a_y,
+ &b_x,
+ &b_y,
+ &c_x,
+ &c_y,
+ &d_x,
+ &d_y,
+ &duration_sec);
+ if(10==nrData && duration_sec>0 && (isForward==1 || isForward==0)){
+ m_motionPlanner.setMotionPlannerParameters(static_cast<bool>(isForward), std::complex<float>(a_x,a_y),std::complex<float>(b_x,b_y),std::complex<float>(c_x,c_y),std::complex<float>(d_x,d_y),duration_sec,m_period_sec);
+ m_isSplineActivated=true;
+ m_state=1;
+ sprintf(b,"ack;;");
+ }else{
+ sprintf(b,"sintax error;;");
+ }
+}
+
+
+/**
+ * @brief Function to convert from linear velocity ( centimeter per second ) of robot to angular velocity ( rotation per second ) of motor.
+ *
+ * @param f_vel_mps linear velocity
+ * @return float angular velocity
+ */
+float CMotionController::Mps2Rps(float f_vel_mps){
+ return f_vel_mps * 150.0;
+}
+
+/**
+ * @brief Static callback function for run method
+ *
+ * @param obj pointer for the object
+ */
+void CMotionController::staticCallbackRun(void* obj){
+ CMotionController* self = static_cast<CMotionController*>(obj);
+ self->_run();
+}
+
+/**
+ * @brief Start RtosTimer, which periodically apply the run method. The period of the task is defined in the contructor.
+ *
+ */
+void CMotionController::startRtosTimer(){
+ this->m_timer.start(static_cast<int>(m_period_sec*1000));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Move/move.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,134 @@
+/**
+ ******************************************************************************
+ * @file Move.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-year
+ * @brief This file contains the class definition for the moving
+ * functionality.
+ ******************************************************************************
+ */
+
+#include "mbed.h"
+#include <Move/move.hpp>
+//#include <array.h>
+
+/** \brief Move Class constructor
+ *
+ * Constructor method
+ *
+ * @param _pwm_servo
+ * @param _pwm_driver
+ * @param _ina_driver
+ * @param _inb_driver
+ * @param _current_driver
+ */
+Move::Move(
+ PinName _pwm_servo,
+ PinName _pwm_driver,
+ PinName _ina_driver,
+ PinName _inb_driver,
+ PinName _current_driver)
+ :servo(_pwm_servo),
+ vnh(_pwm_driver,_ina_driver,_inb_driver,_current_driver)
+{
+};
+
+/** \brief Move Class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+Move::~Move()
+{
+};
+
+/** \brief Steer method
+ *
+ * @param angle
+ *
+ */
+void Move::Steer(float angle)
+{
+ if ((angle <= 23) && (angle >= -23))
+ servo.SetAngle(angle);
+};
+
+/** \brief Move method
+ *
+ * @param speed The Pwm value, must belong to [0,100].
+ *
+ */
+void Move::Speed(float speed)
+{
+ speed /=100;
+ vnh.Run(speed);
+};
+
+/** \brief Brake method
+ *
+ *
+ *
+ */
+void Move::Brake()
+{
+ vnh.Brake();
+}
+
+/** \brief Hard brake method
+ *
+ * @param f_speed The Pwm value, must belong to [0,100].
+ *
+ */
+void Move::Inverse(float f_speed)
+{
+ f_speed /=100;
+ vnh.Inverse(f_speed);
+}
+
+/** \brief Car testing method
+ *
+ *
+ *
+ */
+void Move::TestCar()
+{
+ Steer(20);
+ wait(1);
+ Steer(0);
+ wait(1);
+ Steer(-20);
+ wait(1);
+ ResetCar();
+ wait(1);
+ Speed(25);
+ wait(1);
+ Speed(0);
+ wait(1);
+ Speed(-25);
+ wait(1);
+ ResetCar();
+ wait(1);
+};
+
+/** \brief Reset speed and steer method
+ *
+ *
+ *
+ */
+void Move::ResetCar()
+{
+ Steer(0);
+ Speed(0);
+};
+
+/** \brief Get bridge (driver) object reference method
+ *
+ *
+ * @return reference to VNH object
+ */
+drivers::VNH& Move::getVNH()
+{
+ return vnh;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Queue/queue.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,12 @@ +/** + ****************************************************************************** + * @file Queue.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-year + * @brief This file contains the class definition for the queue + * functionality. + ****************************************************************************** + */ + +#include <Queue/queue.hpp>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SHARP_IR_distance/DistanceSensors/distancesensors.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,13 @@ +/** + ****************************************************************************** + * @file DistanceSensors.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date 08-January-2018 + * @brief This file contains the class implementation for the distance sensors + * read methods. + ****************************************************************************** + */ + +#include <SHARP_IR_distance\DistanceSensors\distancesensors.hpp> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/SHARP_IR_distance/IR_DistanceSensorDriver/ir_distancesensordriver.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,91 @@
+/**
+ ******************************************************************************
+ * @file IR_DistanceSensorDriver.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date 08-January-2018
+ * @brief This file contains the class implementation for the SHARP IR sensor read
+ * methods.
+ ******************************************************************************
+ */
+
+#include <SHARP_IR_distance\IR_DistanceSensorDriver\ir_distancesensordriver.hpp>
+
+/**
+ * @brief Construct a new c ir distancesensordriver::c ir distancesensordriver object
+ *
+ * @param _ain_pin analog entrance pin
+ * @param _en_pin digital enable pin
+ */
+C_IR_DistanceSensorDriver::C_IR_DistanceSensorDriver(AnalogIn _ain_pin, DigitalOut _en_pin)
+ : ain_pin(_ain_pin)
+ , en_pin(_en_pin)
+ , value(0)
+{
+};
+
+/** @brief Class destructor
+
+ Destructor method
+ */
+C_IR_DistanceSensorDriver::~C_IR_DistanceSensorDriver()
+{
+};
+
+/** @brief Method for enabling sensor
+
+
+
+ */
+void C_IR_DistanceSensorDriver::enable(){
+ en_pin=1;
+}
+
+/** @brief Method for disabling sensor
+
+
+
+ */
+void C_IR_DistanceSensorDriver::disable(){
+ en_pin=0;
+}
+/*
+void C_IR_DistanceSensorDriver::setValue(float val){
+ this->value=val;
+}
+*/
+
+/** @brief Method for getting value read from sensor
+
+
+ @return value read from sensor
+ */
+float C_IR_DistanceSensorDriver::getValue(){
+ return this->value;
+}
+
+/** @brief Method for getting scaled value read from sensor
+
+
+ @return scaled value read from sensor
+ */
+float C_IR_DistanceSensorDriver::ReadDistance()
+{
+ // read only if sensor enabled
+ if (this->en_pin == 1){
+ //read analog pin
+ float current_value=ain_pin.read();
+ //-scaling
+ float scaled_value = C_IR_DistanceSensorDriver_A * pow(current_value,5)
+ + C_IR_DistanceSensorDriver_B * pow(current_value,4)
+ + C_IR_DistanceSensorDriver_C * pow(current_value,3)
+ + C_IR_DistanceSensorDriver_D * pow(current_value,2)
+ + C_IR_DistanceSensorDriver_E * current_value
+ + C_IR_DistanceSensorDriver_F;
+
+ //float scaled_value=current_value; // without scaling, gross signal
+ this->value=scaled_value;
+ return this->value;
+ }
+ else return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/SafetyStop/safetystopfunction.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,135 @@
+/**
+ ******************************************************************************
+ * @file SafetyStopFunction.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for the safety stop activation
+ * methods.
+ ******************************************************************************
+ */
+
+#include <SafetyStop/safetystopfunction.hpp>
+
+
+/**
+ * @brief Construct a new CSafetyStopFunction::CSafetyStopFunction object
+ *
+ * @param f_senLeftFront sensor mounteed on left front part
+ * @param f_senMidLeftFront sensor mounteed on mid left front part
+ * @param f_senCenterFront sensor mounted on middle front part
+ * @param f_senMidRightFront sensor mounteed on mid right front part
+ * @param f_senRightFront sensor mounteed on right front part
+ */
+CSafetyStopFunction::CSafetyStopFunction(
+ C_IR_DistanceSensorDriver& f_senLeftFront
+ , C_IR_DistanceSensorDriver& f_senMidLeftFront
+ , C_IR_DistanceSensorDriver& f_senCenterFront
+ , C_IR_DistanceSensorDriver& f_senMidRightFront
+ , C_IR_DistanceSensorDriver& f_senRightFront
+ // , C_IR_DistanceSensorDriver& f_senLeftBack
+ // , C_IR_DistanceSensorDriver& f_senRightBack
+ )
+ : m_active(false)
+ ,m_speed(0)
+ , m_angle(0)
+ , m_senLeftFront(f_senLeftFront)
+ , m_senMidLeftFront(f_senMidLeftFront)
+ , m_senCenterFront(f_senCenterFront)
+ , m_senMidRightFront(f_senMidRightFront)
+ , m_senRightFront(f_senRightFront)
+ // , m_senLeftBach(f_senLeftBack)
+ // , m_senRightBach(f_senRightBack)
+{
+}
+
+/** @brief Class destructor
+ *
+ * Destructor method
+ */
+CSafetyStopFunction::~CSafetyStopFunction()
+{}
+
+/** @brief Function for activating safety stop
+ *
+ * @param f_speed
+ * @param f_angle
+ */
+bool CSafetyStopFunction::isSafetyStopActive(float f_speed, float f_angle){
+ // Verification the state of the functionality
+ if(!this->m_active){
+ // Inactive -> no need to brake
+ return false;
+ }
+ // Get current speed
+ m_speed = f_speed;
+ // Get current angle
+ m_angle = f_angle;
+ // Value indicating whether brake should be activated
+ bool ret_val =false;
+ // dyunamic threshold for activating brake
+ float threshold;
+ // If moving forward take into account only front sensors
+ if (m_speed > 0)
+ {
+ threshold = m_speed*5-(1/m_speed)*10;
+ if ((m_senLeftFront.getValue() <= threshold) ||
+ (m_senMidLeftFront.getValue() <= threshold) ||
+ (m_senCenterFront.getValue() <= threshold) ||
+ (m_senMidRightFront.getValue() <= threshold) ||
+ (m_senRightFront.getValue() <= threshold) )
+ {
+ ret_val = true;
+ }
+ }
+ // If moving forward take into account only front sensors
+ // Uncomment next if clause only if back sensors are being mounted
+ // else if (m_speed < 0)
+ // {
+ // threshold = m_speed*8+(1/m_speed)*10;
+ // if ( (m_senLeftBach.getDistance() <= threshold*(-1)) || (m_senRightBach.getDistance() <= threshold*(-1)) )
+ // {
+ // ret_val = true;
+ // }
+ // }
+
+ // Return value indicating whether brake should be activated
+ return ret_val;
+}
+
+/** @brief Serial callback method
+ *
+ * Serial callback attaching serial callback to CSafetyStopFunction object
+ *
+ * @param obj CSafetyStopFunction controller object
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CSafetyStopFunction::staticSerialCallback(void* obj,char const * a, char * b)
+{
+ CSafetyStopFunction* self = static_cast<CSafetyStopFunction*>(obj);
+ self->serialCallback(a,b);
+}
+
+/** @brief Serial callback actions
+ *
+ * Serial callback method setting controller to values received
+ *
+ * @param a string to read data from
+ * @param b string to write data to
+ *
+ */
+void CSafetyStopFunction::serialCallback(char const * a, char * b){
+ int l_isActivate=0;
+ uint32_t l_res= sscanf(a,"%d",&l_isActivate);
+ if(l_res==1){
+ m_active=(l_isActivate>=1);
+ sprintf(b,"ack;;");
+ }else{
+ sprintf(b,"sintax error;;");
+ }
+ }
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/SerialMonitor/serialmonitor.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,139 @@
+/**
+ ******************************************************************************
+ * @file SerialMonitor.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for the serial communication
+ * functionality.
+ ******************************************************************************
+ */
+
+#include <SerialMonitor/serialmonitor.hpp>
+
+
+namespace serial{
+
+ /** @brief CSerialMonitor class constructor
+ *
+ *
+ * @param f_serialPort reference to serial object
+ * @param f_serialSubscriberMap sensor mounteed on left front part
+ */
+ CSerialMonitor::CSerialMonitor(Serial& f_serialPort
+ ,CSerialSubscriberMap f_serialSubscriberMap)
+ :task::CTask(0)
+ , m_serialPort(f_serialPort)
+ , m_RxBuffer()
+ , m_TxBuffer()
+ , m_parseBuffer()
+ , m_parseIt(m_parseBuffer.begin())
+ , m_serialSubscriberMap(f_serialSubscriberMap)
+ {
+ m_serialPort.attach(mbed::callback(&CSerialMonitor::RxCallback, this), Serial::RxIrq);
+ m_serialPort.attach(mbed::callback(&CSerialMonitor::TxCallback, this), Serial::TxIrq);
+ }
+
+ /** @brief Rx callback
+ *
+ * @param thisPointer the object pointer
+ *
+ */
+ void CSerialMonitor::RxCallback(void *thisPointer)
+ {
+ CSerialMonitor* self = static_cast<CSerialMonitor*>(thisPointer);
+ self->serialRxCallback();
+ }
+
+ /** @brief Tx callback
+ *
+ * @param thisPointer the object pointer
+ *
+ */
+ void CSerialMonitor::TxCallback(void *thisPointer)
+ {
+ CSerialMonitor* self = static_cast<CSerialMonitor*>(thisPointer);
+ self->serialTxCallback();
+ }
+
+ /** @brief Rx callback actions
+ *
+ * @param None
+ *
+ */
+ void CSerialMonitor::serialRxCallback()
+ {
+ __disable_irq();
+ while ((m_serialPort.readable()) && (!m_RxBuffer.isFull())) {
+ char l_c = m_serialPort.getc();
+ m_RxBuffer.push(l_c);
+ }
+ __enable_irq();
+ return;
+ }
+
+ /** @brief Tx callback actions
+ *
+ * @param None
+ *
+ */
+ void CSerialMonitor::serialTxCallback()
+ {
+ __disable_irq();
+ while ((m_serialPort.writeable()) && (!m_TxBuffer.isEmpty())) {
+ m_serialPort.putc(m_TxBuffer.pop());
+ }
+ __enable_irq();
+ return;
+ }
+
+ /** @brief Run method
+ *
+ * @param None
+ * @param None
+ */
+ void CSerialMonitor::_run()
+ {
+ if ((!m_RxBuffer.isEmpty()))
+ {
+ char l_c = m_RxBuffer.pop();
+ // m_serialPort.printf("%c",l_c);
+ if ('#' == l_c)
+ {
+ m_parseIt = m_parseBuffer.begin();
+ m_parseIt[0] = l_c;
+ m_parseIt++;
+ return;
+ }
+ if (m_parseIt != m_parseBuffer.end())
+ {
+ if (l_c == '\n')
+ {
+ if ((';' == m_parseIt[-3]) && (';' == m_parseIt[-2]) && ('\r' == m_parseIt[-1]))
+ {
+ char l_msgID[5];
+ char l_msg[256];
+
+ uint32_t res = sscanf(m_parseBuffer.data(),"#%4s:%s;;",l_msgID,l_msg);
+ if (res == 2)
+ {
+ auto l_pair = m_serialSubscriberMap.find(l_msgID);
+ if (l_pair != m_serialSubscriberMap.end())
+ {
+ char l_resp[256] = "no response given";
+ string s(l_resp);
+ l_pair->second(l_msg,l_resp);
+ m_serialPort.printf("@%s:%s\r\n",l_msgID,l_resp);
+ }
+ }
+ m_parseIt = m_parseBuffer.begin();
+ }
+ }
+ m_parseIt[0] = l_c;
+ m_parseIt++;
+ return;
+ }
+ }
+ }
+
+}; // namespace serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SystemModels/systemmodels.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,11 @@ +/** + ****************************************************************************** + * @file SystemModels.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-2017 + * @brief This file contains the class definitions for system model. + ****************************************************************************** + */ + +#include <SystemModels/systemmodels.hpp>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/TaskManager/taskmanager.cpp Thu Mar 28 07:44:42 2019 +0000
@@ -0,0 +1,92 @@
+/**
+ ******************************************************************************
+ * @file TaskManager.cpp
+ * @author RBRO/PJ-IU
+ * @version V1.0.0
+ * @date day-month-2017
+ * @brief This file contains the class definition for task manager.
+ ******************************************************************************
+ */
+
+#include <TaskManager/taskmanager.hpp>
+
+namespace task{
+
+ /******************************************************************************/
+ /** \brief CTask class constructor
+ *
+ * Constructor method
+ *
+ * @param f_period execution period
+ */
+ CTask::CTask(uint32_t f_period)
+ : m_period(f_period)
+ , m_ticks(0)
+ , m_triggered(false)
+ {
+ }
+
+ /** \brief CTask class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+ CTask::~CTask()
+ {
+ }
+
+ /** \brief Run method
+ *
+ * Destructor method
+ *
+ *
+ *
+ */
+ void CTask::run()
+ {
+ if (m_triggered)
+ {
+ m_triggered = false;
+ _run();
+ }
+ }
+
+ /******************************************************************************/
+ /** \brief CTaskManager class constructor
+ *
+ * Constructor method
+ *
+ * @param f_taskList task list
+ * @param f_taskCount task count
+ * @param f_baseFreq base frequency
+ */
+ CTaskManager::CTaskManager(task::CTask** f_taskList, uint32_t f_taskCount, float f_baseFreq)
+ : m_taskList(f_taskList)
+ , m_taskCount(f_taskCount)
+ {
+ m_ticker.attach(mbed::callback(&task::CTaskManager::callback, this), f_baseFreq);
+ }
+
+ /** \brief CTaskManager class destructor
+ *
+ * Destructor method
+ *
+ *
+ */
+ CTaskManager::~CTaskManager()
+ {
+ m_ticker.detach();
+ }
+
+ /** \brief Callback method
+ *
+ * @param thisPointer The object pointer
+ */
+ void CTaskManager::callback(void *thisPointer)
+ {
+ task::CTaskManager* self = static_cast<task::CTaskManager*>(thisPointer);
+ self->timerCallback();
+ }
+
+}; // namespace task
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Timer/timer.cpp Thu Mar 28 07:44:42 2019 +0000 @@ -0,0 +1,11 @@ +/** + ****************************************************************************** + * @file Timer.cpp + * @author RBRO/PJ-IU + * @version V1.0.0 + * @date day-month-2017 + * @brief This file contains the class definition for the timer functionality. + ****************************************************************************** + */ + +#include <Timer/timer.hpp>