#pragma once
#ifndef _PID_H_
#define _PID_H_
#include <vector>
#include <map>
using namespace std; struct kpid { float kp, ki, kd; long i; };
struct eval
{
float minrate;
float maxrate;
float avgrate;
float avgcalc;
float maxhold;
float minhold;
float avghold;
float varhold;
float countif;//平稳时间
float gradual;
};
struct score { kpid pid; eval _eval[]; };
typedef vector<score> scoretable;
typedef vector<scoretable> favortable;
class cmd
{
public:
virtual void setpid(const kpid& k)const {
printf("-------------------------cmdpid:%.2f,%.2f,%.2f\n", k.kp, k.ki, k.kd);
}
virtual void settarget(float t)const{
printf("-------------------------cmdtarget:%.2f\n",t);
}
virtual void report(const scoretable& table)const
{
FILE* file;
if ( == fopen_s(&file, "pid.table.txt", "a"))
{
for (scoretable::const_iterator it = table.begin(); it != table.end(); ++it)
{
const score& score = *it;
output(score, file);
}
}
fclose(file);
}
virtual void report(const favortable& table)const
{
printf("*************************print\n");
FILE* file;
if ( == fopen_s(&file, "pid.score.txt", "a"))
{
favortable::const_iterator it = table.begin();
for (; it != table.end(); ++it)
{
const scoretable& table = *it;
for (scoretable::const_iterator it = table.begin(); it != table.end(); ++it)
{
const score& score = *it;
output(score, file);
}
fprintf_s(file, "\r\n");
}
}
fclose(file);
}
virtual void trace(const score& score)const
{
FILE* file;
if ( == fopen_s(&file, "pid.trace.txt", "a"))
{
output(score, file);
}
fclose(file);
}
private:
void output(const score& score ,FILE* file)const
{
fprintf_s(file, "PID %5.2f %5.2f %5.2f : ", score.pid.kp, score.pid.ki, score.pid.kd);
for (int i = ; i < ; ++i) {
fprintf_s(file, "[%c] avg:%.2f/%.2f min:%.2f max:%.2f T:%.2f [T:%.2f (%.2f ~ %.2f) avg:%.2f]."
, "+-"[i]
, score._eval[i].avgrate
, score._eval[i].avgcalc
, score._eval[i].minrate
, score._eval[i].maxrate
, score._eval[i].gradual
, score._eval[i].countif
, score._eval[i].minhold
, score._eval[i].maxhold
, score._eval[i].avghold);
}
fprintf_s(file, "\r\n");
}
};
class pid
{
template<class T ,class H>
struct Template{
T val;
vector<H*> list[];
~Template() {
for (int i = ; i < ; ++i)
for (; !list[i].empty(); list[i].pop_back())
delete list[i].back();
}
};
enum tendecy { eupper = , elower = , efirst,equiet,etail,eidle};
struct data { float targetvalue; enum tendecy tendecy; int duration; };
struct temp { float temperature, interval;
temp(float t,float i):temperature(t),interval(i){}
};
typedef Template<data, temp> segment;
typedef Template<kpid, segment> piddata;
typedef vector<piddata *> pidsort;
public:
class policy
{
public:
policy(const kpid pid = { 1.0,0.0,0.0,})
: _target{ ,,,,, }
, _pid(pid),i(),k()
, entry()
{}
virtual const kpid& trimpid(const favortable&);
virtual float target()const;
virtual bool segment();
virtual bool oncepid();
virtual int count() { return ; }
protected:
kpid _pid;
float _target[];
unsigned int i,k;
map<float, int> _score;
const int entry;
};
public:
explicit pid(cmd*);
virtual ~pid();
void apply(policy*);
void init();
void fini();
void input(float temperature, float interval);
private:
void sort();
void score();
void eval(const segment * _segment,struct eval&); void incr(temp *);
void quiet(temp *);
void decr(temp *);
void first(float t);
void tail();
void stage();
void ctrl();
void newpid(const kpid&);
void newtarget(float target);
void endtarget();
void endpid();
void newapply();
void endapply();
private:
segment * _segment;
piddata * _piddata;
pidsort * _pidsort;
private:
enum tendecy _state;
private:
scoretable _scoretable;
favortable _favortable;
cmd* _cmd;
policy* _policy;
vector<policy*> _policylist;
};
#endif #include "pid.h"
#include <assert.h>
#include <algorithm>
#include <limits> class defaultpolicy :public pid::policy
{
public:
const kpid& trimpid(const favortable& t)
{
switch (k)
{
case :
if (_pid.kp < 2.0f)
{
_pid.kp += 0.01;
break;
}
else
{
_pid.i = k = ;
}
case :
if (_pid.ki < 1.2f)
{
_pid.ki += 0.001;
break;
}
else
{
_pid.i = k = ;
}
case :
if (_pid.kd < 1.2f)
{
_pid.kd += 0.001;
break;
}
else
{
_pid.i = k = ;
}
default:
break;
}
return _pid;
}
};
const kpid& pid::policy::trimpid(const favortable& t)
{
if ( k < t.size())
{
const scoretable& _table = t[k]; struct kpid pid;
struct eval val = {};
if (!_table.empty())
{
pid = _table[].pid;
val = _table[]._eval[];
}
else
pid = _pid;
switch (k)
{
case :
_pid.kp += pid.kp >= _pid.kp ? +0.005f : -0.005f;
if (++_score[_pid.kp] > entry)
{
_pid.i = k = ;
_score.clear();
}
if (val.gradual < )
{
break;
}
case :
_pid.ki += pid.ki >= _pid.ki ? +0.001f : -0.001f;
if (++_score[_pid.ki] > entry)
{
_pid.i = k = ;
_score.clear();
}
break;
case :
_pid.kd += pid.kd >= _pid.kd ? +0.001f : -0.001f;
if (++_score[_pid.kd] > entry)
{
_pid.i = k = ;
_score.clear();
}
break;
default:
break;
}
}
return _pid;
}
bool pid::policy::oncepid()
{
return k < ;
}
float pid::policy::target()const
{
return _target[i% _countof(_target)];
}
bool pid::policy::segment()
{
return == (++i % _countof(_target));
} pid::pid(cmd* c)
: _state(eidle)
, _cmd(c)
, _policy(new defaultpolicy())
{
assert(c);
apply(_policy);
}
void pid::apply(policy* p)
{
_policylist.push_back(p);
_policy = p;
}
void pid::init()
{
_favortable.resize();
_pidsort = new pidsort();
newpid(_policy->trimpid(_favortable));
newtarget(_policy->target());
}
void pid::fini()
{
endtarget();
endpid();
score();
sort();
_cmd->trace(_scoretable.back());
std::sort(_scoretable.begin(), _scoretable.end(),[](auto a, auto b){return a._eval[].avgrate > b._eval[].avgrate; });
_cmd->report(_scoretable);
_cmd->report(_favortable);
_favortable.clear();
while (!_pidsort->empty())
{
delete _pidsort->back();
_pidsort->pop_back();
}
delete _pidsort;
while (!_policylist.empty())
{
delete _policylist.back();
_policylist.pop_back();
}
}
pid::~pid()
{
delete _cmd;
}
void pid::newapply()
{
_policy = _policylist.back();
}
void pid::endapply()
{
std::rotate(_policylist.begin(), _policylist.begin() + , _policylist.end());
}
void pid::newpid(const kpid& k)
{
_cmd->setpid(k);
_piddata = new piddata();
_piddata->val = k;
}
void pid::newtarget(float target)
{
_cmd->settarget(target);
_segment = new segment();
_segment->val.targetvalue = target;
_state = efirst;
}
void pid::ctrl()
{
endtarget();
if (_policy->segment())
{
endpid();
score();
sort();
_cmd->trace(_scoretable.back());
if (_policy->oncepid())
{
endapply();
newapply();
}
newpid(_policy->trimpid(_favortable));
}
newtarget(_policy->target());
}
void pid::stage()
{
_segment->val.duration = ;
_state = equiet;
}
void pid::quiet(temp * t)
{
_segment->list[].push_back(t);
_segment->val.duration++;
}
void pid::incr(temp * t)
{
_segment->list[].push_back(t);
}
void pid::decr(temp * t)
{
_segment->list[].push_back(t);
}
void pid::endpid()
{
_pidsort->push_back(_piddata);
}
void pid::endtarget()
{
_piddata->list[_segment->val.tendecy].push_back(_segment);
}
void pid::first(float t)
{
_state = _segment->val.targetvalue > t ? eupper : elower;
_segment->val.tendecy = _state;
}
void pid::tail()
{
_state = etail;
}
void pid::input(float t, float i)
{
assert(_segment);
for(;;)
switch (_state)
{
case efirst:
first(t);
break;
case eupper:
incr(new temp(t,i));
if (_segment->val.targetvalue < t)
{
stage();
break;
}
return;
case elower:
decr(new temp(t, i));
if (_segment->val.targetvalue > t)
{
stage();
break;
}
return;
case equiet:
quiet(new temp(t, i));
if (_segment->val.duration > _policy->count())
{
tail();
break;
}
return;
case etail:
ctrl();
return;
case eidle:
return;
}
}
void pid::eval(const segment * _segment, struct eval& _eval)
{
int i;
auto v = _segment->list;
switch (_segment->val.tendecy)
{
case eupper:
case elower:
struct cnt
{
cnt(float t, float& q, bool b = true)
: target(t)
, quiet(q)
, cmpval(b)
{
quiet = .f;
}
bool operator()(const struct temp* a)
{
bool b = a->temperature > target + 0.5
|| a->temperature < target - 0.5;
if (cmpval == b)
{
quiet += a->interval;
return true;
}
else
return false;
}
float &quiet;
float target;
bool cmpval;
};
i = ;
if (!v[i].empty())
{
_eval.minrate = FLT_MAX;
_eval.maxrate = FLT_MIN;
_eval.avgrate = .0f;
auto it = v[i].begin();
float _t = (*it)->temperature;
while (++it != v[i].end())
{
float r = ((*it)->temperature - _t) / (*it)->interval;
_t = (*it)->temperature;
if (r > _eval.maxrate)
_eval.maxrate = r;
if (r < _eval.minrate)
_eval.minrate = r;
_eval.avgrate += r;
}
_eval.avgrate /= v[i].size();
std::count_if(v[i].begin(), v[i].end(), cnt(_segment->val.targetvalue, _eval.gradual, false));
/**/
float cost = .f;
it = v[i].begin();
while (++it != v[i].end())
cost += (*it)->interval;
_eval.avgcalc = (v[i].back()->temperature - v[i].front()->temperature) / cost;
}
i = ;
if (!v[i].empty())
{
struct cmp {
bool operator()(const struct temp* a, const struct temp* b) {
return a->temperature > b->temperature;
}
};
auto it = v[i].begin();
auto minmax = std::minmax_element(it + , v[i].end(), cmp());
_eval.maxhold = (*minmax.first)->temperature - _segment->val.targetvalue;
_eval.minhold = (*minmax.second)->temperature - _segment->val.targetvalue;
std::count_if(v[i].begin(), v[i].end(), cnt(_segment->val.targetvalue, _eval.countif, true));
/**/
float temp = .f;
for (; it != v[i].end(); ++it)
temp +=abs((*it)->temperature - _segment->val.targetvalue);
_eval.avghold = temp / v[i].size();
_eval.varhold = .f;
}
break;
}
}
void pid::score()
{
struct score _score;
struct eval _eval;
_score.pid = _piddata->val;
for (int i = ; i < ; ++i)
{
_score._eval[i].maxrate = FLT_MIN;
_score._eval[i].minrate = FLT_MAX;
_score._eval[i].gradual = FLT_MIN;
_score._eval[i].maxhold = FLT_MIN;
_score._eval[i].minhold = FLT_MAX;
_score._eval[i].varhold = FLT_MIN;
_score._eval[i].countif = FLT_MIN;
_score._eval[i].avghold = .f;
_score._eval[i].avgcalc = .f;
_score._eval[i].avgrate = .f;
for (int j = ; j < _piddata->list[i].size(); ++j)
{
eval(_piddata->list[i][j], _eval); if (_eval.maxrate > _score._eval[i].maxrate)
_score._eval[i].maxrate = _eval.maxrate;
if (_eval.minrate < _score._eval[i].minrate)
_score._eval[i].minrate = _eval.minrate;
if (_eval.gradual > _score._eval[i].gradual)
_score._eval[i].gradual = _eval.gradual; if (_eval.maxhold > _score._eval[i].maxhold)
_score._eval[i].maxhold = _eval.maxhold;
if (_eval.minhold < _score._eval[i].minhold)
_score._eval[i].minhold = _eval.minhold; if (_eval.varhold > _score._eval[i].varhold)
_score._eval[i].varhold = _eval.varhold;
if (_eval.countif > _score._eval[i].countif)
_score._eval[i].countif = _eval.countif; _score._eval[i].avgrate += _eval.avgrate;
_score._eval[i].avgcalc += _eval.avgcalc; _score._eval[i].avghold += _eval.avghold;
}
_score._eval[i].avgcalc /= _piddata->list[i].size();
_score._eval[i].avgrate /= _piddata->list[i].size();
_score._eval[i].avghold /= _piddata->list[i].size();
}
_scoretable.push_back(_score);
}
void pid::sort()
{
struct cmp
{
cmp(int t=) {}
bool operator()(const struct score& a, const struct score& b) const
{
switch (t)
{
case :
return a._eval[].avgrate > b._eval[].avgrate;
case :
return (a._eval[].maxhold - a._eval[].minhold) > (b._eval[].maxhold - b._eval[].minhold);
case :
return (a._eval[].maxrate - a._eval[].minrate) < (b._eval[].maxrate - b._eval[].minrate);
default:
return a._eval[].maxrate > b._eval[].maxrate;
}
}
int t;
};
int topnum = _scoretable.end() - _scoretable.begin();
topnum = min(topnum, );
for (size_t i = ; i < _favortable.size(); ++i)
{
_favortable[i].resize(topnum);
std::partial_sort_copy(_scoretable.begin(), _scoretable.end()
, _favortable[i].begin(), _favortable[i].end(), cmp(i));
}
}

温控PID自测验程序的更多相关文章

  1. linux根据进程号PID查找启动程序的全路径

    linux根据进程号PID查找启动程序的全路径 2014-01-25 11:09 18629人阅读 评论(0) 收藏 举报  分类: Linux系统管理(29)  版权声明:本文为博主原创文章,未经博 ...

  2. supervisor :a running process with pid = 0,程序PID为0

    Neo君作为一只小白,今天踩到了一个supervisor的坑. 如上图所示,出现这种情况后,想把这个进程停止.或者重启,甚至stop all它还是这个样子,如下图(马赛克部分为进程名称): 一:背景 ...

  3. Windows 查看端口使用、根据pid查找引用程序

    1.查看特定端口的使用情况:以80端口为例,输入命令 netstat -aon|findstr "80" 2.根据PID号找到对应的程序:以PID是6776为例,输入命令taskl ...

  4. Linux 根据PID找到相应应用程序的运行目录

    1.找到运行程序的PID # ps aux | grep redis root pts/ S+ : : grep redis root ? Ssl Aug30 : redis-server *: # ...

  5. 获取fork+exec启动的程序的PID值

    问题背景     业务中有个场景需要自动起一个A程序(由于A程序与 sublime_text 启动后遇到的问题有相似之处,后文就用 sublime_text 来替代A程序,当A程序与 sublime_ ...

  6. linux 程序管理与SElinux

    此文涉及的命令:&.jobs.fg.bg.kill.nohup.ps.top.pstree.free.uname.uptime.netstat.dmesg.vmstat.fuser.lsof. ...

  7. 增量式PID简单翻板角度控制

    1.研究背景 随着电子技术.信息技术和自动控制理论技术的完善与发展,近来微型处理器在控制方面的应用也越来越多.随之逐渐渗透到我们生活的各个领域.如导弹导航装置,飞机上仪表的控制,网络通讯与数据传输,工 ...

  8. linux 程序管理

    在linux下做开发,经常要用到一些管理程序的命令,如查看进程,查看内存等情况.看网络情况.如下的笔记是看书时记下一些简单常用的命令. 1)top [root@005 fsh]#top[-d数字]|t ...

  9. 【程序与资源】linux程序与资源管理

    程序与资源管理:ps.top.free.sar.kill.uname ①ps语法: [root @test /root ]# ps -aux 参数说明: a   :选择所有的程序列出 u   :所有使 ...

随机推荐

  1. 【 Linux 】Systemd 配置文件说明及编写(2)

    1. 开机启动 对于支持 systemd 的软件,如果想要设置开机启动,就执行如下命令(以 http 为例): systemctl enable httpd 上面的命令相当于在 /etc/system ...

  2. FreeRTOS 时间片,外部中断,任务优先级的一个疑问

    时间片1ms 假设有两个任务,A和B,A任务等待中断里面发出的信号量,B任务在运行 此时,B任务运行了300us的时候中断发生,发出信号量,那么任务A接收到信号量,A任务优先级高,A任务运行 有个问题 ...

  3. Office 2010 经验总结

    1. 如何设置蓝底白字? 答:点击菜单项上的"页面布局"→"页面颜色",就可以选择喜欢的页面颜色,字体颜色也会跟着发生改变. 补充:如果不喜欢相应的页面颜色中系 ...

  4. sql 表的连接与查找

    A.left outer join: 左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行. SQL: select a.a, a.b, a.c, b.c, b.d, b.f fro ...

  5. SELinux安全子系统的学习

    SELinux(Security-Enhanced Linux)是美国国家安全局在 Linux 开源社区的帮助下开发的 一个强制访问控制(MAC,Mandatory Access Control)的安 ...

  6. mysql left join 右表数据不唯一的情况解决方法

    mysql left join 右表数据不唯一的情况解决方法 <pre>member 表id username1 fdipzone2 terry member_login_log 表id ...

  7. ubuntu 安装 iperf

    iperf的github https://github.com/esnet/iperf/releases 解压 sudo tar -zvxf iperf-3.6.tar.gz -C /usr/loca ...

  8. Variational Auto-encoder(VAE)变分自编码器-Pytorch

    import os import torch import torch.nn as nn import torch.nn.functional as F import torchvision from ...

  9. 用pytorch1.0快速搭建简单的神经网络

    用pytorch1.0搭建简单的神经网络 import torch import torch.nn.functional as F # 包含激励函数 # 建立神经网络 # 先定义所有的层属性(__in ...

  10. 过滤器( filter )的使用

    转自:https://www.jianshu.com/p/2ea2b0e4d1f2 过滤器通常 在 web 服务端用的比较多,有要功能 在客户端的请求访问后端资源之前,拦截这些请求. 在服务器的响应发 ...