Example project

Dependencies:   PM2_Libary Eigen

Files at this revision

API Documentation at this revision

Comitter:
pmic
Date:
Sat May 14 15:27:12 2022 +0200
Parent:
41:7484471403aa
Child:
43:0a124a21e227
Commit message:
Working solution, only mbed update left

Changed in this revision

Controller.cpp Show diff for this revision Revisions of this file
Controller.h Show diff for this revision Revisions of this file
EncoderCounterROME2.cpp Show diff for this revision Revisions of this file
EncoderCounterROME2.h Show diff for this revision Revisions of this file
IRSensor.cpp Show annotated file Show diff for this revision Revisions of this file
IRSensor.h Show annotated file Show diff for this revision Revisions of this file
Motion.cpp Show diff for this revision Revisions of this file
Motion.h Show diff for this revision Revisions of this file
PM2_Libary.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/Controller.cpp	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Controller.cpp
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#include "Controller.h"
-
-using namespace std;
-
-const float Controller::PERIOD = 0.001f;                    // period of control task, given in [s]
-const float Controller::M_PI = 3.14159265f;                 // the mathematical constant PI
-const float Controller::WHEEL_DISTANCE = 0.190f;            // distance between wheels, given in [m]
-const float Controller::WHEEL_RADIUS = 0.0375f;             // radius of wheels, given in [m]
-const float Controller::MAXIMUM_VELOCITY = 500.0;           // maximum wheel velocity, given in [rpm]
-const float Controller::MAXIMUM_ACCELERATION = 1000.0;       // maximum wheel acceleration, given in [rpm/s]
-const float Controller::COUNTS_PER_TURN = 1200.0f;          // encoder resolution (pololu motors: 1200.0f, maxon motors: 86016.0f)
-const float Controller::LOWPASS_FILTER_FREQUENCY = 300.0f;  // given in [rad/s]
-const float Controller::KN = 40.0f;                         // speed constant in [rpm/V] (pololu motors: 40.0f, maxon motors: 45.0f)
-const float Controller::KP = 0.15f;                         // speed control parameter
-const float Controller::MAX_VOLTAGE = 12.0f;                // battery voltage in [V]
-const float Controller::MIN_DUTY_CYCLE = 0.02f;             // minimum duty-cycle
-const float Controller::MAX_DUTY_CYCLE = 0.98f;             // maximum duty-cycle
-
-/**
- * Creates and initialises the robot controller.
- * @param pwmLeft a reference to the pwm output for the left motor.
- * @param pwmRight a reference to the pwm output for the right motor.
- * @param counterLeft a reference to the encoder counter of the left motor.
- * @param counterRight a reference to the encoder counter of the right motor.
- */
-Controller::Controller(PwmOut& pwmLeft, PwmOut& pwmRight, EncoderCounterROME2& counterLeft, EncoderCounterROME2& counterRight) : pwmLeft(pwmLeft), pwmRight(pwmRight), counterLeft(counterLeft), counterRight(counterRight), thread(osPriorityHigh, STACK_SIZE) {
-    
-    // initialise pwm outputs
-
-    pwmLeft.period(0.00005f);  // pwm period of 50 us
-    pwmLeft = 0.5f;            // duty-cycle of 50%
-
-    pwmRight.period(0.00005f); // pwm period of 50 us
-    pwmRight = 0.5f;           // duty-cycle of 50%
-
-    // initialise local variables
-
-    translationalVelocity = 0.0f;
-    rotationalVelocity = 0.0f;
-
-    actualTranslationalVelocity = 0.0f;
-    actualRotationalVelocity = 0.0f;
-
-    desiredSpeedLeft = 0.0f;
-    desiredSpeedRight = 0.0f;
-
-    actualSpeedLeft = 0.0f;
-    actualSpeedRight = 0.0f;
-
-    motionLeft.setProfileVelocity(MAXIMUM_VELOCITY);
-    motionLeft.setProfileAcceleration(MAXIMUM_ACCELERATION);
-    motionLeft.setProfileDeceleration(MAXIMUM_ACCELERATION);
-
-    motionRight.setProfileVelocity(MAXIMUM_VELOCITY);
-    motionRight.setProfileAcceleration(MAXIMUM_ACCELERATION);
-    motionRight.setProfileDeceleration(MAXIMUM_ACCELERATION);
-
-    previousValueCounterLeft = counterLeft.read();
-    previousValueCounterRight = counterRight.read();
-
-    speedLeftFilter.setPeriod(PERIOD);
-    speedLeftFilter.setFrequency(LOWPASS_FILTER_FREQUENCY);
-
-    speedRightFilter.setPeriod(PERIOD);
-    speedRightFilter.setFrequency(LOWPASS_FILTER_FREQUENCY);
-
-    // start thread and timer interrupt
-    
-    thread.start(callback(this, &Controller::run));
-    ticker.attach(callback(this, &Controller::sendThreadFlag), std::chrono::microseconds{static_cast<long int>(1.0e6f * PERIOD)});
-}
-
-/**
- * Deletes this Controller object.
- */
-Controller::~Controller() {
-    
-    ticker.detach(); // stop the timer interrupt
-}
-
-/**
- * Sets the desired translational velocity of the robot.
- * @param velocity the desired translational velocity, given in [m/s].
- */
-void Controller::setTranslationalVelocity(float velocity) {
-    
-    this->translationalVelocity = velocity;
-}
-
-/**
- * Sets the desired rotational velocity of the robot.
- * @param velocity the desired rotational velocity, given in [rad/s].
- */
-void Controller::setRotationalVelocity(float velocity) {
-    
-    this->rotationalVelocity = velocity;
-}
-
-/**
- * Gets the actual translational velocity of the robot.
- * @return the actual translational velocity, given in [m/s].
- */
-float Controller::getActualTranslationalVelocity() {
-    
-    return actualTranslationalVelocity;
-}
-
-/**
- * Gets the actual rotational velocity of the robot.
- * @return the actual rotational velocity, given in [rad/s].
- */
-float Controller::getActualRotationalVelocity() {
-    
-    return actualRotationalVelocity;
-}
-
-/**
- * This method is called by the ticker timer interrupt service routine.
- * It sends a flag to the thread to make it run again.
- */
-void Controller::sendThreadFlag() {
-    
-    thread.flags_set(threadFlag);
-}
-
-/**
- * This is an internal method of the controller that is running periodically.
- */
-void Controller::run() {
-
-    while (true) {
-        
-        // wait for the periodic thread flag
-        
-        ThisThread::flags_wait_any(threadFlag);
-        
-        // calculate the values 'desiredSpeedLeft' and 'desiredSpeedRight' using the kinematic model
-        
-        desiredSpeedLeft = (translationalVelocity-WHEEL_DISTANCE/2.0f*rotationalVelocity)/WHEEL_RADIUS*60.0f/2.0f/M_PI;
-        desiredSpeedRight = -(translationalVelocity+WHEEL_DISTANCE/2.0f*rotationalVelocity)/WHEEL_RADIUS*60.0f/2.0f/M_PI;
-        
-        // calculate planned speedLeft and speedRight values using the motion planner
-        
-        motionLeft.incrementToVelocity(desiredSpeedLeft, PERIOD);
-        motionRight.incrementToVelocity(desiredSpeedRight, PERIOD);
-        
-        desiredSpeedLeft = motionLeft.getVelocity();
-        desiredSpeedRight = motionRight.getVelocity();
-        
-        // calculate the actual speed of the motors in [rpm]
-
-        short valueCounterLeft = counterLeft.read();
-        short valueCounterRight = counterRight.read();
-
-        short countsInPastPeriodLeft = valueCounterLeft-previousValueCounterLeft;
-        short countsInPastPeriodRight = valueCounterRight-previousValueCounterRight;
-
-        previousValueCounterLeft = valueCounterLeft;
-        previousValueCounterRight = valueCounterRight;
-
-        actualSpeedLeft = speedLeftFilter.filter((float)countsInPastPeriodLeft/COUNTS_PER_TURN/PERIOD*60.0f);
-        actualSpeedRight = speedRightFilter.filter((float)countsInPastPeriodRight/COUNTS_PER_TURN/PERIOD*60.0f);
-
-        // calculate desired motor voltages Uout
-
-        float voltageLeft = KP*(desiredSpeedLeft-actualSpeedLeft)+desiredSpeedLeft/KN;
-        float voltageRight = KP*(desiredSpeedRight-actualSpeedRight)+desiredSpeedRight/KN;
-
-        // calculate, limit and set the duty-cycle
-
-        float dutyCycleLeft = 0.5f+0.5f*voltageLeft/MAX_VOLTAGE;
-        if (dutyCycleLeft < MIN_DUTY_CYCLE) dutyCycleLeft = MIN_DUTY_CYCLE;
-        else if (dutyCycleLeft > MAX_DUTY_CYCLE) dutyCycleLeft = MAX_DUTY_CYCLE;
-        pwmLeft = dutyCycleLeft;
-
-        float dutyCycleRight = 0.5f+0.5f*voltageRight/MAX_VOLTAGE;
-        if (dutyCycleRight < MIN_DUTY_CYCLE) dutyCycleRight = MIN_DUTY_CYCLE;
-        else if (dutyCycleRight > MAX_DUTY_CYCLE) dutyCycleRight = MAX_DUTY_CYCLE;
-        pwmRight = dutyCycleRight;
-
-        // calculate the values 'actualTranslationalVelocity' and 'actualRotationalVelocity' using the kinematic model
-
-        actualTranslationalVelocity = (actualSpeedLeft-actualSpeedRight)*2.0f*M_PI/60.0f*WHEEL_RADIUS/2.0f;
-        actualRotationalVelocity = (-actualSpeedRight-actualSpeedLeft)*2.0f*M_PI/60.0f*WHEEL_RADIUS/WHEEL_DISTANCE;
-    }
-}
--- a/Controller.h	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Controller.h
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#ifndef CONTROLLER_H_
-#define CONTROLLER_H_
-
-#include <cstdlib>
-#include <mbed.h>
-#include "EncoderCounterROME2.h"
-#include "Motion.h"
-#include "LowpassFilter.h"
-#include "ThreadFlag.h"
-
-/**
- * This class implements a controller that regulates the
- * speed of the two motors of the ROME2 mobile robot.
- */
-class Controller {
-    
-    public:
-        
-                Controller(PwmOut& pwmLeft, PwmOut& pwmRight, EncoderCounterROME2& counterLeft, EncoderCounterROME2& counterRight);
-        virtual ~Controller();
-        void    setTranslationalVelocity(float velocity);
-        void    setRotationalVelocity(float velocity);
-        float   getActualTranslationalVelocity();
-        float   getActualRotationalVelocity();
-        
-    private:
-        
-        static const unsigned int   STACK_SIZE = 4096;  // stack size of thread, given in [bytes]
-        static const float          PERIOD;             // period of control task, given in [s]
-        
-        static const float  M_PI;                       // the mathematical constant PI
-        static const float  WHEEL_DISTANCE;             // distance between wheels, given in [m]
-        static const float  WHEEL_RADIUS;               // radius of wheels, given in [m]
-        static const float  MAXIMUM_VELOCITY;           // maximum wheel velocity, given in [rpm]
-        static const float  MAXIMUM_ACCELERATION;       // maximum wheel acceleration, given in [rpm/s]
-        static const float  COUNTS_PER_TURN;
-        static const float  LOWPASS_FILTER_FREQUENCY;
-        static const float  KN;
-        static const float  KP;
-        static const float  MAX_VOLTAGE;
-        static const float  MIN_DUTY_CYCLE;
-        static const float  MAX_DUTY_CYCLE;
-
-        PwmOut&             pwmLeft;
-        PwmOut&             pwmRight;
-        EncoderCounterROME2&     counterLeft;
-        EncoderCounterROME2&     counterRight;
-        float               translationalVelocity;
-        float               rotationalVelocity;
-        float               actualTranslationalVelocity;
-        float               actualRotationalVelocity;
-        float               desiredSpeedLeft;
-        float               desiredSpeedRight;
-        float               actualSpeedLeft;
-        float               actualSpeedRight;
-        Motion              motionLeft;
-        Motion              motionRight;
-        short               previousValueCounterLeft;
-        short               previousValueCounterRight;
-        LowpassFilter       speedLeftFilter;
-        LowpassFilter       speedRightFilter;
-        ThreadFlag          threadFlag;
-        Thread              thread;
-        Ticker              ticker;
-        
-        void    sendThreadFlag();
-        void    run();
-};
-
-#endif /* CONTROLLER_H_ */
--- a/EncoderCounterROME2.cpp	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * EncoderCounterROME2.cpp
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#include "EncoderCounterROME2.h"
-
-using namespace std;
-
-/**
- * Creates and initialises the driver to read the quadrature
- * encoder counter of the STM32 microcontroller.
- * @param a the input pin for the channel A.
- * @param b the input pin for the channel B.
- */
-EncoderCounterROME2::EncoderCounterROME2(PinName a, PinName b) {
-    
-    // check pins
-    
-    if ((a == PA_15) && (b == PB_3)) {
-        
-        // pinmap OK for TIM2 CH1 and CH2
-        
-        TIM = TIM2;
-        
-        // configure reset and clock control registers
-        
-        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;    // manually enable port B (port A enabled by mbed library)
-        
-        // configure general purpose I/O registers
-        
-        GPIOA->MODER &= ~GPIO_MODER_MODER15;    // reset port A15
-        GPIOA->MODER |= GPIO_MODER_MODER15_1;   // set alternate mode of port A15
-        GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR15;    // reset pull-up/pull-down on port A15
-        GPIOA->PUPDR |= GPIO_PUPDR_PUPDR15_1;   // set input as pull-down
-        GPIOA->AFR[1] &= ~0xF0000000;           // reset alternate function of port A15
-        GPIOA->AFR[1] |= 1 << 4*7;              // set alternate funtion 1 of port A15
-        
-        GPIOB->MODER &= ~GPIO_MODER_MODER3;     // reset port B3
-        GPIOB->MODER |= GPIO_MODER_MODER3_1;    // set alternate mode of port B3
-        GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR3;     // reset pull-up/pull-down on port B3
-        GPIOB->PUPDR |= GPIO_PUPDR_PUPDR3_1;    // set input as pull-down
-        GPIOB->AFR[0] &= ~(0xF << 4*3);         // reset alternate function of port B3
-        GPIOB->AFR[0] |= 1 << 4*3;              // set alternate funtion 1 of port B3
-        
-        // configure reset and clock control registers
-        
-        RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST;  //reset TIM2 controller
-        RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST;
-        
-        RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;     // TIM2 clock enable
-        
-    } else if ((a == PB_4) && (b == PC_7)) {
-        
-        // pinmap OK for TIM3 CH1 and CH2
-        
-        TIM = TIM3;
-        
-        // configure reset and clock control registers
-        
-        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;    // manually enable port B
-        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;    // manually enable port C
-        
-        // configure general purpose I/O registers
-        
-        GPIOB->MODER &= ~GPIO_MODER_MODER4;     // reset port B4
-        GPIOB->MODER |= GPIO_MODER_MODER4_1;    // set alternate mode of port B4
-        GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR4;     // reset pull-up/pull-down on port B4
-        GPIOB->PUPDR |= GPIO_PUPDR_PUPDR4_1;    // set input as pull-down
-        GPIOB->AFR[0] &= ~(0xF << 4*4);         // reset alternate function of port B4
-        GPIOB->AFR[0] |= 2 << 4*4;              // set alternate funtion 2 of port B4
-        
-        GPIOC->MODER &= ~GPIO_MODER_MODER7;     // reset port C7
-        GPIOC->MODER |= GPIO_MODER_MODER7_1;    // set alternate mode of port C7
-        GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR7;     // reset pull-up/pull-down on port C7
-        GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_1;    // set input as pull-down
-        GPIOC->AFR[0] &= ~0xF0000000;           // reset alternate function of port C7
-        GPIOC->AFR[0] |= 2 << 4*7;              // set alternate funtion 2 of port C7
-        
-        // configure reset and clock control registers
-        
-        RCC->APB1RSTR |= RCC_APB1RSTR_TIM3RST;  //reset TIM3 controller
-        RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM3RST;
-        
-        RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;     // TIM3 clock enable
-        
-    } else if ((a == PD_12) && (b == PD_13)) {
-        
-        // pinmap OK for TIM4 CH1 and CH2
-        
-        TIM = TIM4;
-        
-        // configure reset and clock control registers
-        
-        RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;    // manually enable port D
-        
-        // configure general purpose I/O registers
-        
-        GPIOD->MODER &= ~GPIO_MODER_MODER12;    // reset port D12
-        GPIOD->MODER |= GPIO_MODER_MODER12_1;   // set alternate mode of port D12
-        GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR12;    // reset pull-up/pull-down on port D12
-        GPIOD->PUPDR |= GPIO_PUPDR_PUPDR12_1;   // set input as pull-down
-        GPIOD->AFR[1] &= ~(0xF << 4*4);         // reset alternate function of port D12
-        GPIOD->AFR[1] |= 2 << 4*4;              // set alternate funtion 2 of port D12
-        
-        GPIOD->MODER &= ~GPIO_MODER_MODER13;    // reset port D13
-        GPIOD->MODER |= GPIO_MODER_MODER13_1;   // set alternate mode of port D13
-        GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR13;    // reset pull-up/pull-down on port D13
-        GPIOD->PUPDR |= GPIO_PUPDR_PUPDR13_1;   // set input as pull-down
-        GPIOD->AFR[1] &= ~(0xF << 4*5);         // reset alternate function of port D13
-        GPIOD->AFR[1] |= 2 << 4*5;              // set alternate funtion 2 of port D13
-        
-        // configure reset and clock control registers
-        
-        RCC->APB1RSTR |= RCC_APB1RSTR_TIM4RST;  //reset TIM4 controller
-        RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM4RST;
-        
-        RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;     // TIM4 clock enable
-        
-    } else {
-        
-        printf("pinmap not found for peripheral\n");
-        
-        TIM = NULL;
-    }
-    
-    // disable deep sleep for timer clocks
-    
-    sleep_manager_lock_deep_sleep();
-    
-    // configure general purpose timer 2, 3 or 4
-    
-    if (TIM != NULL) {
-        
-        TIM->CR1 = 0x0000;          // counter disable
-        TIM->CR2 = 0x0000;          // reset master mode selection
-        TIM->SMCR = TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0; // counting on both TI1 & TI2 edges
-        TIM->CCMR1 = TIM_CCMR1_CC2S_0 | TIM_CCMR1_CC1S_0;
-        TIM->CCMR2 = 0x0000;        // reset capture mode register 2
-        TIM->CCER = TIM_CCER_CC2E | TIM_CCER_CC1E;
-        TIM->CNT = 0x0000;          // reset counter value
-        TIM->ARR = 0xFFFF;          // auto reload register
-        TIM->CR1 = TIM_CR1_CEN;     // counter enable
-    }
-}
-
-/**
- * Deletes this EncoderCounterROME2 object.
- */
-EncoderCounterROME2::~EncoderCounterROME2() {}
-
-/**
- * Resets the counter value to zero.
- */
-void EncoderCounterROME2::reset() {
-    
-    TIM->CNT = 0x0000;
-}
-
-/**
- * Resets the counter value to a given offset value.
- * @param offset the offset value to reset the counter to.
- */
-void EncoderCounterROME2::reset(short offset) {
-    
-    TIM->CNT = -offset;
-}
-
-/**
- * Reads the quadrature encoder counter value.
- * @return the quadrature encoder counter as a signed 16-bit integer value.
- */
-short EncoderCounterROME2::read() {
-    
-    return (short)(-TIM->CNT);
-}
-
-/**
- * The empty operator is a shorthand notation of the <code>read()</code> method.
- */
-EncoderCounterROME2::operator short() {
-    
-    return read();
-}
--- a/EncoderCounterROME2.h	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * EncoderCounterROME2.h
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#ifndef ENCODER_COUNTER_ROME2_H_
-#define ENCODER_COUNTER_ROME2_H_
-
-#include <cstdlib>
-#include <mbed.h>
-
-/**
- * This class implements a driver to read the quadrature
- * encoder counter of the STM32 microcontroller.
- */
-class EncoderCounterROME2 {
-    
-    public:
-        
-                    EncoderCounterROME2(PinName a, PinName b);
-        virtual     ~EncoderCounterROME2();
-        void        reset();
-        void        reset(short offset);
-        short       read();
-                    operator short();
-        
-    private:
-        
-        TIM_TypeDef*    TIM;
-};
-
-#endif /* ENCODER_COUNTER_ROME2_H_ */
--- a/IRSensor.cpp	Wed May 11 09:44:25 2022 +0200
+++ b/IRSensor.cpp	Sat May 14 15:27:12 2022 +0200
@@ -45,9 +45,9 @@
 /**
  * The empty operator is a shorthand notation of the <code>read()</code> method.
  */
-/*
+ /*
 IRSensor::operator float() {
     
     return read();
 }
-*/
\ No newline at end of file
+*/
--- a/IRSensor.h	Wed May 11 09:44:25 2022 +0200
+++ b/IRSensor.h	Sat May 14 15:27:12 2022 +0200
@@ -21,7 +21,7 @@
                 IRSensor(AnalogIn& distance, DigitalOut& bit0, DigitalOut& bit1, DigitalOut& bit2, int number);
         virtual ~IRSensor();
         float   read();
-                // operator float();
+                //operator float();
         
     private:
         
--- a/Motion.cpp	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,601 +0,0 @@
-/*
- * Motion.cpp
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#include <cmath>
-#include <algorithm>
-#include "Motion.h"
-
-using namespace std;
-
-const float Motion::DEFAULT_LIMIT = 1.0f;       // default value for limits
-const float Motion::MINIMUM_LIMIT = 1.0e-9f;    // smallest value allowed for limits
-
-/**
- * Creates a <code>Motion</code> object.
- * The values for position, velocity and acceleration are set to 0.
- */
-Motion::Motion() {
-    
-    position = 0.0;
-    velocity = 0.0f;
-    
-    profileVelocity = DEFAULT_LIMIT;
-    profileAcceleration = DEFAULT_LIMIT;
-    profileDeceleration = DEFAULT_LIMIT;
-}
-
-/**
- * Creates a <code>Motion</code> object with given values for position and velocity.
- * @param position the initial position value of this motion, given in [m] or [rad].
- * @param velocity the initial velocity value of this motion, given in [m/s] or [rad/s].
- */
-Motion::Motion(double position, float velocity) {
-    
-    this->position = position;
-    this->velocity = velocity;
-    
-    profileVelocity = DEFAULT_LIMIT;
-    profileAcceleration = DEFAULT_LIMIT;
-    profileDeceleration = DEFAULT_LIMIT;
-}
-
-/**
- * Creates a <code>Motion</code> object with given values for position and velocity.
- * @param motion another <code>Motion</code> object to copy the values from.
- */
-Motion::Motion(const Motion& motion) {
-    
-    position = motion.position;
-    velocity = motion.velocity;
-    
-    profileVelocity = motion.profileVelocity;
-    profileAcceleration = motion.profileAcceleration;
-    profileDeceleration = motion.profileDeceleration;
-}
-
-/**
- * Deletes the Motion object.
- */
-Motion::~Motion() {}
-
-/**
- * Sets the values for position and velocity.
- * @param position the desired position value of this motion, given in [m] or [rad].
- * @param velocity the desired velocity value of this motion, given in [m/s] or [rad/s].
- */
-void Motion::set(double position, float velocity) {
-    
-    this->position = position;
-    this->velocity = velocity;
-}
-
-/**
- * Sets the values for position and velocity.
- * @param motion another <code>Motion</code> object to copy the values from.
- */
-void Motion::set(const Motion& motion) {
-    
-    position = motion.position;
-    velocity = motion.velocity;
-}
-
-/**
- * Sets the position value.
- * @param position the desired position value of this motion, given in [m] or [rad].
- */
-void Motion::setPosition(double position) {
-    
-    this->position = position;
-}
-
-/**
- * Gets the position value.
- * @return the position value of this motion, given in [m] or [rad].
- */
-double Motion::getPosition() {
-    
-    return position;
-}
-
-/**
- * Sets the velocity value.
- * @param velocity the desired velocity value of this motion, given in [m/s] or [rad/s].
- */
-void Motion::setVelocity(float velocity) {
-    
-    this->velocity = velocity;
-}
-
-/**
- * Gets the velocity value.
- * @return the velocity value of this motion, given in [m/s] or [rad/s].
- */
-float Motion::getVelocity() {
-    
-    return velocity;
-}
-
-/**
- * Sets the limit for the velocity value.
- * @param profileVelocity the limit of the velocity.
- */
-void Motion::setProfileVelocity(float profileVelocity) {
-    
-    if (profileVelocity > MINIMUM_LIMIT) this->profileVelocity = profileVelocity; else this->profileVelocity = MINIMUM_LIMIT;
-}
-
-/**
- * Sets the limit for the acceleration value.
- * @param profileAcceleration the limit of the acceleration.
- */
-void Motion::setProfileAcceleration(float profileAcceleration) {
-    
-    if (profileAcceleration > MINIMUM_LIMIT) this->profileAcceleration = profileAcceleration; else this->profileAcceleration = MINIMUM_LIMIT;
-}
-
-/**
- * Sets the limit for the deceleration value.
- * @param profileDeceleration the limit of the deceleration.
- */
-void Motion::setProfileDeceleration(float profileDeceleration) {
-    
-    if (profileDeceleration > MINIMUM_LIMIT) this->profileDeceleration = profileDeceleration; else this->profileDeceleration = MINIMUM_LIMIT;
-}
-
-/**
- * Sets the limits for velocity, acceleration and deceleration values.
- * @param profileVelocity the limit of the velocity.
- * @param profileAcceleration the limit of the acceleration.
- * @param profileDeceleration the limit of the deceleration.
- */
-void Motion::setLimits(float profileVelocity, float profileAcceleration, float profileDeceleration) {
-    
-    if (profileVelocity > MINIMUM_LIMIT) this->profileVelocity = profileVelocity; else this->profileVelocity = MINIMUM_LIMIT;
-    if (profileAcceleration > MINIMUM_LIMIT) this->profileAcceleration = profileAcceleration; else this->profileAcceleration = MINIMUM_LIMIT;
-    if (profileDeceleration > MINIMUM_LIMIT) this->profileDeceleration = profileDeceleration; else this->profileDeceleration = MINIMUM_LIMIT;
-}
-
-/**
- * Gets the time needed to move to a given target position.
- * @param targetPosition the desired target position given in [m] or [rad].
- * @return the time to move to the target position, given in [s].
- */
-float Motion::getTimeToPosition(double targetPosition) {
-    
-    // calculate position, when velocity is reduced to zero
-    
-    double stopPosition = (velocity > 0.0f) ? position+(double)(velocity*velocity/profileDeceleration*0.5f) : position-(double)(velocity*velocity/profileDeceleration*0.5f);
-    
-    if (targetPosition > stopPosition) { // positive velocity required
-        
-        if (velocity > profileVelocity) { // slow down to profile velocity first
-            
-            float t1 = (velocity-profileVelocity)/profileDeceleration;
-            float t2 = (float)(targetPosition-stopPosition)/profileVelocity;
-            float t3 = profileVelocity/profileDeceleration;
-            
-            return t1+t2+t3;
-            
-        } else if (velocity > 0.0f) { // speed up to profile velocity
-            
-            float t1 = (profileVelocity-velocity)/profileAcceleration;
-            float t3 = profileVelocity/profileDeceleration;
-            float t2 = ((float)(targetPosition-position)-(velocity+profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3;
-            
-            if (t2 < 0.0f) {
-                float maxVelocity = sqrt((2.0f*(float)(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration));
-                t1 = (maxVelocity-velocity)/profileAcceleration;
-                t2 = 0.0f;
-                t3 = maxVelocity/profileDeceleration;
-            }
-            
-            return t1+t2+t3;
-            
-        } else { // slow down to zero first, and then speed up to profile velocity
-            
-            float t1 = -velocity/profileDeceleration;
-            float t2 = profileVelocity/profileAcceleration;
-            float t4 = profileVelocity/profileDeceleration;
-            float t3 = ((float)(targetPosition-position)-velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4);
-            
-            if (t3 < 0.0f) {
-                float maxVelocity = sqrt((2.0f*(float)(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration));
-                t2 = maxVelocity/profileAcceleration;
-                t3 = 0.0f;
-                t4 = maxVelocity/profileDeceleration;
-            }
-            
-            return t1+t2+t3+t4;
-        }
-        
-    } else { // negative velocity required
-        
-        if (velocity < -profileVelocity) { // slow down to (negative) profile velocity first
-            
-            float t1 = (-profileVelocity-velocity)/profileDeceleration;
-            float t2 = (float)(stopPosition-targetPosition)/profileVelocity;
-            float t3 = profileVelocity/profileDeceleration;
-            
-            return t1+t2+t3;
-            
-        } else if (velocity < 0.0f) { // speed up to (negative) profile velocity
-            
-            float t1 = (velocity+profileVelocity)/profileAcceleration;
-            float t3 = profileVelocity/profileDeceleration;
-            float t2 = ((float)(position-targetPosition)+(velocity-profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3;
-            
-            if (t2 < 0.0f) {
-                float minVelocity = -sqrt((-2.0f*(float)(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration));
-                t1 = (velocity-minVelocity)/profileAcceleration;
-                t2 = 0.0f;
-                t3 = -minVelocity/profileDeceleration;
-            }
-            
-            return t1+t2+t3;
-            
-        } else { // slow down to zero first, and then speed up to (negative) profile velocity
-            
-            float t1 = velocity/profileDeceleration;
-            float t2 = profileVelocity/profileAcceleration;
-            float t4 = profileVelocity/profileDeceleration;
-            float t3 = (-(float)(targetPosition-position)+velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4);
-            
-            if (t3 < 0.0f) {
-                float minVelocity = -sqrt((-2.0f*(float)(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration));
-                t2 = -minVelocity/profileAcceleration;
-                t3 = 0.0f;
-                t4 = -minVelocity/profileDeceleration;
-            }
-            
-            return t1+t2+t3+t4;
-        }
-    }
-}
-
-/**
- * Increments the current motion towards a given target velocity.
- * @param targetVelocity the desired target velocity given in [m/s] or [rad/s].
- * @param period the time period to increment the motion values for, given in [s].
- */
-void Motion::incrementToVelocity(float targetVelocity, float period) {
-    
-    if (targetVelocity < -profileVelocity) targetVelocity = -profileVelocity;
-    else if (targetVelocity > profileVelocity) targetVelocity = profileVelocity;
-    
-    if (targetVelocity > 0.0f) {
-        
-        if (velocity > targetVelocity) { // slow down to target velocity
-            
-            float t1 = (velocity-targetVelocity)/profileDeceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*period)*period);
-                velocity += -profileDeceleration*period;
-            } else {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)(velocity*(period-t1));
-            }
-            
-        } else if (velocity > 0.0f) { // speed up to target velocity
-            
-            float t1 = (targetVelocity-velocity)/profileAcceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileAcceleration*0.5f*period)*period);
-                velocity += profileAcceleration*period;
-            } else {
-                position += (double)((velocity+profileAcceleration*0.5f*t1)*t1);
-                velocity += profileAcceleration*t1;
-                position += (double)(velocity*(period-t1));
-            }
-            
-        } else { // slow down to zero first, and then speed up to target velocity
-            
-            float t1 = -velocity/profileDeceleration;
-            float t2 = targetVelocity/profileAcceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*period)*period);
-                velocity += profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*(period-t1))*(period-t1));
-                velocity += profileAcceleration*(period-t1);
-            } else {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*t2)*t2);
-                velocity += profileAcceleration*t2;
-                position += (double)(velocity*(period-t1-t2));
-            }
-        }
-        
-    } else {
-        
-        if (velocity < targetVelocity) { // slow down to (negative) target velocity
-            
-            float t1 = (targetVelocity-velocity)/profileDeceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*period)*period);
-                velocity += profileDeceleration*period;
-            } else {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)(velocity*(period-t1));
-            }
-            
-        } else if (velocity < 0.0f) { // speed up to (negative) target velocity
-            
-            float t1 = (velocity-targetVelocity)/profileAcceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileAcceleration*0.5f*period)*period);
-                velocity += -profileAcceleration*period;
-            } else {
-                position += (double)((velocity-profileAcceleration*0.5f*t1)*t1);
-                velocity += -profileAcceleration*t1;
-                position += (double)(velocity*(period-t1));
-            }
-            
-        } else { // slow down to zero first, and then speed up to (negative) target velocity
-            
-            float t1 = velocity/profileDeceleration;
-            float t2 = -targetVelocity/profileAcceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*period)*period);
-                velocity += -profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*(period-t1))*(period-t1));
-                velocity += -profileAcceleration*(period-t1);
-            } else {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*t2)*t2);
-                velocity += -profileAcceleration*t2;
-                position += (double)(velocity*(period-t1-t2));
-            }
-        }
-    }
-}
-
-/**
- * Increments the current motion towards a given target position.
- * @param targetPosition the desired target position given in [m] or [rad].
- * @param period the time period to increment the motion values for, given in [s].
- */
-void Motion::incrementToPosition(double targetPosition, float period) {
-    
-    // calculate position, when velocity is reduced to zero
-    
-    double stopPosition = (velocity > 0.0f) ? position+(double)(velocity*velocity/profileDeceleration*0.5f) : position-(double)(velocity*velocity/profileDeceleration*0.5f);
-    
-    if (targetPosition > stopPosition) { // positive velocity required
-        
-        if (velocity > profileVelocity) { // slow down to profile velocity first
-            
-            float t1 = (velocity-profileVelocity)/profileDeceleration;
-            float t2 = (float)(targetPosition-stopPosition)/profileVelocity;
-            float t3 = profileVelocity/profileDeceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*period)*period);
-                velocity += -profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)(velocity*(period-t1));
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity-profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2));
-                velocity += -profileDeceleration*(period-t1-t2);
-            } else {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity-profileDeceleration*0.5f*t3)*t3);
-                velocity += -profileDeceleration*t3;
-            }
-            
-        } else if (velocity > 0.0f) { // speed up to profile velocity
-            
-            float t1 = (profileVelocity-velocity)/profileAcceleration;
-            float t3 = profileVelocity/profileDeceleration;
-            float t2 = ((float)(targetPosition-position)-(velocity+profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3;
-            
-            if (t2 < 0.0f) {
-                float maxVelocity = sqrt((2.0f*(float)(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration));
-                t1 = (maxVelocity-velocity)/profileAcceleration;
-                t2 = 0.0f;
-                t3 = maxVelocity/profileDeceleration;
-            }
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileAcceleration*0.5f*period)*period);
-                velocity += profileAcceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity+profileAcceleration*0.5f*t1)*t1);
-                velocity += profileAcceleration*t1;
-                position += (double)(velocity*(period-t1));
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity+profileAcceleration*0.5f*t1)*t1);
-                velocity += profileAcceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity-profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2));
-                velocity += -profileDeceleration*(period-t1-t2);
-            } else {
-                position += (double)((velocity+profileAcceleration*0.5f*t1)*t1);
-                velocity += profileAcceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity-profileDeceleration*0.5f*t3)*t3);
-                velocity += -profileDeceleration*t3;
-            }
-            
-        } else { // slow down to zero first, and then speed up to profile velocity
-            
-            float t1 = -velocity/profileDeceleration;
-            float t2 = profileVelocity/profileAcceleration;
-            float t4 = profileVelocity/profileDeceleration;
-            float t3 = ((float)(targetPosition-position)-velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4);
-            
-            if (t3 < 0.0f) {
-                float maxVelocity = sqrt((2.0f*(float)(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration));
-                t2 = maxVelocity/profileAcceleration;
-                t3 = 0.0f;
-                t4 = maxVelocity/profileDeceleration;
-            }
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*period)*period);
-                velocity += profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*(period-t1))*(period-t1));
-                velocity += profileAcceleration*(period-t1);
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*t2)*t2);
-                velocity += profileAcceleration*t2;
-                position += (double)(velocity*(period-t1-t2));
-            } else if (t1+t2+t3+t4 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*t2)*t2);
-                velocity += profileAcceleration*t2;
-                position += (double)(velocity*t3);
-                position += (double)((velocity-profileDeceleration*0.5f*(period-t1-t2-t3))*(period-t1-t2-t3));
-                velocity += -profileDeceleration*(period-t1-t2-t3);
-            } else {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)((velocity+profileAcceleration*0.5f*t2)*t2);
-                velocity += profileAcceleration*t2;
-                position += (double)(velocity*t3);
-                position += (double)((velocity-profileDeceleration*0.5f*t4)*t4);
-                velocity += -profileDeceleration*t4;
-            }
-        }
-        
-    } else { // negative velocity required
-        
-        if (velocity < -profileVelocity) { // slow down to (negative) profile velocity first
-            
-            float t1 = (-profileVelocity-velocity)/profileDeceleration;
-            float t2 = (float)(stopPosition-targetPosition)/profileVelocity;
-            float t3 = profileVelocity/profileDeceleration;
-            
-            if (t1 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*period)*period);
-                velocity += profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)(velocity*(period-t1));
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity+profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2));
-                velocity += profileDeceleration*(period-t1-t2);
-            } else {
-                position += (double)((velocity+profileDeceleration*0.5f*t1)*t1);
-                velocity += profileDeceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity+profileDeceleration*0.5f*t3)*t3);
-                velocity += profileDeceleration*t3;
-            }
-            
-        } else if (velocity < 0.0f) { // speed up to (negative) profile velocity
-            
-            float t1 = (velocity+profileVelocity)/profileAcceleration;
-            float t3 = profileVelocity/profileDeceleration;
-            float t2 = ((float)(position-targetPosition)+(velocity-profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3;
-            
-            if (t2 < 0.0f) {
-                float minVelocity = -sqrt((-2.0f*(float)(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration));
-                t1 = (velocity-minVelocity)/profileAcceleration;
-                t2 = 0.0f;
-                t3 = -minVelocity/profileDeceleration;
-            }
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileAcceleration*0.5f*period)*period);
-                velocity += -profileAcceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity-profileAcceleration*0.5f*t1)*t1);
-                velocity += -profileAcceleration*t1;
-                position += (double)(velocity*(period-t1));
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity-profileAcceleration*0.5f*t1)*t1);
-                velocity += -profileAcceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity+profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2));
-                velocity += profileDeceleration*(period-t1-t2);
-            } else {
-                position += (double)((velocity-profileAcceleration*0.5f*t1)*t1);
-                velocity += -profileAcceleration*t1;
-                position += (double)(velocity*t2);
-                position += (double)((velocity+profileDeceleration*0.5f*t3)*t3);
-                velocity += profileDeceleration*t3;
-            }
-            
-        } else { // slow down to zero first, and then speed up to (negative) profile velocity
-            
-            float t1 = velocity/profileDeceleration;
-            float t2 = profileVelocity/profileAcceleration;
-            float t4 = profileVelocity/profileDeceleration;
-            float t3 = (-(float)(targetPosition-position)+velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4);
-            
-            if (t3 < 0.0f) {
-                float minVelocity = -sqrt((-2.0f*(float)(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration));
-                t2 = -minVelocity/profileAcceleration;
-                t3 = 0.0f;
-                t4 = -minVelocity/profileDeceleration;
-            }
-            
-            if (t1 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*period)*period);
-                velocity += -profileDeceleration*period;
-            } else if (t1+t2 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*(period-t1))*(period-t1));
-                velocity += -profileAcceleration*(period-t1);
-            } else if (t1+t2+t3 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*t2)*t2);
-                velocity += -profileAcceleration*t2;
-                position += (double)(velocity*(period-t1-t2));
-            } else if (t1+t2+t3+t4 > period) {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*t2)*t2);
-                velocity += -profileAcceleration*t2;
-                position += (double)(velocity*t3);
-                position += (double)((velocity+profileDeceleration*0.5f*(period-t1-t2-t3))*(period-t1-t2-t3));
-                velocity += profileDeceleration*(period-t1-t2-t3);
-            } else {
-                position += (double)((velocity-profileDeceleration*0.5f*t1)*t1);
-                velocity += -profileDeceleration*t1;
-                position += (double)((velocity-profileAcceleration*0.5f*t2)*t2);
-                velocity += -profileAcceleration*t2;
-                position += (double)(velocity*t3);
-                position += (double)((velocity+profileDeceleration*0.5f*t4)*t4);
-                velocity += profileDeceleration*t4;
-            }
-        }
-    }
-}
--- a/Motion.h	Wed May 11 09:44:25 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Motion.h
- * Copyright (c) 2022, ZHAW
- * All rights reserved.
- */
-
-#ifndef MOTION_H_
-#define MOTION_H_
-
-#include <cstdlib>
-
-/**
- * This class keeps the motion values <code>position</code> and <code>velocity</code>, and
- * offers methods to increment these values towards a desired target position or velocity.
- * <br/>
- * To increment the current motion values, this class uses a simple 2nd order motion planner.
- * This planner calculates the motion to the target position or velocity with the various motion
- * phases, based on given limits for the profile velocity, acceleration and deceleration.
- * <br/>
- * Note that the trajectory is calculated every time the motion state is incremented.
- * This allows to change the target position or velocity, as well as the limits for profile
- * velocity, acceleration and deceleration at any time.
- */
-class Motion {
-    
-    public:
-        
-        double      position;       /**< The position value of this motion, given in [m] or [rad]. */
-        float       velocity;       /**< The velocity value of this motion, given in [m/s] or [rad/s]. */
-        
-                    Motion();
-                    Motion(double position, float velocity);
-                    Motion(const Motion& motion);
-        virtual     ~Motion();
-        void        set(double position, float velocity);
-        void        set(const Motion& motion);
-        void        setPosition(double position);
-        double      getPosition();
-        void        setVelocity(float velocity);
-        float       getVelocity();
-        void        setProfileVelocity(float profileVelocity);
-        void        setProfileAcceleration(float profileAcceleration);
-        void        setProfileDeceleration(float profileDeceleration);
-        void        setLimits(float profileVelocity, float profileAcceleration, float profileDeceleration);
-        float       getTimeToPosition(double targetPosition);
-        void        incrementToVelocity(float targetVelocity, float period);
-        void        incrementToPosition(double targetPosition, float period);
-        
-    private:
-        
-        static const float  DEFAULT_LIMIT;  // default value for limits
-        static const float  MINIMUM_LIMIT;  // smallest value allowed for limits
-        
-        float       profileVelocity;
-        float       profileAcceleration;
-        float       profileDeceleration;
-};
-
-#endif /* MOTION_H_ */
--- a/PM2_Libary.lib	Wed May 11 09:44:25 2022 +0200
+++ b/PM2_Libary.lib	Sat May 14 15:27:12 2022 +0200
@@ -1,1 +1,1 @@
-https://os.mbed.com/users/pmic/code/PM2_Libary/#6b30640c9e2e
+https://os.mbed.com/users/pmic/code/PM2_Libary/#05abc1d2a2b90c1153c16504c84bdc9d3cd7d809
\ No newline at end of file
--- a/main.cpp	Wed May 11 09:44:25 2022 +0200
+++ b/main.cpp	Sat May 14 15:27:12 2022 +0200
@@ -1,79 +1,113 @@
-#include <stdio.h>
 #include <mbed.h>
+#include <math.h>
 #include <vector>
 
+#include "PM2_Libary.h"
+#include "Eigen/Dense.h"
+
 #include "IRSensor.h"
-#include "EncoderCounterROME2.h"
-#include "Controller.h"
-
-#include "Eigen/Dense.h"
 
 # define M_PI 3.14159265358979323846  // number pi
 
+/**
+ * notes:
+ * - IRSensor class is not available in PM2_Libary
+ * - ROME2 Robot uses different PINS than PES board
+ */
+
 // logical variable main task
 bool do_execute_main_task = false;  // this variable will be toggled via the user button (blue button) to or not to execute the main task
 
 // user button on nucleo board
 Timer user_button_timer;            // create Timer object which we use to check if user button was pressed for a certain time (robust against signal bouncing)
-InterruptIn user_button(BUTTON1);   // create InterruptIn interface object to evaluate user button falling and rising edge (no blocking code in ISR)
+InterruptIn user_button(PC_13);     // create InterruptIn interface object to evaluate user button falling and rising edge (no blocking code in ISR)
 void user_button_pressed_fcn();     // custom functions which gets executed when user button gets pressed and released, definition below
 void user_button_released_fcn();
 
-// while loop gets executed every main_task_period_ms milliseconds
-int main_task_period_ms = 50;   // define main task period time in ms e.g. 50 ms -> main task runns 20 times per second
-Timer main_task_timer;          // create Timer object which we use to run the main task every main task period time in ms
+int main() {
+    
+    // while loop gets executed every main_task_period_ms milliseconds
+    const int main_task_period_ms = 10;   // define main task period time in ms e.g. 50 ms -> main task runns 20 times per second
+    Timer main_task_timer;                // create Timer object which we use to run the main task every main task period time in ms
 
-// led on nucleo board
-DigitalOut user_led(LED1);      // create DigitalOut object to command user led
-
-static const int ROBOT_OFF = 0;      // discrete states of this state machine
-static const int MOVE_FORWARD = 1;
-static const int TURN_LEFT = 2;
-static const int TURN_RIGHT = 3;
-static const int SLOWING_DOWN = 4;
+    // led on nucleo board
+    DigitalOut user_led(LED1);      // create DigitalOut object to command user led
 
-const float DISTANCE_THRESHOLD = 0.4f;        // minimum allowed distance to obstacle in [m]
-const float TRANSLATIONAL_VELOCITY = 1.0f;    // translational velocity in [m/s]
-const float ROTATIONAL_VELOCITY = 1.0f;       // rotational velocity in [rad/s]
-const float VELOCITY_THRESHOLD = 0.01;        // velocity threshold before switching off, in [m/s] and [rad/s]
+    // discrete states of this state machine
+    const int ROBOT_OFF = 0;      
+    const int MOVE_FORWARD = 1;
+    const int TURN_LEFT = 2;
+    const int TURN_RIGHT = 3;
+    const int SLOWING_DOWN = 4;
 
-DigitalOut led0(PD_4);
-DigitalOut led1(PD_3);
-DigitalOut led2(PD_6);
-DigitalOut led3(PD_2);
-DigitalOut led4(PD_7);
-DigitalOut led5(PD_5);
-std::vector<DigitalOut> leds = {led0, led1, led2, led3, led4, led5};
+    // default parameters for robots movement
+    const float DISTANCE_THRESHOLD = 0.2f;        // minimum allowed distance to obstacle in [m]
+    const float TRANSLATIONAL_VELOCITY = 0.4f;    // translational velocity in [m/s]
+    const float ROTATIONAL_VELOCITY = 1.6f;       // rotational velocity in [rad/s]
+    const float VELOCITY_THRESHOLD = 0.05;        // velocity threshold before switching off, in [m/s] and [rad/s]
+
+    // create DigitalOut objects for leds
+    DigitalOut led0(PC_8);
+    DigitalOut led1(PC_6);
+    DigitalOut led2(PB_12);
+    DigitalOut led3(PA_7);
+    DigitalOut led4(PC_0);
+    DigitalOut led5(PC_9);
+    std::vector<DigitalOut> leds = {led0, led1, led2, led3, led4, led5};
 
-// create IR sensor objects  
-AnalogIn dist(PA_0);
-DigitalOut enable(PG_1);
-DigitalOut bit0(PF_0);
-DigitalOut bit1(PF_1);
-DigitalOut bit2(PF_2);
+    // create IR sensor objects  
+    AnalogIn dist(PB_1);
+    DigitalOut enable_leds(PC_1);
+    DigitalOut bit0(PH_1);
+    DigitalOut bit1(PC_2);
+    DigitalOut bit2(PC_3);
+    IRSensor irSensor0(dist, bit0, bit1, bit2, 0);
+    IRSensor irSensor1(dist, bit0, bit1, bit2, 1);
+    IRSensor irSensor2(dist, bit0, bit1, bit2, 2);
+    IRSensor irSensor3(dist, bit0, bit1, bit2, 3);
+    IRSensor irSensor4(dist, bit0, bit1, bit2, 4);
+    IRSensor irSensor5(dist, bit0, bit1, bit2, 5);
+    std::vector<IRSensor> irSensors = {irSensor0, irSensor1, irSensor2, irSensor3, irSensor4, irSensor5};
 
-IRSensor irSensor0(dist, bit0, bit1, bit2, 0);
-IRSensor irSensor1(dist, bit0, bit1, bit2, 1);
-IRSensor irSensor2(dist, bit0, bit1, bit2, 2);
-IRSensor irSensor3(dist, bit0, bit1, bit2, 3);
-IRSensor irSensor4(dist, bit0, bit1, bit2, 4);
-IRSensor irSensor5(dist, bit0, bit1, bit2, 5);
+    // 19:1 Metal Gearmotor 37Dx68L mm 12V with 64 CPR Encoder (Helical Pinion)
+    DigitalOut enable_motors(PB_2);
+    DigitalIn motorDriverFault(PB_14);
+    DigitalIn motorDriverWarning(PB_15);
 
-// create motor control objects   
-DigitalOut enableMotorDriver(PG_0); 
-DigitalIn motorDriverFault(PD_1);
-DigitalIn motorDriverWarning(PD_0);
-PwmOut pwmLeft(PF_9);
-PwmOut pwmRight(PF_8);
-EncoderCounterROME2 counterLeft(PD_12, PD_13);
-EncoderCounterROME2 counterRight(PB_4, PC_7);
+    // create SpeedController objects
+    FastPWM pwm_M1(PA_9);  // motor M1 is closed-loop speed controlled (angle velocity)
+    FastPWM pwm_M2(PA_8);  // motor M2 is closed-loop speed controlled (angle velocity)
+    EncoderCounter  encoder_M1(PA_6, PC_7); // create encoder objects to read in the encoder counter values
+    EncoderCounter  encoder_M2(PB_6, PB_7);
+    const float max_voltage = 12.0f;                // define maximum voltage of battery packs, adjust this to 6.0f V if you only use one batterypack
+    const float counts_per_turn = 64.0f * 19.0f;    // define counts per turn at gearbox end: counts/turn * gearratio
+    const float kn = 530.0f / 12.0f;                // define motor constant in rpm per V
+    
+    SpeedController* speedControllers[2];
+    speedControllers[0] = new SpeedController(counts_per_turn, kn, max_voltage, pwm_M1, encoder_M1);
+    speedControllers[1] = new SpeedController(counts_per_turn, kn, max_voltage, pwm_M2, encoder_M2);
+    speedControllers[0]->setSpeedCntrlGain(0.04f);      // adjust speedcontroller gains
+    speedControllers[1]->setSpeedCntrlGain(0.04f);
+    speedControllers[0]->setMaxAccelerationRPS(10.0f);  // adjust max. acceleration for smooth movement
+    speedControllers[1]->setMaxAccelerationRPS(10.0f);
 
-int state;
-// create robot controller objects
-Controller controller(pwmLeft, pwmRight, counterLeft, counterRight);
-// StateMachine stateMachine(controller, enableMotorDriver, led0, led1, led2, led3, led4, led5, button, irSensor0, irSensor1, irSensor2, irSensor3, irSensor4, irSensor5);
-
-int main() {
+    // robot kinematics
+    const float r_wheel = 0.0766f / 2.0f; // wheel radius
+    const float L_wheel = 0.176f;         // distance from wheel to wheel
+    Eigen::Matrix2f Cwheel2robot; // transform wheel to robot
+    //Eigen::Matrix2f Crobot2wheel; // transform robot to wheel
+    Cwheel2robot << -r_wheel / 2.0f   ,  r_wheel / 2.0f   ,
+                    -r_wheel / L_wheel, -r_wheel / L_wheel;
+    //Crobot2wheel << -1.0f / r_wheel, -L_wheel / (2.0f * r_wheel),
+    //                 1.0f / r_wheel, -L_wheel / (2.0f * r_wheel);
+    Eigen::Vector2f robot_coord;  // contains v and w (robot translational and rotational velocities)
+    Eigen::Vector2f wheel_speed;  // w1 w2 (wheel speed)
+    Eigen::Vector2f wheel_speed_actual;
+    Eigen::Vector2f robot_coord_actual;
+    robot_coord.setZero();
+    wheel_speed.setZero();
+    wheel_speed_actual.setZero();
+    robot_coord_actual.setZero();
 
     // attach button fall and rise functions to user button object
     user_button.fall(&user_button_pressed_fcn);
@@ -81,159 +115,110 @@
     
     // start timer
     main_task_timer.start();
-        
-    enable = 1;
-    
-    enableMotorDriver = 0;
-    state = ROBOT_OFF;
 
-    Eigen::Matrix<float, 6, 1> irSensor_distance; // transform wheel to robot
+    // set initial state machine state, enalbe leds, disable motors
+    int state = ROBOT_OFF;
+    enable_leds = 1;
+    enable_motors = 0;
     
     while (true) { // this loop will run forever
         
         main_task_timer.reset();
 
-        // read the distance sensors
-        irSensor_distance << irSensor0.read(),
-                             irSensor1.read(),
-                             irSensor2.read(),
-                             irSensor3.read(),
-                             irSensor4.read(),
-                             irSensor5.read();
-
-        // set the leds based on distance measurements
-        ///*
-        // iterator based foor loop
-        int cnt = 0;
-        for(auto it = leds.begin(); it != leds.end(); it++){
-            *it =  irSensor_distance(cnt) < DISTANCE_THRESHOLD;
-            cnt++;
+        // set leds according to DISTANCE_THRESHOLD
+        for (uint8_t i = 0; i < leds.size(); i++) {
+            if (irSensors[i].read() > DISTANCE_THRESHOLD)
+                leds[i] =  0;
+            else
+                leds[i] = 1;
         }
-        //*/
-        /*
-        // index based for loop
-        for (int i = 0; i < leds.size(); i++) {
-            leds[i] =  irSensor_distance(i) < DISTANCE_THRESHOLD;
-        }
-        */
-        /*
-        // range based for loop
-        int cnt = 0;
-        for(DigitalOut led : leds){
-            led =  irSensor_distance(cnt) < DISTANCE_THRESHOLD;
-            cnt++;
-        }
-        /*
-        led0 = irSensor_distance(0) < DISTANCE_THRESHOLD;
-        led1 = irSensor_distance(1) < DISTANCE_THRESHOLD;
-        led2 = irSensor_distance(2) < DISTANCE_THRESHOLD;
-        led3 = irSensor_distance(3) < DISTANCE_THRESHOLD;
-        led4 = irSensor_distance(4) < DISTANCE_THRESHOLD;
-        led5 = irSensor_distance(5) < DISTANCE_THRESHOLD;
-        */
 
+        // read actual wheel speed and transform it to robot coordinates
+        wheel_speed_actual << speedControllers[0]->getSpeedRPS(), speedControllers[1]->getSpeedRPS();
+        robot_coord_actual =  Cwheel2robot * wheel_speed_actual;
+
+        // state machine
         switch (state) {
             
-            // enables Motors, sets translational speed and switches to MOVE_FORWARD
-            case ROBOT_OFF:           
+            case ROBOT_OFF:
+                
                 if (do_execute_main_task) {
-                    enableMotorDriver = 1;
-                    controller.setTranslationalVelocity(TRANSLATIONAL_VELOCITY);
-                    controller.setRotationalVelocity(0.0f);
+                    enable_motors = 1;
+                    robot_coord(0) = TRANSLATIONAL_VELOCITY;
+                    robot_coord(1) = 0.0f;
                     state = MOVE_FORWARD;
                 }
                 break;
-
-            // continue here    
+                
             case MOVE_FORWARD:
+
                 if (!do_execute_main_task) {
-                    controller.setTranslationalVelocity(0);
-                    controller.setRotationalVelocity(0);
+                    robot_coord(0) = 0.0f;
+                    robot_coord(1) = 0.0f;
                     state = SLOWING_DOWN;
-                    break;
-                }
-
-                // ???
-                if (irSensor_distance(2) < DISTANCE_THRESHOLD && irSensor_distance(2) < DISTANCE_THRESHOLD) {
-                    controller.setTranslationalVelocity(-TRANSLATIONAL_VELOCITY/2);
-                    controller.setRotationalVelocity(-ROTATIONAL_VELOCITY);
+                } else if ((irSensors[0].read() < DISTANCE_THRESHOLD) || (irSensors[1].read() < DISTANCE_THRESHOLD)) {
+                    robot_coord(0) = 0.0f;
+                    robot_coord(1) =  ROTATIONAL_VELOCITY;
+                    state = TURN_LEFT;
+                } else if (irSensors[5].read() < DISTANCE_THRESHOLD) {
+                    robot_coord(0) = 0.0f;
+                    robot_coord(1) = -ROTATIONAL_VELOCITY;
                     state = TURN_RIGHT;
-                    break;
-                // ???
-                } else if (irSensor_distance(4) < DISTANCE_THRESHOLD && irSensor_distance(4) < DISTANCE_THRESHOLD) {
-                    controller.setTranslationalVelocity(-TRANSLATIONAL_VELOCITY/2);
-                    controller.setRotationalVelocity(ROTATIONAL_VELOCITY);
-                    state = TURN_LEFT;
-                    break;
-                } else if (irSensor_distance(3) < DISTANCE_THRESHOLD/2) {
-                    controller.setTranslationalVelocity(-TRANSLATIONAL_VELOCITY);
-                    controller.setRotationalVelocity(-ROTATIONAL_VELOCITY);
-                    state = TURN_RIGHT;
-                    break;
+                } else {
+                    // leave it driving
                 }
-                
                 break;
                 
             case TURN_LEFT:
+
                 if (!do_execute_main_task) {
-                    controller.setTranslationalVelocity(0);
-                    controller.setRotationalVelocity(0);
+                    robot_coord(1) = 0.0f;
                     state = SLOWING_DOWN;
-                    break;
-                }
 
-                if ( (irSensor_distance(2) > DISTANCE_THRESHOLD) && (irSensor_distance(3) > DISTANCE_THRESHOLD) && (irSensor_distance(4) > DISTANCE_THRESHOLD) ) {
-                    controller.setRotationalVelocity(0);
-                    controller.setTranslationalVelocity(TRANSLATIONAL_VELOCITY);
+                } else if ((irSensors[0].read() > DISTANCE_THRESHOLD) && (irSensors[1].read() > DISTANCE_THRESHOLD) && (irSensors[5].read() > DISTANCE_THRESHOLD)) {
+                    robot_coord(0) = TRANSLATIONAL_VELOCITY;
+                    robot_coord(1) = 0.0f;
                     state = MOVE_FORWARD;
-                    break;
                 }
                 break;
                 
-            case TURN_RIGHT:  
+            case TURN_RIGHT:
+
                 if (!do_execute_main_task) {
-                    controller.setTranslationalVelocity(0);
-                    controller.setRotationalVelocity(0);
+                    robot_coord(1) = 0.0f;
                     state = SLOWING_DOWN;
-                    break;
-                }   
-
-                if ( (irSensor_distance(2) > DISTANCE_THRESHOLD) && (irSensor_distance(3) > DISTANCE_THRESHOLD) && (irSensor_distance(4) > DISTANCE_THRESHOLD) ) {
-                    controller.setRotationalVelocity(0);
-                    controller.setTranslationalVelocity(TRANSLATIONAL_VELOCITY);
+                } else if ((irSensors[0].read() > DISTANCE_THRESHOLD) && (irSensors[1].read() > DISTANCE_THRESHOLD) && (irSensors[5].read() > DISTANCE_THRESHOLD)) {
+                    robot_coord(0) = TRANSLATIONAL_VELOCITY;
+                    robot_coord(1) = 0.0f;
                     state = MOVE_FORWARD;
-                    break;
                 }
                 break;
                 
             case SLOWING_DOWN:
-                if (abs(controller.getActualTranslationalVelocity()) < VELOCITY_THRESHOLD 
-                    && abs(controller.getActualRotationalVelocity()) > VELOCITY_THRESHOLD) {
-                    state = ROBOT_OFF;
-                    enableMotorDriver = 0;
+                
+                if ((fabs(robot_coord_actual(0)) < VELOCITY_THRESHOLD) && (fabs(robot_coord_actual(1)) < VELOCITY_THRESHOLD)) {
+                    enable_motors = 0;
                     state = ROBOT_OFF;
                 }
                 
                 break;
-                
-            default:
-                
-                state = ROBOT_OFF;
+
         }
 
+        // transform robot coordinates to wheel speed
+        wheel_speed = Cwheel2robot.inverse() * robot_coord;
+
+        // command speedController objects
+        speedControllers[0]->setDesiredSpeedRPS(wheel_speed(0) / (2.0f * M_PI)); // set a desired speed for speed controlled dc motors M1
+        speedControllers[1]->setDesiredSpeedRPS(wheel_speed(1) / (2.0f * M_PI)); // set a desired speed for speed controlled dc motors M2
+        
         user_led = !user_led;
         
-        /*
-        if (do_execute_main_task)
-            printf("button pressed\r\n");
-        else
-            printf("button NOT pressed\r\n");
-        */
-        // printf("actual velocity: %.3f [m/s] / %.3f [rad/s]\r\n", controller.getActualTranslationalVelocity(), controller.getActualRotationalVelocity());
-        printf("%f, %f, %f, %f, %f, %f\r\n", irSensor_distance(0), irSensor_distance(1), irSensor_distance(2), irSensor_distance(3), irSensor_distance(4), irSensor_distance(5));
+        // do only output via serial what's really necessary (this makes your code slow)
+        printf("%f, %f\r\n", wheel_speed_actual(0), wheel_speed_actual(1));
         
         // read timer and make the main thread sleep for the remaining time span (non blocking)
-        auto main_task_elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(main_task_timer.elapsed_time()).count();
+        int main_task_elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(main_task_timer.elapsed_time()).count();
         thread_sleep_for(main_task_period_ms - main_task_elapsed_time_ms);
     }
 }