summaryrefslogtreecommitdiff
path: root/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thermal/virtualtemp_estimator/virtualtemp_estimator.cpp')
-rw-r--r--thermal/virtualtemp_estimator/virtualtemp_estimator.cpp305
1 files changed, 259 insertions, 46 deletions
diff --git a/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp b/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
index 2dc2185c..e5374714 100644
--- a/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
+++ b/thermal/virtualtemp_estimator/virtualtemp_estimator.cpp
@@ -24,12 +24,12 @@ namespace thermal {
namespace vtestimator {
void VirtualTempEstimator::LoadTFLiteWrapper() {
- if (!data_) {
- LOG(ERROR) << "data_ is nullptr during LoadTFLiteWrapper";
+ if (!tflite_instance_) {
+ LOG(ERROR) << "tflite_instance_ is nullptr during LoadTFLiteWrapper";
return;
}
- std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+ std::unique_lock<std::mutex> lock(tflite_instance_->tflite_methods.mutex);
void *mLibHandle = dlopen("/vendor/lib64/libthermal_tflite_wrapper.so", 0);
if (mLibHandle == nullptr) {
@@ -37,122 +37,335 @@ void VirtualTempEstimator::LoadTFLiteWrapper() {
return;
}
- data_->tflite_methods.create =
+ tflite_instance_->tflite_methods.create =
reinterpret_cast<tflitewrapper_create>(dlsym(mLibHandle, "Create"));
- if (!data_->tflite_methods.create) {
+ if (!tflite_instance_->tflite_methods.create) {
LOG(ERROR) << "Could not link and cast tflitewrapper_create with error: " << dlerror();
}
- data_->tflite_methods.init = reinterpret_cast<tflitewrapper_init>(dlsym(mLibHandle, "Init"));
- if (!data_->tflite_methods.init) {
+ tflite_instance_->tflite_methods.init =
+ reinterpret_cast<tflitewrapper_init>(dlsym(mLibHandle, "Init"));
+ if (!tflite_instance_->tflite_methods.init) {
LOG(ERROR) << "Could not link and cast tflitewrapper_init with error: " << dlerror();
}
- data_->tflite_methods.invoke =
+ tflite_instance_->tflite_methods.invoke =
reinterpret_cast<tflitewrapper_invoke>(dlsym(mLibHandle, "Invoke"));
- if (!data_->tflite_methods.invoke) {
+ if (!tflite_instance_->tflite_methods.invoke) {
LOG(ERROR) << "Could not link and cast tflitewrapper_invoke with error: " << dlerror();
}
- data_->tflite_methods.destroy =
+ tflite_instance_->tflite_methods.destroy =
reinterpret_cast<tflitewrapper_destroy>(dlsym(mLibHandle, "Destroy"));
- if (!data_->tflite_methods.destroy) {
+ if (!tflite_instance_->tflite_methods.destroy) {
LOG(ERROR) << "Could not link and cast tflitewrapper_destroy with error: " << dlerror();
}
}
-VirtualTempEstimator::VirtualTempEstimator(size_t num_input_samples) {
- data_ = std::make_unique<VirtualTempEstimatorTFLiteData>(num_input_samples);
- LoadTFLiteWrapper();
+VirtualTempEstimator::VirtualTempEstimator(VtEstimationType estimationType,
+ size_t num_linked_sensors) {
+ type = estimationType;
+
+ common_instance_ = std::make_unique<VtEstimatorCommonData>(num_linked_sensors);
+ if (estimationType == kUseMLModel) {
+ tflite_instance_ = std::make_unique<VtEstimatorTFLiteData>();
+ LoadTFLiteWrapper();
+ } else if (estimationType == kUseLinearModel) {
+ linear_model_instance_ = std::make_unique<VtEstimatorLinearModelData>();
+ } else {
+ LOG(ERROR) << "Unsupported estimationType [" << estimationType << "]";
+ }
}
VirtualTempEstimator::~VirtualTempEstimator() {
LOG(INFO) << "VirtualTempEstimator destructor";
}
-VtEstimatorStatus VirtualTempEstimator::Initialize(const char *model_path) {
- LOG(INFO) << "Initialize VirtualTempEstimator\n";
+VtEstimatorStatus VirtualTempEstimator::LinearModelInitialize(LinearModelInitData data) {
+ if (linear_model_instance_ == nullptr || common_instance_ == nullptr) {
+ LOG(ERROR) << "linear_model_instance_ or common_instance_ is nullptr during Initialize";
+ return kVtEstimatorInitFailed;
+ }
+
+ size_t num_linked_sensors = common_instance_->num_linked_sensors;
+ std::unique_lock<std::mutex> lock(linear_model_instance_->mutex);
- if (!data_) {
- LOG(ERROR) << "data_ is nullptr during Initialize\n";
+ if ((num_linked_sensors == 0) || (data.coefficients.size() == 0) ||
+ (data.prev_samples_order == 0)) {
+ LOG(ERROR) << "Invalid num_linked_sensors [" << num_linked_sensors
+ << "] or coefficients.size() [" << data.coefficients.size()
+ << "] or prev_samples_order [" << data.prev_samples_order << "]";
return kVtEstimatorInitFailed;
}
- std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+ if (data.coefficients.size() != (num_linked_sensors * data.prev_samples_order)) {
+ LOG(ERROR) << "In valid args coefficients.size()[" << data.coefficients.size()
+ << "] num_linked_sensors [" << num_linked_sensors << "] prev_samples_order["
+ << data.prev_samples_order << "]";
+ return kVtEstimatorInvalidArgs;
+ }
+
+ common_instance_->use_prev_samples = data.use_prev_samples;
+ common_instance_->prev_samples_order = data.prev_samples_order;
+
+ linear_model_instance_->input_samples.reserve(common_instance_->prev_samples_order);
+ linear_model_instance_->coefficients.reserve(common_instance_->prev_samples_order);
- if (!model_path) {
+ // Store coefficients
+ for (size_t i = 0; i < data.prev_samples_order; ++i) {
+ std::vector<float> single_order_coefficients;
+ for (size_t j = 0; j < num_linked_sensors; ++j) {
+ single_order_coefficients.emplace_back(data.coefficients[i * num_linked_sensors + j]);
+ }
+ linear_model_instance_->coefficients.emplace_back(single_order_coefficients);
+ }
+
+ common_instance_->cur_sample_index = 0;
+ common_instance_->offset = data.offset;
+ common_instance_->is_initialized = true;
+
+ return kVtEstimatorOk;
+}
+
+VtEstimatorStatus VirtualTempEstimator::TFliteInitialize(MLModelInitData data) {
+ if (!tflite_instance_ || !common_instance_) {
+ LOG(ERROR) << "tflite_instance_ or common_instance_ is nullptr during Initialize\n";
+ return kVtEstimatorInitFailed;
+ }
+
+ std::string model_path = data.model_path;
+ size_t num_linked_sensors = common_instance_->num_linked_sensors;
+ bool use_prev_samples = data.use_prev_samples;
+ size_t prev_samples_order = data.prev_samples_order;
+ size_t num_hot_spots = data.num_hot_spots;
+ size_t output_label_count = data.output_label_count;
+
+ std::unique_lock<std::mutex> lock(tflite_instance_->tflite_methods.mutex);
+
+ if (model_path.empty()) {
LOG(ERROR) << "Invalid model_path:" << model_path;
return kVtEstimatorInvalidArgs;
}
- if (!data_->input_buffer || !data_->input_buffer_size) {
- LOG(ERROR) << "Invalid data_ members " << model_path
- << " input_buffer: " << data_->input_buffer
- << " input_buffer_size: " << data_->input_buffer_size;
+ if (num_linked_sensors == 0 || prev_samples_order < 1 ||
+ (!use_prev_samples && prev_samples_order > 1)) {
+ LOG(ERROR) << "Invalid tflite_instance_ config: "
+ << "number of linked sensor: " << num_linked_sensors
+ << " use previous: " << use_prev_samples
+ << " previous sample order: " << prev_samples_order;
+ return kVtEstimatorInitFailed;
+ }
+
+ common_instance_->use_prev_samples = data.use_prev_samples;
+ common_instance_->prev_samples_order = prev_samples_order;
+ tflite_instance_->input_buffer_size = num_linked_sensors * prev_samples_order;
+ tflite_instance_->input_buffer = new float[tflite_instance_->input_buffer_size];
+ if (common_instance_->use_prev_samples) {
+ tflite_instance_->scratch_buffer = new float[tflite_instance_->input_buffer_size];
+ }
+
+ if (output_label_count < 1 || num_hot_spots < 1) {
+ LOG(ERROR) << "Invalid tflite_instance_ config:"
+ << "number of hot spots: " << num_hot_spots
+ << " predicted sample order: " << output_label_count;
return kVtEstimatorInitFailed;
}
- if (!data_->tflite_methods.create || !data_->tflite_methods.init ||
- !data_->tflite_methods.invoke || !data_->tflite_methods.destroy) {
+ tflite_instance_->output_label_count = output_label_count;
+ tflite_instance_->num_hot_spots = num_hot_spots;
+ tflite_instance_->output_buffer_size = output_label_count * num_hot_spots;
+ tflite_instance_->output_buffer = new float[tflite_instance_->output_buffer_size];
+
+ if (!tflite_instance_->tflite_methods.create || !tflite_instance_->tflite_methods.init ||
+ !tflite_instance_->tflite_methods.invoke || !tflite_instance_->tflite_methods.destroy) {
LOG(ERROR) << "Invalid tflite methods";
return kVtEstimatorInitFailed;
}
- data_->tflite_wrapper = data_->tflite_methods.create(kNumInputTensors, kNumOutputTensors);
- if (!data_->tflite_wrapper) {
+ tflite_instance_->tflite_wrapper =
+ tflite_instance_->tflite_methods.create(kNumInputTensors, kNumOutputTensors);
+ if (!tflite_instance_->tflite_wrapper) {
LOG(ERROR) << "Failed to create tflite wrapper";
return kVtEstimatorInitFailed;
}
- int ret = data_->tflite_methods.init(data_->tflite_wrapper, model_path);
+ int ret = tflite_instance_->tflite_methods.init(tflite_instance_->tflite_wrapper,
+ model_path.c_str());
if (ret) {
LOG(ERROR) << "Failed to Init tflite_wrapper for " << model_path << " (ret: )" << ret
<< ")";
return kVtEstimatorInitFailed;
}
- data_->is_initialized = true;
- data_->model_path = model_path;
+ common_instance_->cur_sample_index = 0;
+ common_instance_->offset = data.offset;
+ common_instance_->is_initialized = true;
+ tflite_instance_->model_path = model_path;
LOG(INFO) << "Successfully initialized VirtualTempEstimator for " << model_path;
return kVtEstimatorOk;
}
-VtEstimatorStatus VirtualTempEstimator::Estimate(const std::vector<float> &thermistors,
- float *output) {
- if (!data_) {
- LOG(ERROR) << "data_ is nullptr during Estimate\n";
+VtEstimatorStatus VirtualTempEstimator::LinearModelEstimate(const std::vector<float> &thermistors,
+ float *output) {
+ if (linear_model_instance_ == nullptr || common_instance_ == nullptr) {
+ LOG(ERROR) << "linear_model_instance_ or common_instance_ is nullptr during Initialize";
return kVtEstimatorInitFailed;
}
- std::unique_lock<std::mutex> lock(data_->tflite_methods.mutex_);
+ size_t prev_samples_order = common_instance_->prev_samples_order;
+ size_t num_linked_sensors = common_instance_->num_linked_sensors;
+
+ std::unique_lock<std::mutex> lock(linear_model_instance_->mutex);
- if (!data_->is_initialized) {
- LOG(ERROR) << "data_ not initialized for " << data_->model_path;
+ if ((thermistors.size() != num_linked_sensors) || (output == nullptr)) {
+ LOG(ERROR) << "Invalid args Thermistors size[" << thermistors.size()
+ << "] num_linked_sensors[" << num_linked_sensors << "] output[" << output << "]";
+ return kVtEstimatorInvalidArgs;
+ }
+
+ if (common_instance_->is_initialized == false) {
+ LOG(ERROR) << "VirtualTempEstimator not initialized to estimate";
return kVtEstimatorInitFailed;
}
- if ((thermistors.size() != data_->input_buffer_size) || (!output)) {
- LOG(ERROR) << "Invalid args for " << data_->model_path
+ // For the first iteration copy current inputs to all previous inputs
+ // This would allow the estimator to have previous samples from the first iteration itself
+ // and provide a valid predicted value
+ if (common_instance_->first_iteration) {
+ for (size_t i = 0; i < prev_samples_order; ++i) {
+ linear_model_instance_->input_samples[i] = thermistors;
+ }
+ common_instance_->first_iteration = false;
+ }
+
+ size_t cur_sample_index = common_instance_->cur_sample_index;
+ linear_model_instance_->input_samples[cur_sample_index] = thermistors;
+
+ // Calculate Weighted Average Value
+ int input_level = cur_sample_index;
+ float estimated_value = 0;
+ for (size_t i = 0; i < prev_samples_order; ++i) {
+ for (size_t j = 0; j < num_linked_sensors; ++j) {
+ estimated_value += linear_model_instance_->coefficients[i][j] *
+ linear_model_instance_->input_samples[input_level][j];
+ }
+ input_level--; // go to previous samples
+ input_level = (input_level >= 0) ? input_level : (prev_samples_order - 1);
+ }
+
+ estimated_value += common_instance_->offset;
+
+ // Update sample index
+ cur_sample_index++;
+ cur_sample_index = (cur_sample_index % prev_samples_order);
+ common_instance_->cur_sample_index = cur_sample_index;
+
+ *output = estimated_value;
+ return kVtEstimatorOk;
+}
+
+VtEstimatorStatus VirtualTempEstimator::TFliteEstimate(const std::vector<float> &thermistors,
+ float *output) {
+ if (tflite_instance_ == nullptr || common_instance_ == nullptr) {
+ LOG(ERROR) << "tflite_instance_ or common_instance_ is nullptr during Estimate\n";
+ return kVtEstimatorInitFailed;
+ }
+
+ std::unique_lock<std::mutex> lock(tflite_instance_->tflite_methods.mutex);
+
+ if (!common_instance_->is_initialized) {
+ LOG(ERROR) << "tflite_instance_ not initialized for " << tflite_instance_->model_path;
+ return kVtEstimatorInitFailed;
+ }
+
+ size_t num_linked_sensors = common_instance_->num_linked_sensors;
+ if ((thermistors.size() != num_linked_sensors) || (!output)) {
+ LOG(ERROR) << "Invalid args for " << tflite_instance_->model_path
<< " thermistors.size(): " << thermistors.size()
- << " input_buffer_size: " << data_->input_buffer_size << " output: " << output;
+ << " num_linked_sensors: " << num_linked_sensors << " output: " << output;
return kVtEstimatorInvalidArgs;
}
// copy input data into input tensors
- for (size_t i = 0; i < data_->input_buffer_size; ++i) {
- data_->input_buffer[i] = thermistors[i];
+ size_t cur_sample_index = common_instance_->cur_sample_index;
+ size_t prev_samples_order = common_instance_->prev_samples_order;
+ size_t sample_start_index;
+ if (common_instance_->first_iteration) {
+ // For the first iteration copy current inputs to all previous inputs
+ // This would allow the estimator to have previous samples from the first iteration itself
+ // and provide a valid predicted value
+ for (size_t i = 0; i < prev_samples_order; ++i) {
+ sample_start_index = num_linked_sensors * i;
+ for (size_t j = 0; j < num_linked_sensors; ++j) {
+ tflite_instance_->input_buffer[sample_start_index + j] = thermistors[j];
+ }
+ }
+ common_instance_->first_iteration = false;
+ } else {
+ sample_start_index = cur_sample_index * num_linked_sensors;
+ for (size_t i = 0; i < num_linked_sensors; ++i) {
+ tflite_instance_->input_buffer[sample_start_index + i] = thermistors[i];
+ }
}
- int ret = data_->tflite_methods.invoke(data_->tflite_wrapper, data_->input_buffer,
- data_->input_buffer_size, output, 1);
+ // prepare model input
+ float *model_input;
+ size_t input_buffer_size = tflite_instance_->input_buffer_size;
+ size_t output_buffer_size = tflite_instance_->output_buffer_size;
+ if (!common_instance_->use_prev_samples) {
+ model_input = tflite_instance_->input_buffer;
+ } else {
+ sample_start_index = ((cur_sample_index + 1) * num_linked_sensors) % input_buffer_size;
+ for (size_t i = 0; i < input_buffer_size; ++i) {
+ size_t input_index = (sample_start_index + i) % input_buffer_size;
+ tflite_instance_->scratch_buffer[i] = tflite_instance_->input_buffer[input_index];
+ }
+ model_input = tflite_instance_->scratch_buffer;
+ }
+
+ int ret = tflite_instance_->tflite_methods.invoke(
+ tflite_instance_->tflite_wrapper, model_input, input_buffer_size,
+ tflite_instance_->output_buffer, output_buffer_size);
if (ret) {
- LOG(ERROR) << "Failed to Invoke for " << data_->model_path << " (ret: " << ret << ")";
+ LOG(ERROR) << "Failed to Invoke for " << tflite_instance_->model_path << " (ret: " << ret
+ << ")";
return kVtEstimatorInvokeFailed;
}
+ // Update sample index
+ common_instance_->cur_sample_index = (cur_sample_index + 1) % prev_samples_order;
+
+ // virtual sensor currently only support scalar output
+ *output = tflite_instance_->output_buffer[0] + common_instance_->offset;
+
return kVtEstimatorOk;
}
+VtEstimatorStatus VirtualTempEstimator::Estimate(const std::vector<float> &thermistors,
+ float *output) {
+ if (type == kUseMLModel) {
+ return TFliteEstimate(thermistors, output);
+ } else if (type == kUseLinearModel) {
+ return LinearModelEstimate(thermistors, output);
+ }
+
+ LOG(ERROR) << "Unsupported estimationType [" << type << "]";
+ return kVtEstimatorUnSupported;
+}
+
+VtEstimatorStatus VirtualTempEstimator::Initialize(const VtEstimationInitData &data) {
+ LOG(INFO) << "Initialize VirtualTempEstimator for " << type;
+
+ if (type == kUseMLModel) {
+ return TFliteInitialize(data.ml_model_init_data);
+ } else if (type == kUseLinearModel) {
+ return LinearModelInitialize(data.linear_model_init_data);
+ }
+
+ LOG(ERROR) << "Unsupported estimationType [" << type << "]";
+ return kVtEstimatorUnSupported;
+}
+
} // namespace vtestimator
} // namespace thermal