openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.0 KiB

#include "tfmodel.h"
#include <string>
#include <string.h>
#include <stdlib.h>
#include <stdexcept>
#include "common/util.h"
#include "common/swaglog.h"
#include <cassert>
void TFModel::status_check() const {
if (TF_GetCode(this->status) != TF_OK) {
throw std::runtime_error(TF_Message(status));
}
}
TF_Tensor *TFModel::allocate_tensor_for_output(TF_Output out, float *dat) {
int num_dims = TF_GraphGetTensorNumDims(graph, out, status);
status_check();
int64_t *dims = new int64_t[num_dims];
TF_GraphGetTensorShape(graph, out, dims, num_dims, status);
status_check();
dims[0] = 1;
int total = 1;
for (int i = 0; i < num_dims; i++) total *= dims[i];
//printf("dims %d total %d wdat %p\n", num_dims, total, dat);
// don't deallocate the buffers
auto d = [](void* ddata, size_t, void* arg) {};
TF_Tensor *ret = TF_NewTensor(TF_FLOAT, dims, num_dims, (void*)dat, sizeof(float)*total, d, NULL);
//TF_Tensor *ret = TF_AllocateTensor(TF_FLOAT, dims, num_dims, sizeof(float)*total);
//memcpy(TF_TensorData(ret), dat, sizeof(float)*total);
assert(ret);
delete[] dims;
return ret;
}
TFModel::TFModel(const char *path, float *_output, size_t _output_size, int runtime) {
// load model
{
TF_Buffer* buf;
size_t model_size;
char tmp[1024];
snprintf(tmp, sizeof(tmp), "%s.pb", path);
LOGD("loading model %s", tmp);
uint8_t *model_data = (uint8_t *)read_file(tmp, &model_size);
assert(model_data);
buf = TF_NewBuffer();
buf->data = model_data;
buf->length = model_size;
buf->data_deallocator = [](void *data, size_t) { free(data); };
LOGD("loaded model of size %d", model_size);
// import graph
status = TF_NewStatus();
graph = TF_NewGraph();
TF_ImportGraphDefOptions *opts = TF_NewImportGraphDefOptions();
// TODO: fix the GPU, currently it hangs if you set this to /gpu:0
//TF_ImportGraphDefOptionsSetDefaultDevice(opts, "/cpu:0");
TF_GraphImportGraphDef(graph, buf, opts, status);
TF_DeleteImportGraphDefOptions(opts);
TF_DeleteBuffer(buf);
status_check();
LOGD("imported graph");
}
// set up session
TF_SessionOptions* sess_opts = TF_NewSessionOptions();
// don't use all GPU memory
/*uint8_t config[15] = {0x32, 0xb, 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x1, 0x38, 0x1};
double gpu_memory_fraction = 0.2;
auto bytes = reinterpret_cast<std::uint8_t*>(&gpu_memory_fraction);
for (std::size_t i = 0; i < sizeof(gpu_memory_fraction); ++i) {
config[i + 3] = bytes[i];
}
TF_SetConfig(sess_opts, config, sizeof(config), status);
status_check();*/
// make session
session = TF_NewSession(graph, sess_opts, status);
TF_DeleteSessionOptions(sess_opts);
status_check();
// find tensors
// TODO: make this generic
input_operation = {TF_GraphOperationByName(graph, "lambda/div"), 0};
if (input_operation.oper == NULL) {
input_operation = {TF_GraphOperationByName(graph, "vision_lambda/div"), 0};
}
assert(input_operation.oper != NULL);
output_operation = {TF_GraphOperationByName(graph, "outputs/outputs/Identity"), 0};
if (output_operation.oper == NULL) {
output_operation = {TF_GraphOperationByName(graph, "outputs/concat"), 0};
}
assert(output_operation.oper != NULL);
// output tensor is good to bind now
output = _output;
output_size = _output_size;
}
TFModel::~TFModel() {
TF_DeleteSession(session, status);
status_check();
TF_DeleteGraph(graph);
TF_DeleteStatus(status);
}
void TFModel::addRecurrent(float *state, int state_size) {
rnn_operation.oper = TF_GraphOperationByName(graph, "rnn_state");
rnn_operation.index = 0;
assert(rnn_operation.oper != NULL);
rnn_input_buf = state;
}
void TFModel::addDesire(float *state, int state_size) {
desire_operation.oper = TF_GraphOperationByName(graph, "desire");
desire_operation.index = 0;
assert(desire_operation.oper != NULL);
desire_input_buf = state;
}
void TFModel::execute(float *net_input_buf) {
TF_Tensor *input_tensor = allocate_tensor_for_output(input_operation, net_input_buf);
assert(input_tensor);
TF_Tensor *output_tensor = NULL;
if (rnn_input_buf == NULL) {
TF_SessionRun(session, NULL,
&input_operation, &input_tensor, 1,
&output_operation, &output_tensor, 1,
NULL, 0, NULL, status);
} else {
//printf("%f %f %f\n", net_input_buf[0], rnn_input_buf[0], desire_input_buf[0]);
TF_Tensor *rnn_tensor = allocate_tensor_for_output(rnn_operation, rnn_input_buf);
TF_Tensor *desire_tensor = allocate_tensor_for_output(desire_operation, desire_input_buf);
TF_Output io[] = {input_operation, rnn_operation, desire_operation};
TF_Tensor* id[] = {input_tensor, rnn_tensor, desire_tensor};
TF_SessionRun(session, NULL,
io, id, 3,
&output_operation, &output_tensor, 1,
NULL, 0, NULL, status);
TF_DeleteTensor(rnn_tensor);
TF_DeleteTensor(desire_tensor);
}
TF_DeleteTensor(input_tensor);
status_check();
assert(output_tensor);
memcpy((void*)output, TF_TensorData(output_tensor), output_size*sizeof(float));
TF_DeleteTensor(output_tensor);
}