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.
299 lines
11 KiB
299 lines
11 KiB
6 years ago
|
#include <string.h>
|
||
|
#include <assert.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#ifdef QCOM
|
||
6 years ago
|
#include <eigen3/Eigen/Dense>
|
||
6 years ago
|
#else
|
||
6 years ago
|
#include <Eigen/Dense>
|
||
6 years ago
|
#endif
|
||
|
|
||
|
#include "common/timing.h"
|
||
|
#include "driving.h"
|
||
|
|
||
6 years ago
|
#define MODEL_WIDTH 512
|
||
|
#define MODEL_HEIGHT 256
|
||
|
#define MODEL_NAME "driving_model_dlc"
|
||
6 years ago
|
|
||
6 years ago
|
#define LEAD_MDN_N 5 // probs for 5 groups
|
||
|
#define MDN_VALS 4 // output xyva for each lead group
|
||
|
#define SELECTION 3 //output 3 group (lead now, in 2s and 6s)
|
||
|
#define MDN_GROUP_SIZE 11
|
||
|
#define SPEED_BUCKETS 100
|
||
5 years ago
|
#define OUTPUT_SIZE ((MODEL_PATH_DISTANCE*2) + (2*(MODEL_PATH_DISTANCE*2 + 1)) + MDN_GROUP_SIZE*LEAD_MDN_N + SELECTION + OTHER_META_SIZE + DESIRE_PRED_SIZE)
|
||
6 years ago
|
#ifdef TEMPORAL
|
||
|
#define TEMPORAL_SIZE 512
|
||
|
#else
|
||
|
#define TEMPORAL_SIZE 0
|
||
|
#endif
|
||
|
|
||
6 years ago
|
// #define DUMP_YUV
|
||
|
|
||
6 years ago
|
Eigen::Matrix<float, MODEL_PATH_DISTANCE, POLYFIT_DEGREE - 1> vander;
|
||
6 years ago
|
|
||
|
void model_init(ModelState* s, cl_device_id device_id, cl_context context, int temporal) {
|
||
|
model_input_init(&s->in, MODEL_WIDTH, MODEL_HEIGHT, device_id, context);
|
||
|
const int output_size = OUTPUT_SIZE + TEMPORAL_SIZE;
|
||
|
s->output = (float*)malloc(output_size * sizeof(float));
|
||
|
memset(s->output, 0, output_size * sizeof(float));
|
||
6 years ago
|
s->m = new DefaultRunModel("../../models/driving_model.dlc", s->output, output_size, USE_GPU_RUNTIME);
|
||
6 years ago
|
#ifdef TEMPORAL
|
||
|
assert(temporal);
|
||
|
s->m->addRecurrent(&s->output[OUTPUT_SIZE], TEMPORAL_SIZE);
|
||
|
#endif
|
||
6 years ago
|
#ifdef DESIRE
|
||
|
s->desire = (float*)malloc(DESIRE_SIZE * sizeof(float));
|
||
|
for (int i = 0; i < DESIRE_SIZE; i++) s->desire[i] = 0.0;
|
||
|
s->m->addDesire(s->desire, DESIRE_SIZE);
|
||
|
#endif
|
||
6 years ago
|
|
||
|
// Build Vandermonde matrix
|
||
|
for(int i = 0; i < MODEL_PATH_DISTANCE; i++) {
|
||
6 years ago
|
for(int j = 0; j < POLYFIT_DEGREE - 1; j++) {
|
||
6 years ago
|
vander(i, j) = pow(i, POLYFIT_DEGREE-j-1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ModelData model_eval_frame(ModelState* s, cl_command_queue q,
|
||
|
cl_mem yuv_cl, int width, int height,
|
||
6 years ago
|
mat3 transform, void* sock, float *desire_in) {
|
||
6 years ago
|
struct {
|
||
|
float *path;
|
||
|
float *left_lane;
|
||
|
float *right_lane;
|
||
|
float *lead;
|
||
6 years ago
|
float *speed;
|
||
5 years ago
|
float *meta;
|
||
6 years ago
|
} net_outputs = {NULL};
|
||
|
|
||
6 years ago
|
#ifdef DESIRE
|
||
|
if (desire_in != NULL) {
|
||
|
for (int i = 0; i < DESIRE_SIZE; i++) s->desire[i] = desire_in[i];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
6 years ago
|
//for (int i = 0; i < OUTPUT_SIZE + TEMPORAL_SIZE; i++) { printf("%f ", s->output[i]); } printf("\n");
|
||
|
|
||
|
float *net_input_buf = model_input_prepare(&s->in, q, yuv_cl, width, height, transform);
|
||
|
|
||
6 years ago
|
#ifdef DUMP_YUV
|
||
|
FILE *dump_yuv_file = fopen("/sdcard/dump.yuv", "wb");
|
||
|
fwrite(net_input_buf, MODEL_HEIGHT*MODEL_WIDTH*3/2, sizeof(float), dump_yuv_file);
|
||
|
fclose(dump_yuv_file);
|
||
|
assert(1==2);
|
||
|
#endif
|
||
|
|
||
6 years ago
|
//printf("readinggggg \n");
|
||
|
//FILE *f = fopen("goof_frame", "r");
|
||
|
//fread(net_input_buf, sizeof(float), MODEL_HEIGHT*MODEL_WIDTH*3/2, f);
|
||
|
//fclose(f);
|
||
|
//sleep(1);
|
||
6 years ago
|
//printf("%i \n",OUTPUT_SIZE);
|
||
|
//printf("%i \n",MDN_GROUP_SIZE);
|
||
6 years ago
|
s->m->execute(net_input_buf);
|
||
|
|
||
|
// net outputs
|
||
|
net_outputs.path = &s->output[0];
|
||
|
net_outputs.left_lane = &s->output[MODEL_PATH_DISTANCE*2];
|
||
|
net_outputs.right_lane = &s->output[MODEL_PATH_DISTANCE*2 + MODEL_PATH_DISTANCE*2 + 1];
|
||
|
net_outputs.lead = &s->output[MODEL_PATH_DISTANCE*2 + (MODEL_PATH_DISTANCE*2 + 1)*2];
|
||
6 years ago
|
//net_outputs.speed = &s->output[OUTPUT_SIZE - SPEED_BUCKETS];
|
||
5 years ago
|
net_outputs.meta = &s->output[OUTPUT_SIZE - OTHER_META_SIZE - DESIRE_PRED_SIZE];
|
||
6 years ago
|
|
||
|
ModelData model = {0};
|
||
|
|
||
|
for (int i=0; i<MODEL_PATH_DISTANCE; i++) {
|
||
|
model.path.points[i] = net_outputs.path[i];
|
||
|
model.left_lane.points[i] = net_outputs.left_lane[i] + 1.8;
|
||
|
model.right_lane.points[i] = net_outputs.right_lane[i] - 1.8;
|
||
|
model.path.stds[i] = softplus(net_outputs.path[MODEL_PATH_DISTANCE + i]);
|
||
|
model.left_lane.stds[i] = softplus(net_outputs.left_lane[MODEL_PATH_DISTANCE + i]);
|
||
|
model.right_lane.stds[i] = softplus(net_outputs.right_lane[MODEL_PATH_DISTANCE + i]);
|
||
|
}
|
||
|
|
||
5 years ago
|
model.path.std = softplus(net_outputs.path[MODEL_PATH_DISTANCE]);
|
||
|
model.left_lane.std = softplus(net_outputs.left_lane[MODEL_PATH_DISTANCE]);
|
||
|
model.right_lane.std = softplus(net_outputs.right_lane[MODEL_PATH_DISTANCE]);
|
||
6 years ago
|
|
||
|
model.path.prob = 1.;
|
||
|
model.left_lane.prob = sigmoid(net_outputs.left_lane[MODEL_PATH_DISTANCE*2]);
|
||
|
model.right_lane.prob = sigmoid(net_outputs.right_lane[MODEL_PATH_DISTANCE*2]);
|
||
|
|
||
|
poly_fit(model.path.points, model.path.stds, model.path.poly);
|
||
|
poly_fit(model.left_lane.points, model.left_lane.stds, model.left_lane.poly);
|
||
|
poly_fit(model.right_lane.points, model.right_lane.stds, model.right_lane.poly);
|
||
|
|
||
|
const double max_dist = 140.0;
|
||
|
const double max_rel_vel = 10.0;
|
||
6 years ago
|
// Every output distribution from the MDN includes the probabilties
|
||
|
// of it representing a current lead car, a lead car in 2s
|
||
|
// or a lead car in 4s
|
||
|
|
||
|
// Find the distribution that corresponds to the current lead
|
||
6 years ago
|
int mdn_max_idx = 0;
|
||
|
for (int i=1; i<LEAD_MDN_N; i++) {
|
||
6 years ago
|
if (net_outputs.lead[i*MDN_GROUP_SIZE + 8] > net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 8]) {
|
||
|
mdn_max_idx = i;
|
||
|
}
|
||
|
}
|
||
|
model.lead.prob = sigmoid(net_outputs.lead[LEAD_MDN_N*MDN_GROUP_SIZE]);
|
||
|
model.lead.dist = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE] * max_dist;
|
||
|
model.lead.std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS]) * max_dist;
|
||
|
model.lead.rel_y = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 1];
|
||
|
model.lead.rel_y_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 1]);
|
||
|
model.lead.rel_v = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 2] * max_rel_vel;
|
||
|
model.lead.rel_v_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 2]) * max_rel_vel;
|
||
|
model.lead.rel_a = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 3];
|
||
|
model.lead.rel_a_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 3]);
|
||
6 years ago
|
|
||
|
// Find the distribution that corresponds to the lead in 2s
|
||
6 years ago
|
mdn_max_idx = 0;
|
||
|
for (int i=1; i<LEAD_MDN_N; i++) {
|
||
|
if (net_outputs.lead[i*MDN_GROUP_SIZE + 9] > net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 9]) {
|
||
6 years ago
|
mdn_max_idx = i;
|
||
|
}
|
||
|
}
|
||
6 years ago
|
model.lead_future.prob = sigmoid(net_outputs.lead[LEAD_MDN_N*MDN_GROUP_SIZE + 1]);
|
||
|
model.lead_future.dist = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE] * max_dist;
|
||
|
model.lead_future.std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS]) * max_dist;
|
||
|
model.lead_future.rel_y = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 1];
|
||
|
model.lead_future.rel_y_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 1]);
|
||
|
model.lead_future.rel_v = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 2] * max_rel_vel;
|
||
|
model.lead_future.rel_v_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 2]) * max_rel_vel;
|
||
|
model.lead_future.rel_a = net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + 3];
|
||
|
model.lead_future.rel_a_std = softplus(net_outputs.lead[mdn_max_idx*MDN_GROUP_SIZE + MDN_VALS + 3]);
|
||
|
|
||
|
|
||
|
// get speed percentiles numbers represent 5th, 15th, ... 95th percentile
|
||
|
for (int i=0; i < SPEED_PERCENTILES; i++) {
|
||
|
model.speed[i] = ((float) SPEED_BUCKETS)/2.0;
|
||
|
}
|
||
6 years ago
|
//float sum = 0;
|
||
|
//for (int idx = 0; idx < SPEED_BUCKETS; idx++) {
|
||
|
// sum += net_outputs.speed[idx];
|
||
|
// int idx_percentile = (sum + .05) * SPEED_PERCENTILES;
|
||
|
// if (idx_percentile < SPEED_PERCENTILES ){
|
||
|
// model.speed[idx_percentile] = ((float)idx)/2.0;
|
||
|
// }
|
||
|
//}
|
||
6 years ago
|
// make sure no percentiles are skipped
|
||
6 years ago
|
//for (int i=SPEED_PERCENTILES-1; i > 0; i--){
|
||
|
// if (model.speed[i-1] > model.speed[i]){
|
||
|
// model.speed[i-1] = model.speed[i];
|
||
|
// }
|
||
|
//}
|
||
5 years ago
|
for (int i=0; i<OTHER_META_SIZE + DESIRE_PRED_SIZE; i++) {
|
||
|
model.meta[i] = net_outputs.meta[i];
|
||
|
}
|
||
|
|
||
6 years ago
|
return model;
|
||
|
}
|
||
|
|
||
|
void model_free(ModelState* s) {
|
||
|
free(s->output);
|
||
|
model_input_free(&s->in);
|
||
|
delete s->m;
|
||
|
}
|
||
|
|
||
|
void poly_fit(float *in_pts, float *in_stds, float *out) {
|
||
|
// References to inputs
|
||
|
Eigen::Map<Eigen::Matrix<float, MODEL_PATH_DISTANCE, 1> > pts(in_pts, MODEL_PATH_DISTANCE);
|
||
|
Eigen::Map<Eigen::Matrix<float, MODEL_PATH_DISTANCE, 1> > std(in_stds, MODEL_PATH_DISTANCE);
|
||
6 years ago
|
Eigen::Map<Eigen::Matrix<float, POLYFIT_DEGREE - 1, 1> > p(out, POLYFIT_DEGREE - 1);
|
||
|
|
||
|
float y0 = pts[0];
|
||
|
pts = pts.array() - y0;
|
||
6 years ago
|
|
||
|
// Build Least Squares equations
|
||
6 years ago
|
Eigen::Matrix<float, MODEL_PATH_DISTANCE, POLYFIT_DEGREE - 1> lhs = vander.array().colwise() / std.array();
|
||
6 years ago
|
Eigen::Matrix<float, MODEL_PATH_DISTANCE, 1> rhs = pts.array() / std.array();
|
||
|
|
||
6 years ago
|
// Improve numerical stability
|
||
6 years ago
|
Eigen::Matrix<float, POLYFIT_DEGREE - 1, 1> scale = 1. / (lhs.array()*lhs.array()).sqrt().colwise().sum();
|
||
6 years ago
|
lhs = lhs * scale.asDiagonal();
|
||
|
|
||
6 years ago
|
// Solve inplace
|
||
|
Eigen::ColPivHouseholderQR<Eigen::Ref<Eigen::MatrixXf> > qr(lhs);
|
||
|
p = qr.solve(rhs);
|
||
6 years ago
|
|
||
|
// Apply scale to output
|
||
|
p = p.transpose() * scale.asDiagonal();
|
||
6 years ago
|
out[3] = y0;
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
|
||
|
void fill_path(cereal::ModelData::PathData::Builder path, const PathData path_data) {
|
||
6 years ago
|
if (std::getenv("DEBUG")){
|
||
|
kj::ArrayPtr<const float> stds(&path_data.stds[0], ARRAYSIZE(path_data.stds));
|
||
|
path.setStds(stds);
|
||
|
|
||
|
kj::ArrayPtr<const float> points(&path_data.points[0], ARRAYSIZE(path_data.points));
|
||
|
path.setPoints(points);
|
||
|
}
|
||
|
|
||
6 years ago
|
kj::ArrayPtr<const float> poly(&path_data.poly[0], ARRAYSIZE(path_data.poly));
|
||
|
path.setPoly(poly);
|
||
|
path.setProb(path_data.prob);
|
||
|
path.setStd(path_data.std);
|
||
|
}
|
||
|
|
||
|
void fill_lead(cereal::ModelData::LeadData::Builder lead, const LeadData lead_data) {
|
||
|
lead.setDist(lead_data.dist);
|
||
|
lead.setProb(lead_data.prob);
|
||
|
lead.setStd(lead_data.std);
|
||
|
lead.setRelY(lead_data.rel_y);
|
||
|
lead.setRelYStd(lead_data.rel_y_std);
|
||
|
lead.setRelVel(lead_data.rel_v);
|
||
|
lead.setRelVelStd(lead_data.rel_v_std);
|
||
|
lead.setRelA(lead_data.rel_a);
|
||
|
lead.setRelAStd(lead_data.rel_a_std);
|
||
|
}
|
||
|
|
||
5 years ago
|
void fill_meta(cereal::ModelData::MetaData::Builder meta, const float * meta_data) {
|
||
|
meta.setEngagedProb(meta_data[0]);
|
||
|
meta.setGasDisengageProb(meta_data[1]);
|
||
|
meta.setBrakeDisengageProb(meta_data[2]);
|
||
|
meta.setSteerOverrideProb(meta_data[3]);
|
||
|
kj::ArrayPtr<const float> desire_pred(&meta_data[OTHER_META_SIZE], DESIRE_PRED_SIZE);
|
||
|
meta.setDesirePrediction(desire_pred);
|
||
|
}
|
||
|
|
||
6 years ago
|
void model_publish(PubSocket *sock, uint32_t frame_id,
|
||
6 years ago
|
const ModelData data, uint64_t timestamp_eof) {
|
||
|
// make msg
|
||
|
capnp::MallocMessageBuilder msg;
|
||
|
cereal::Event::Builder event = msg.initRoot<cereal::Event>();
|
||
|
event.setLogMonoTime(nanos_since_boot());
|
||
|
|
||
|
auto framed = event.initModel();
|
||
|
framed.setFrameId(frame_id);
|
||
|
framed.setTimestampEof(timestamp_eof);
|
||
|
|
||
|
kj::ArrayPtr<const float> speed(&data.speed[0], ARRAYSIZE(data.speed));
|
||
|
framed.setSpeed(speed);
|
||
6 years ago
|
|
||
|
|
||
6 years ago
|
auto lpath = framed.initPath();
|
||
|
fill_path(lpath, data.path);
|
||
|
auto left_lane = framed.initLeftLane();
|
||
|
fill_path(left_lane, data.left_lane);
|
||
|
auto right_lane = framed.initRightLane();
|
||
|
fill_path(right_lane, data.right_lane);
|
||
|
|
||
|
auto lead = framed.initLead();
|
||
|
fill_lead(lead, data.lead);
|
||
|
auto lead_future = framed.initLeadFuture();
|
||
|
fill_lead(lead_future, data.lead_future);
|
||
|
|
||
5 years ago
|
auto meta = framed.initMeta();
|
||
|
fill_meta(meta, data.meta);
|
||
|
|
||
6 years ago
|
|
||
|
// send message
|
||
|
auto words = capnp::messageToFlatArray(msg);
|
||
|
auto bytes = words.asBytes();
|
||
6 years ago
|
sock->send((char*)bytes.begin(), bytes.size());
|
||
6 years ago
|
}
|