bug fixes

This commit is contained in:
Inex Code 2021-05-11 16:16:28 +00:00
parent 6478ccacb7
commit df3f9f9dbf

View file

@ -11,15 +11,16 @@
#include <cpprest/uri.h> #include <cpprest/uri.h>
#include <cpprest/json.h> #include <cpprest/json.h>
using namespace utility; // Common utilities like string conversions using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs. using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality using namespace web::http; // Common HTTP functionality
using namespace web::http::experimental::listener; // HTTP listener using namespace web::http::experimental::listener; // HTTP listener
using namespace concurrency::streams; // Asynchronous streams using namespace concurrency::streams; // Asynchronous streams
using namespace std; using namespace std;
class PIDImpl { class PIDImpl
{
public: public:
// Kp - proportional gain // Kp - proportional gain
// Ki - Integral gain // Ki - Integral gain
@ -47,14 +48,7 @@ private:
* Implementation * Implementation
*/ */
PIDImpl::PIDImpl(double dt, double max, double min, double Kp, double Kd, double Ki) PIDImpl::PIDImpl(double dt, double max, double min, double Kp, double Kd, double Ki)
: _dt(dt) : _dt(dt), _max(max), _min(min), _Kp(Kp), _Kd(Kd), _Ki(Ki), _pre_error(0), _integral(0)
, _max(max)
, _min(min)
, _Kp(Kp)
, _Kd(Kd)
, _Ki(Ki)
, _pre_error(0)
, _integral(0)
{ {
} }
@ -97,7 +91,8 @@ PIDImpl::~PIDImpl()
{ {
} }
enum ECmd { enum ECmd
{
ENone, ENone,
EExit EExit
}; };
@ -115,7 +110,8 @@ float getHZadFromUser()
return 10.; return 10.;
} }
class Bear { class Bear
{
float h; float h;
float m; float m;
float v; float v;
@ -124,10 +120,10 @@ class Bear {
public: public:
Bear() Bear()
{ {
v = 0; // m/s v = 0; // m/s
a = 0; // m/s2 a = 0; // m/s2
m = 10; // kg m = 10; // kg
h = 0; // Текущая высота h = 0; // Текущая высота
} }
float getH() float getH()
{ {
@ -153,7 +149,8 @@ public:
h = h + dh; h = h + dh;
a = (extrnForce - 9.8 * m) / m; // m * a = mg - F a = (extrnForce - 9.8 * m) / m; // m * a = mg - F
if (h < 0) { // Stay on the ground if (h < 0)
{ // Stay on the ground
h = 0.; h = 0.;
v = 0.; v = 0.;
a = 0.; a = 0.;
@ -171,11 +168,10 @@ public:
} }
}; };
class Engine; class Engine
{
class Engine {
float enginePower = 0; // n 0..500 n float enginePower = 0; // n 0..500 n
float maxPower; // n float maxPower; // n
public: public:
Engine(float imaxPower) Engine(float imaxPower)
{ {
@ -199,16 +195,15 @@ public:
} }
}; };
class SmartFlyingBear : public Bear { class SmartFlyingBear : public Bear
PIDImpl* pid; {
Engine* pengine; unique_ptr<PIDImpl> pid;
unique_ptr<Engine> pengine;
float hZad; float hZad;
public: public:
SmartFlyingBear(PIDImpl* ppid, Engine* ppengine) SmartFlyingBear(PIDImpl *ppid, Engine *ppengine) : pid(ppid), pengine(ppengine)
{ {
pid = ppid;
pengine = ppengine;
hZad = 0; hZad = 0;
} }
@ -220,11 +215,13 @@ public:
virtual void calc(float dt, float extrnForce) virtual void calc(float dt, float extrnForce)
{ {
float enginePowerPercent = 0; float enginePowerPercent = 0;
if (pid != nullptr) { if (pid != nullptr)
{
enginePowerPercent = pid->calculate(hZad, getH()); enginePowerPercent = pid->calculate(hZad, getH());
} }
if (pengine != nullptr) { if (pengine != nullptr)
{
pengine->setPower(enginePowerPercent); pengine->setPower(enginePowerPercent);
Bear::calc(dt, extrnForce + pengine->getForce()); Bear::calc(dt, extrnForce + pengine->getForce());
} }
@ -238,17 +235,19 @@ int model()
//Bear pooh; //Bear pooh;
SmartFlyingBear superpooh(new PIDImpl(0.1, 100, -100, 0.15, 0.001, 0.01), new Engine(500.)); SmartFlyingBear superpooh(new PIDImpl(0.1, 100, -100, 0.15, 0.001, 0.01), new Engine(500.));
float t = 0; // Время моделирования float t = 0; // Время моделирования
float dt = 0.1; // s float dt = 0.1; // s
float lastT = -5; float lastT = -5;
float hZad = 0; // Измененение высоты за шаг моделирования float hZad = 0; // Измененение высоты за шаг моделирования
while (cmd != EExit) { while (cmd != EExit)
{
mtx.lock(); mtx.lock();
hZad = targetH; // Неблокирующая функция для получения высоты hZad = targetH; // Неблокирующая функция для получения высоты
mtx.unlock(); mtx.unlock();
if (abs(superpooh.getH() - hZad) < 1 && abs(t - lastT) > 5) { if (abs(superpooh.getH() - hZad) < 1 && abs(t - lastT) > 5)
{
superpooh.eat(0.1); superpooh.eat(0.1);
lastT = t; lastT = t;
} }
@ -258,9 +257,12 @@ int model()
t = t + dt; t = t + dt;
if (t < 200) { if (t < 200)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} else { }
else
{
std::cout << "Weight = " << superpooh.getM() << std::endl; std::cout << "Weight = " << superpooh.getM() << std::endl;
std::cout << "Velocity = " << superpooh.getV() << std::endl; std::cout << "Velocity = " << superpooh.getV() << std::endl;
std::cout << "Acceleration = " << superpooh.getA() << std::endl; std::cout << "Acceleration = " << superpooh.getA() << std::endl;
@ -278,74 +280,93 @@ void handle_signal(int s)
cmd = EExit; cmd = EExit;
} }
bool is_authentificated(http_request message) { bool is_authentificated(http_request message)
{
auto headers = message.headers(); auto headers = message.headers();
if (message.headers().find("Authorization") == headers.end()) return false; if (message.headers().find("Authorization") == headers.end())
return false;
auto authHeader = headers["Authorization"]; auto authHeader = headers["Authorization"];
auto credsPos = authHeader.find("Basic"); auto credsPos = authHeader.find("Basic");
if (credsPos == std::string::npos) if (credsPos == std::string::npos)
return false; return false;
auto base64 = authHeader.substr(credsPos + std::string("Basic").length() + 1); auto base64 = authHeader.substr(credsPos + std::string("Basic").length() + 1);
if (base64.empty()) return false; if (base64.empty())
return false;
auto bytes = utility::conversions::from_base64(base64); auto bytes = utility::conversions::from_base64(base64);
std::string creds(bytes.begin(), bytes.end()); std::string creds(bytes.begin(), bytes.end());
auto colonPos = creds.find(":"); auto colonPos = creds.find(":");
if (colonPos == std::string::npos) return false; if (colonPos == std::string::npos)
return false;
auto user = creds.substr(0, colonPos); auto user = creds.substr(0, colonPos);
auto password = creds.substr(colonPos + 1, creds.size() - colonPos - 1); auto password = creds.substr(colonPos + 1, creds.size() - colonPos - 1);
if (user == "pooh" && password == "honey") { if (user == "pooh" && password == "honey")
{
return true; return true;
} else { }
else
{
return false; return false;
} }
} }
void handle_get(http_request message){ void handle_get(http_request message)
cout<<"Handle get: "<<message.to_string()<<endl; {
if (is_authentificated(message)) { cout << "Handle get: " << message.to_string() << endl;
if (is_authentificated(message))
{
json::value jsonObject; json::value jsonObject;
jsonObject[U("target_height")] = json::value::number(targetH); jsonObject[U("target_height")] = json::value::number(targetH);
message.reply(status_codes::OK,jsonObject); message.reply(status_codes::OK, jsonObject);
} else { }
else
{
message.reply(status_codes::Forbidden); message.reply(status_codes::Forbidden);
} }
} }
void handle_post(http_request message){ void handle_post(http_request message)
cout<<"Handle post: "<<message.to_string()<<endl; {
cout << "Handle post: " << message.to_string() << endl;
if (is_authentificated(message)) {
if (is_authentificated(message))
{
json::value jsonObject; json::value jsonObject;
try{ try
{
message.extract_json() message.extract_json()
.then([&jsonObject](json::value jo){ .then([&jsonObject](json::value jo) {
cout<<"Val:"<<jo.serialize() << endl; cout << "Val:" << jo.serialize() << endl;
jsonObject = jo; jsonObject = jo;
mtx.lock(); const lock_guard<mutex> lock(mtx);
targetH = jsonObject.at(U("target_height")).as_number().to_double(); targetH = jsonObject.at(U("target_height")).as_number().to_double();
cout<<"Val:"<<targetH<< endl; cout << "Val:" << targetH << endl;
mtx.unlock();
}) })
.wait(); .wait();
} }
catch (const std::exception & e) { catch (const exception &e)
{
printf("Error exception:%s\n", e.what()); printf("Error exception:%s\n", e.what());
} }
message.reply(status_codes::OK,jsonObject); message.reply(status_codes::OK, jsonObject);
} else { }
else
{
message.reply(status_codes::Forbidden); message.reply(status_codes::Forbidden);
} }
} }
void handle_quit(http_request message){ void handle_quit(http_request message)
cout<<"Handle quit: "<<message.to_string()<<endl; {
if (is_authentificated(message)) { cout << "Handle quit: " << message.to_string() << endl;
if (is_authentificated(message))
{
cmd = EExit; cmd = EExit;
message.reply(status_codes::OK); message.reply(status_codes::OK);
} else { }
else
{
message.reply(status_codes::Forbidden); message.reply(status_codes::Forbidden);
} }
} }
@ -355,23 +376,26 @@ int main()
int rc = 0; int rc = 0;
web::http::experimental::listener::http_listener web::http::experimental::listener::http_listener
listener(U("http://localhost:8080/")); listener(U("http://localhost:8080/"));
listener.support(methods::GET,handle_get); listener.support(methods::GET, handle_get);
listener.support(methods::POST,handle_post); listener.support(methods::POST, handle_post);
listener.support(methods::DEL,handle_quit); listener.support(methods::DEL, handle_quit);
try{ try
{
std::thread th(model); std::thread th(model);
listener.open() listener.open()
.then([&listener](){printf("\nStarting svrRest\n");}) .then([&listener]() { printf("\nStarting svrRest\n"); })
.wait(); .wait();
while(cmd != EExit); while (cmd != EExit)
;
th.join(); th.join();
} }
catch (const std::exception & e) { catch (const std::exception &e)
printf("Error exception:%s\n", e.what()); {
} printf("Error exception:%s\n", e.what());
}
signal(SIGINT, handle_signal); signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal); signal(SIGTERM, handle_signal);