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.
 
 
 
 
 
 

199 lines
6.3 KiB

#include "commonmodel.h"
#include <czmq.h>
#include "cereal/gen/c/log.capnp.h"
#include "common/mat.h"
#include "common/timing.h"
void model_input_init(ModelInput* s, int width, int height,
cl_device_id device_id, cl_context context) {
int err;
s->device_id = device_id;
s->context = context;
transform_init(&s->transform, context, device_id);
s->transformed_width = width;
s->transformed_height = height;
s->transformed_y_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
s->transformed_width*s->transformed_height, NULL, &err);
assert(err == 0);
s->transformed_u_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
(s->transformed_width/2)*(s->transformed_height/2), NULL, &err);
assert(err == 0);
s->transformed_v_cl = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
(s->transformed_width/2)*(s->transformed_height/2), NULL, &err);
assert(err == 0);
s->net_input_size = ((width*height*3)/2)*sizeof(float);
s->net_input = clCreateBuffer(s->context, CL_MEM_READ_WRITE,
s->net_input_size, (void*)NULL, &err);
assert(err == 0);
loadyuv_init(&s->loadyuv, context, device_id, s->transformed_width, s->transformed_height);
}
float *model_input_prepare(ModelInput* s, cl_command_queue q,
cl_mem yuv_cl, int width, int height,
mat3 transform) {
int err;
int i = 0;
transform_queue(&s->transform, q,
yuv_cl, width, height,
s->transformed_y_cl, s->transformed_u_cl, s->transformed_v_cl,
s->transformed_width, s->transformed_height,
transform);
loadyuv_queue(&s->loadyuv, q,
s->transformed_y_cl, s->transformed_u_cl, s->transformed_v_cl,
s->net_input);
float *net_input_buf = (float *)clEnqueueMapBuffer(q, s->net_input, CL_TRUE,
CL_MAP_READ, 0, s->net_input_size,
0, NULL, NULL, &err);
clFinish(q);
return net_input_buf;
}
void model_input_free(ModelInput* s) {
transform_destroy(&s->transform);
loadyuv_destroy(&s->loadyuv);
}
float sigmoid(float input) {
return 1 / (1 + expf(-input));
}
float softplus(float input) {
return log1p(expf(input));
}
void softmax(const float* input, float* output, size_t len) {
float max_val = -FLT_MAX;
for(int i = 0; i < len; i++) {
const float v = input[i];
if( v > max_val ) {
max_val = v;
}
}
float denominator = 0;
for(int i = 0; i < len; i++) {
float const v = input[i];
float const v_exp = expf(v - max_val);
denominator += v_exp;
output[i] = v_exp;
}
const float inv_denominator = 1. / denominator;
for(int i = 0; i < len; i++) {
output[i] *= inv_denominator;
}
}
static cereal_ModelData_PathData_ptr path_to_cereal(struct capn_segment *cs, const PathData data) {
capn_list32 poly_ptr = capn_new_list32(cs, POLYFIT_DEGREE);
for (int i=0; i<POLYFIT_DEGREE; i++) {
capn_set32(poly_ptr, i, capn_from_f32(data.poly[i]));
}
if (getenv("DEBUG_MODEL")){
capn_list32 points_ptr = capn_new_list32(cs, MODEL_PATH_DISTANCE);
capn_list32 stds_ptr = capn_new_list32(cs, MODEL_PATH_DISTANCE);
for (int i=0; i<MODEL_PATH_DISTANCE; i++) {
capn_set32(points_ptr, i, capn_from_f32(data.points[i]));
capn_set32(stds_ptr, i, capn_from_f32(data.stds[i]));
}
struct cereal_ModelData_PathData d = {
.points = points_ptr,
.stds = stds_ptr,
.prob = data.prob,
.std = data.std,
.poly = poly_ptr,
};
cereal_ModelData_PathData_ptr ret = cereal_new_ModelData_PathData(cs);
cereal_write_ModelData_PathData(&d, ret);
return ret;
} else {
struct cereal_ModelData_PathData d = {
.prob = data.prob,
.std = data.std,
.poly = poly_ptr,
};
cereal_ModelData_PathData_ptr ret = cereal_new_ModelData_PathData(cs);
cereal_write_ModelData_PathData(&d, ret);
return ret;
}
}
static cereal_ModelData_LeadData_ptr lead_to_cereal(struct capn_segment *cs, const LeadData data) {
cereal_ModelData_LeadData_ptr leadp = cereal_new_ModelData_LeadData(cs);
struct cereal_ModelData_LeadData leadd = (struct cereal_ModelData_LeadData){
.dist = data.dist,
.prob = data.prob,
.std = data.std,
.relY = data.rel_y,
.relYStd = data.rel_y_std,
.relVel = data.rel_v,
.relVelStd = data.rel_v_std,
.relA = data.rel_a,
.relAStd = data.rel_a_std,
};
cereal_write_ModelData_LeadData(&leadd, leadp);
return leadp;
}
void model_publish(void* sock, uint32_t frame_id,
const mat3 transform, const ModelData data) {
struct capn rc;
capn_init_malloc(&rc);
struct capn_segment *cs = capn_root(&rc).seg;
capn_list32 input_transform_ptr = capn_new_list32(cs, 3*3);
for (int i = 0; i < 3 * 3; i++) {
capn_set32(input_transform_ptr, i, capn_from_f32(transform.v[i]));
}
capn_list32 speed_perc_ptr = capn_new_list32(cs, SPEED_PERCENTILES);
for (int i=0; i<SPEED_PERCENTILES; i++) {
capn_set32(speed_perc_ptr, i, capn_from_f32(data.speed[i]));
}
cereal_ModelData_ModelSettings_ptr settingsp = cereal_new_ModelData_ModelSettings(cs);
struct cereal_ModelData_ModelSettings settingsd = {
.inputTransform = input_transform_ptr,
};
cereal_write_ModelData_ModelSettings(&settingsd, settingsp);
cereal_ModelData_ptr modelp = cereal_new_ModelData(cs);
struct cereal_ModelData modeld = (struct cereal_ModelData){
.frameId = frame_id,
.path = path_to_cereal(cs, data.path),
.leftLane = path_to_cereal(cs, data.left_lane),
.rightLane = path_to_cereal(cs, data.right_lane),
.lead = lead_to_cereal(cs, data.lead),
.leadFuture = lead_to_cereal(cs, data.lead_future),
.settings = settingsp,
.speed = speed_perc_ptr,
};
cereal_write_ModelData(&modeld, modelp);
cereal_Event_ptr eventp = cereal_new_Event(cs);
struct cereal_Event event = {
.logMonoTime = nanos_since_boot(),
.valid = true,
.which = cereal_Event_model,
.model = modelp,
};
cereal_write_Event(&event, eventp);
capn_setp(capn_root(&rc), 0, eventp.p);
uint8_t buf[4096];
ssize_t rs = capn_write_mem(&rc, buf, sizeof(buf), 0);
zmq_send(sock, buf, rs, ZMQ_DONTWAIT);
capn_free(&rc);
}