2026-05-09 11:23:45 +08:00
|
|
|
|
|
|
|
|
|
|
#include "mix_cc/ihyper_db.h"
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <base/BitTool.h>
|
|
|
|
|
|
#include <eqpalg/algs/roller3.h>
|
|
|
|
|
|
#include <eqpalg/exp_macro/get_macro_replaced_exp.h>
|
|
|
|
|
|
#include <eqpalg/feature_extraction/daa.h>
|
|
|
|
|
|
#include <eqpalg/utility/build_alarm_info.h>
|
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
int Roller3::init() {
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
try {
|
|
|
|
|
|
res += AlgBase::init();
|
|
|
|
|
|
this->con_monitor_.setThreshold(100);
|
|
|
|
|
|
|
|
|
|
|
|
logger_->Debug() << "离群群方式[-2:%;-3:实际值]:" << exp_type_ << std::endl;
|
|
|
|
|
|
logger_->Debug() << "res:" << res << std::endl;
|
|
|
|
|
|
if (res != 0) {
|
|
|
|
|
|
this->exp_is_wrong_ = true;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (rule_json_.at("output").contains("error")) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
error_str_ =
|
|
|
|
|
|
rule_json_.at("output").at("error").at("value").get<std::string>();
|
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
|
logger_->Error() << "output,error出错:" << e.what()
|
|
|
|
|
|
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
|
|
|
|
|
|
error_message_str_ += "报警内容格式异常!";
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
res += this->reload_config_data_source(); /*3.数据源*/
|
|
|
|
|
|
|
|
|
|
|
|
res += this->first_fill_mm_vars(); /*4.数据项*/
|
|
|
|
|
|
|
|
|
|
|
|
res += init_X_exp();
|
|
|
|
|
|
rule_stat_.unit = unit_;
|
|
|
|
|
|
print_load_content();
|
|
|
|
|
|
|
|
|
|
|
|
for (auto tagid : tag_seq_) {
|
|
|
|
|
|
state_info_map_[tagid] = HoldState::StateInfo();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
|
std::throw_with_nested(
|
|
|
|
|
|
mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
|
this->exp_is_wrong_ = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Roller3::Roller3(const string &name, const mix_cc::json &rule_json,
|
|
|
|
|
|
const string &ruleId, size_t exp_type)
|
|
|
|
|
|
: ExpBase(name, rule_json, ruleId, exp_type) {
|
|
|
|
|
|
logger_.reset(
|
|
|
|
|
|
new LOG("Roller3_" + std::to_string(exp_type) + ":" + rule_name_,
|
|
|
|
|
|
AUTO_CATCH_PID));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Roller3::~Roller3() {
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AlarmInfo Roller3::mon_proc() {
|
|
|
|
|
|
|
2026-05-15 13:08:30 +08:00
|
|
|
|
if (!expr_engine_->evaluateBool("act")) {
|
2026-05-09 11:23:45 +08:00
|
|
|
|
logger_->Debug() << "前提条件不满足!" << std::endl;
|
|
|
|
|
|
return AlarmInfo{};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*最新数据*/
|
|
|
|
|
|
for (int i = 0; i < value_num_; i++) {
|
|
|
|
|
|
values_[i] = std::fabs(mm_vars["tag" + std::to_string(tag_seq_[i])]);
|
|
|
|
|
|
if (values_[i] == 0) {
|
|
|
|
|
|
is_zero_list_[i] = 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
is_zero_list_[i] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*中位数*/
|
|
|
|
|
|
median_ = calculateMedian(values_);
|
|
|
|
|
|
/*允许偏差*/
|
|
|
|
|
|
double deviationMax = std::fabs(median_ * limit_error_ * 0.01);
|
|
|
|
|
|
double deviationWarn = std::fabs(median_ * limit_warn_ * 0.01);
|
|
|
|
|
|
if (exp_type_ == ExpType::OuterAct) {
|
|
|
|
|
|
deviationMax = limit_error_;
|
|
|
|
|
|
deviationWarn = limit_warn_;
|
|
|
|
|
|
}
|
|
|
|
|
|
/*数据偏差*/
|
|
|
|
|
|
for (int j = 0; j < value_num_; j++) {
|
|
|
|
|
|
deviations_[j] = std::fabs(values_[j] - median_);
|
|
|
|
|
|
if (is_zero_list_[j] == 1) {
|
|
|
|
|
|
deviations_[j] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*找最大偏差*/
|
|
|
|
|
|
auto maxIndexValue = findMaxWithIndex(deviations_);
|
|
|
|
|
|
|
|
|
|
|
|
limit_down_ = median_ - deviationWarn;
|
|
|
|
|
|
limit_up_ = median_ + deviationWarn;
|
|
|
|
|
|
rule_stat_.limit_down = get_up_down(limit_down_, 0);
|
|
|
|
|
|
rule_stat_.limit_up = get_up_down(limit_up_, 1);
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
rule_stat_.current_value =
|
|
|
|
|
|
std::fabs(mm_vars["tag" + std::to_string(maxIndexValue.first + 1)]);
|
|
|
|
|
|
|
|
|
|
|
|
/*无持续时间要求*/
|
|
|
|
|
|
if (hold_time_ <= this->delay_time_) {
|
|
|
|
|
|
/*报警检查*/
|
|
|
|
|
|
if (ExpBase::detect_up_down(rule_stat_.current_value)) {
|
|
|
|
|
|
std::string msg = "";
|
|
|
|
|
|
msg = error_str_ + "," +
|
|
|
|
|
|
SingletonTemplate<Item2Chines>::GetInstance()(
|
|
|
|
|
|
m_tags[maxIndexValue.first]) +
|
|
|
|
|
|
":" +
|
|
|
|
|
|
DAA::double2str(
|
|
|
|
|
|
std::fabs(
|
|
|
|
|
|
mm_vars["tag" + std::to_string(maxIndexValue.first + 1)]),
|
|
|
|
|
|
3) +
|
|
|
|
|
|
unit_ + ",合理区间:[" +
|
|
|
|
|
|
DAA::double2strLimit(rule_stat_.limit_down, 3) + "," +
|
|
|
|
|
|
DAA::double2strLimit(rule_stat_.limit_up, 3) + "]" + unit_;
|
|
|
|
|
|
auto alarm_time = get_alarm_time();
|
|
|
|
|
|
print_exp_vars();
|
|
|
|
|
|
logger_->Debug() << " median_:" << median_ << ",maxIndexValue:["
|
|
|
|
|
|
<< maxIndexValue.first << "," << maxIndexValue.second
|
|
|
|
|
|
<< "]," << msg << endl;
|
|
|
|
|
|
if (maxIndexValue.second > deviationMax) {
|
|
|
|
|
|
return utility::build_alarm_info("ERROR", rule_id_, rule_name_, "EXP16",
|
|
|
|
|
|
msg, alarm_time);
|
|
|
|
|
|
}
|
|
|
|
|
|
return utility::build_alarm_info("WARN", rule_id_, rule_name_, "EXP16",
|
|
|
|
|
|
msg, alarm_time);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
std::string msg = "";
|
|
|
|
|
|
msg = error_str_;
|
|
|
|
|
|
HoldState::AlarmType alarm_type = HoldState::AlarmType::Warn;
|
|
|
|
|
|
/*持续时间检测*/
|
|
|
|
|
|
for (int i = 0; i < value_num_; i++) {
|
|
|
|
|
|
int tagid = tag_seq_[i];
|
|
|
|
|
|
double n_value = values_[i];
|
|
|
|
|
|
HoldState::AlarmState up_down = Roller3::detect_up_down(n_value);
|
|
|
|
|
|
HoldState::StateInfo &n_state_info = state_info_map_[tagid];
|
|
|
|
|
|
std::string tag_name;
|
|
|
|
|
|
int idx = tag_seq_[i] - 1;
|
|
|
|
|
|
if (idx >= 0 && idx < m_tags.size()) {
|
|
|
|
|
|
tag_name = SingletonTemplate<Item2Chines>::GetInstance()(m_tags[idx]);
|
|
|
|
|
|
}
|
|
|
|
|
|
HoldState::AlarmType n_alarm_type = deviations_[i] > deviationMax
|
|
|
|
|
|
? HoldState::AlarmType::Error
|
|
|
|
|
|
: HoldState::AlarmType::Warn;
|
|
|
|
|
|
if (is_zero_list_[i] != 1 && up_down != HoldState::AlarmState::None) {
|
|
|
|
|
|
if (up_down == n_state_info.last_alarm_tate) {
|
|
|
|
|
|
n_state_info.alarm_type = n_alarm_type == HoldState::AlarmType::Warn
|
|
|
|
|
|
? n_alarm_type
|
|
|
|
|
|
: n_state_info.alarm_type;
|
|
|
|
|
|
if ((now_time_ - n_state_info.last_start_time) > hold_time_) {
|
|
|
|
|
|
/*报警*/
|
|
|
|
|
|
msg = msg + "," + tag_name + ":" +
|
|
|
|
|
|
DAA::double2str(std::fabs(n_value), 3) + unit_;
|
|
|
|
|
|
alarm_type = n_state_info.alarm_type;
|
|
|
|
|
|
n_state_info.last_start_time = now_time_;
|
|
|
|
|
|
n_state_info.alarm_type = HoldState::AlarmType::Error;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
n_state_info.last_start_time = now_time_;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
n_state_info.last_alarm_tate = up_down;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!msg.empty()) {
|
|
|
|
|
|
auto alarm_time = get_alarm_time();
|
|
|
|
|
|
print_exp_vars();
|
|
|
|
|
|
logger_->Debug() << " median_:" << median_ << ",maxIndexValue:["
|
|
|
|
|
|
<< maxIndexValue.first << "," << maxIndexValue.second
|
|
|
|
|
|
<< "]," << msg << endl;
|
|
|
|
|
|
if (alarm_type == HoldState::AlarmType::Error) {
|
|
|
|
|
|
return utility::build_alarm_info("ERROR", rule_id_, rule_name_, "EXP16",
|
|
|
|
|
|
msg, alarm_time);
|
|
|
|
|
|
}
|
|
|
|
|
|
return utility::build_alarm_info("WARN", rule_id_, rule_name_, "EXP16",
|
|
|
|
|
|
msg, alarm_time);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return AlarmInfo{};
|
|
|
|
|
|
}
|
|
|
|
|
|
std::vector<AlarmInfo> Roller3::exec_task(mix_cc::time_range_t time_range) {
|
|
|
|
|
|
std::vector<AlarmInfo> result;
|
|
|
|
|
|
for (auto now_time = time_range.get_left();
|
|
|
|
|
|
now_time <= time_range.get_right(); now_time += delay_time_) {
|
|
|
|
|
|
this->now_time_ = now_time;
|
|
|
|
|
|
auto rr1 = this->exec_mon();
|
|
|
|
|
|
result.push_back(rr1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Roller3::print_load_content() {
|
|
|
|
|
|
logger_->Debug() << "limit_error_:" << limit_error_
|
|
|
|
|
|
<< ",exp_str_:" << exp_str_ << ",tags_exp_:" << tags_exp_
|
|
|
|
|
|
<< std::endl;
|
|
|
|
|
|
logger_->Debug() << "limit_error_:" << limit_error_
|
|
|
|
|
|
<< ",limit_warn_:" << limit_warn_ << ",单位unit_:" << unit_
|
|
|
|
|
|
<< ",detect_mode_:" << detect_mode_
|
|
|
|
|
|
<< ",hold_time:" << hold_time_.count() << "ms" << std::endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Roller3::init_X_exp() {
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (rule_json_.at("function").contains("pre_exp")) {
|
|
|
|
|
|
string tmp_exp =
|
|
|
|
|
|
rule_json_.at("function").at("pre_exp").at("value").get<std::string>();
|
|
|
|
|
|
|
|
|
|
|
|
exp_str_ = get_macro_replaced_exp(tmp_exp);
|
|
|
|
|
|
res += init_hold_exp_str(exp_str_);
|
|
|
|
|
|
|
2026-05-15 13:08:30 +08:00
|
|
|
|
// ExpressionEngine::registerExpression() now handles FunVars processing internally.
|
2026-05-09 11:23:45 +08:00
|
|
|
|
feedback_mode_ = false;
|
|
|
|
|
|
auto messy_code = exp_messy_code_check(exp_str_);
|
|
|
|
|
|
if (messy_code == -1) {
|
|
|
|
|
|
this->error_code_list_.push_back(
|
|
|
|
|
|
{ErrorType::EnCodeError, ErrorLocation::ActExp});
|
|
|
|
|
|
res += messy_code;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rule_json_.at("function").contains("input")) {
|
|
|
|
|
|
tags_exp_ =
|
|
|
|
|
|
rule_json_.at("function").at("input").at("value").get<std::string>();
|
|
|
|
|
|
auto tag_seq = extractTagNumbers(tags_exp_);
|
|
|
|
|
|
if (tag_seq.empty()) {
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
std::sort(tag_seq.begin(), tag_seq.end());
|
|
|
|
|
|
tag_seq_ = tag_seq;
|
|
|
|
|
|
if (rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.contains("limit_error")) {
|
|
|
|
|
|
|
|
|
|
|
|
limit_error_ = std::stod(rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
}
|
|
|
|
|
|
if (rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.contains("limit_warn")) {
|
|
|
|
|
|
limit_warn_ = std::stod(rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("limit_warn")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rule_json_.at("function").at("input").at("param").contains("unit")) {
|
|
|
|
|
|
unit_ = rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("unit")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.contains("detect_mode")) {
|
|
|
|
|
|
detect_mode_ = std::stoi(rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("detect_mode")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
}
|
|
|
|
|
|
if (rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.contains("hold_time")) {
|
|
|
|
|
|
|
|
|
|
|
|
hold_time_ = milliseconds(std::stoi(rule_json_.at("function")
|
|
|
|
|
|
.at("input")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("hold_time")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
value_num_ = tag_seq_.size();
|
2026-05-15 13:08:30 +08:00
|
|
|
|
if (exp_str_ != "") {
|
|
|
|
|
|
int reg_ret = expr_engine_->registerExpression("act", exp_str_);
|
|
|
|
|
|
if (reg_ret != 0) {
|
2026-05-09 11:23:45 +08:00
|
|
|
|
this->error_code_list_.push_back(
|
|
|
|
|
|
{ErrorType::CalError, ErrorLocation::ActExp});
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-15 13:08:30 +08:00
|
|
|
|
if (tags_exp_ != "") {
|
|
|
|
|
|
int reg_ret = expr_engine_->registerExpression("result", tags_exp_);
|
|
|
|
|
|
if (reg_ret != 0) {
|
2026-05-09 11:23:45 +08:00
|
|
|
|
this->error_code_list_.push_back(
|
2026-05-15 13:08:30 +08:00
|
|
|
|
{ErrorType::CalError, ErrorLocation::ResultExp});
|
2026-05-09 11:23:45 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
deviations_.resize(value_num_, 0);
|
|
|
|
|
|
values_.resize(value_num_, 0);
|
|
|
|
|
|
is_zero_list_.resize(value_num_, 0);
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vector<int> Roller3::extractTagNumbers(const string &expr) {
|
|
|
|
|
|
vector<int> result;
|
|
|
|
|
|
const string tagPrefix = "tag"; // 定义要查找的前缀
|
|
|
|
|
|
size_t pos = 0; // 当前查找位置
|
|
|
|
|
|
|
|
|
|
|
|
while (pos < expr.size()) {
|
|
|
|
|
|
// 查找下一个 "tag" 的出现位置
|
|
|
|
|
|
size_t found = expr.find(tagPrefix, pos);
|
|
|
|
|
|
if (found == string::npos) {
|
|
|
|
|
|
break; // 没有更多 "tag",退出循环
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算数字部分的起始位置(在 "tag" 之后)
|
|
|
|
|
|
size_t numStart = found + tagPrefix.size();
|
|
|
|
|
|
size_t numEnd = numStart;
|
|
|
|
|
|
|
|
|
|
|
|
// 提取连续的数字字符序列(直到遇到非数字字符,如 '+' 或字符串结尾)
|
|
|
|
|
|
while (numEnd < expr.size() && isdigit(expr[numEnd])) {
|
|
|
|
|
|
numEnd++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果存在数字序列,则转换为整数并添加到结果中
|
|
|
|
|
|
if (numEnd > numStart) {
|
|
|
|
|
|
string numStr = expr.substr(numStart, numEnd - numStart);
|
|
|
|
|
|
try {
|
2026-05-09 13:32:24 +08:00
|
|
|
|
int num = stoi(numStr);
|
2026-05-09 11:23:45 +08:00
|
|
|
|
result.push_back(num);
|
|
|
|
|
|
} catch (const invalid_argument &e) {
|
|
|
|
|
|
// 处理无效数字字符串(例如非数字内容),根据需求可忽略或记录错误
|
|
|
|
|
|
// 这里选择跳过无效转换,继续处理后续部分
|
|
|
|
|
|
} catch (const out_of_range &e) {
|
|
|
|
|
|
// 处理数字超出 int 范围的情况,同样跳过
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新查找位置到当前数字序列的末尾,继续搜索
|
|
|
|
|
|
pos = numEnd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Roller3::calculateMedian(
|
|
|
|
|
|
std::vector<double> data) { // 传值以创建副本,不改变原向量
|
|
|
|
|
|
if (data.empty())
|
|
|
|
|
|
return 0.0;
|
|
|
|
|
|
size_t size = data.size();
|
2026-05-09 13:33:07 +08:00
|
|
|
|
std::sort(data.begin(), data.end());
|
2026-05-09 11:23:45 +08:00
|
|
|
|
|
|
|
|
|
|
if (size % 2 == 0) {
|
|
|
|
|
|
// 偶数个元素,取中间两个数的平均值
|
|
|
|
|
|
return (data[size / 2 - 1] + data[size / 2]) / 2.0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 奇数个元素,取中间的数
|
|
|
|
|
|
return data[size / 2];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 函数返回一个pair,first是下标,second是最大值
|
|
|
|
|
|
std::pair<int, double>
|
|
|
|
|
|
Roller3::findMaxWithIndex(const std::vector<double> &vec) {
|
|
|
|
|
|
// 检查vector是否为空
|
|
|
|
|
|
if (vec.empty()) {
|
|
|
|
|
|
return std::make_pair(-1, 0.0); // 返回无效值
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 13:32:24 +08:00
|
|
|
|
// 使用max_element找到最大元素的迭代器
|
2026-05-09 11:23:45 +08:00
|
|
|
|
auto max_iter = std::max_element(vec.begin(), vec.end());
|
|
|
|
|
|
|
|
|
|
|
|
int index = std::distance(vec.begin(), max_iter);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取最大值
|
|
|
|
|
|
double max_value = *max_iter;
|
|
|
|
|
|
|
|
|
|
|
|
return std::make_pair(index, max_value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Roller3::get_up_down(const double &value, bool is_up) {
|
|
|
|
|
|
switch (this->detect_mode_) {
|
|
|
|
|
|
case DetectMode::Default:
|
|
|
|
|
|
return value;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case DetectMode::OnlyLeft:
|
|
|
|
|
|
return is_up ? 32767 : value;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case DetectMode::OnlyRight:
|
|
|
|
|
|
return is_up ? value : -32768;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return value;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HoldState::AlarmState Roller3::detect_up_down(const double &value) {
|
|
|
|
|
|
switch (this->detect_mode_) {
|
|
|
|
|
|
case DetectMode::Default: {
|
|
|
|
|
|
if (value < this->limit_down_) {
|
|
|
|
|
|
return HoldState::AlarmState::DownLower;
|
|
|
|
|
|
} else if (value > limit_up_) {
|
|
|
|
|
|
return HoldState::AlarmState::UpHigher;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return HoldState::AlarmState::None;
|
|
|
|
|
|
}
|
|
|
|
|
|
} break;
|
|
|
|
|
|
case DetectMode::OnlyLeft:
|
|
|
|
|
|
return value < limit_down_ ? HoldState::AlarmState::DownLower
|
|
|
|
|
|
: HoldState::AlarmState::None;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case DetectMode::OnlyRight:
|
|
|
|
|
|
return value > limit_up_ ? HoldState::AlarmState::UpHigher
|
|
|
|
|
|
: HoldState::AlarmState::None;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return HoldState::AlarmState::None;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return HoldState::AlarmState::None;
|
|
|
|
|
|
}
|