From ce3bf983ac16a16859dc8074fc4d22aca692d072 Mon Sep 17 00:00:00 2001 From: theantihero Date: Sun, 3 Mar 2019 02:37:56 -0500 Subject: [PATCH] Revert "Visiond pc ver" --- phonelibs/json11/json11.o | Bin 0 -> 142824 bytes selfdrive/visiond/build_from_src.mk | 38 +- selfdrive/visiond/camera_eon_stream.cc | 228 ----------- selfdrive/visiond/camera_eon_stream.h | 60 --- selfdrive/visiond/model.cc | 5 - selfdrive/visiond/monitoring.cc | 1 - selfdrive/visiond/snpemodel.cc | 11 +- selfdrive/visiond/visiond_pc.cc | 537 ------------------------- 8 files changed, 19 insertions(+), 861 deletions(-) create mode 100644 phonelibs/json11/json11.o delete mode 100644 selfdrive/visiond/camera_eon_stream.cc delete mode 100644 selfdrive/visiond/camera_eon_stream.h delete mode 100644 selfdrive/visiond/visiond_pc.cc diff --git a/phonelibs/json11/json11.o b/phonelibs/json11/json11.o new file mode 100644 index 0000000000000000000000000000000000000000..1e32cca71ffc3babc59454d354fe99c53400c23a GIT binary patch literal 142824 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

FM5!@~Rmn_`Q|FYn2 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 literal 0 HcmV?d00001 diff --git a/selfdrive/visiond/build_from_src.mk b/selfdrive/visiond/build_from_src.mk index 826ac7b43177cc..2d59d7fbacfa6e 100644 --- a/selfdrive/visiond/build_from_src.mk +++ b/selfdrive/visiond/build_from_src.mk @@ -38,35 +38,34 @@ ifeq ($(UNAME_S),Darwin) $(PHONELIBS)/zmq/mac/lib/libzmq.a OPENCL_LIBS = -framework OpenCL - - PLATFORM_OBJS = camera_fake.o \ - ../common/visionbuf_cl.o else - # assuem x86_64 linux + LIBYUV_FLAGS = -I$(PHONELIBS)/libyuv/x64/include + LIBYUV_LIBS = $(PHONELIBS)/libyuv/x64/lib/libyuv.a - ZMQ_FLAGS = -I$(PHONELIBS)/zmq/aarch64/include - ZMQ_LIBS = -l:libczmq.a -l:libzmq.a -luuid + ZMQ_FLAGS = -I$(EXTERNAL)/zmq/include + ZMQ_LIBS = -L$(EXTERNAL)/zmq/lib \ + -l:libczmq.a -l:libzmq.a OPENCL_LIBS = -lOpenCL - - SNPE_FLAGS = -I$(SNPE_ROOT)/include/zdl - SNPE_LIBS = -L$(SNPE_ROOT)/lib/x86_64-linux-clang/ \ - -lSNPE -lsymphony-cpu - - CXXFLAGS += -I../common - - PLATFORM_OBJS = camera_eon_stream.o endif + CURL_FLAGS = -I/usr/include/curl + CURL_LIBS = -lcurl -lz + SSL_FLAGS = -I/usr/include/openssl/ SSL_LIBS = -lssl -lcrypto - OTHER_LIBS = -lz -lm -lpthread -lavcodec -lavutil + OPENCV_FLAGS = + OPENCV_LIBS = -lopencv_video \ + -lopencv_imgproc \ + -lopencv_core + OTHER_LIBS = -lz -lm -lpthread + PLATFORM_OBJS = camera_fake.o \ + ../common/visionbuf_cl.o CFLAGS += -D_GNU_SOURCE \ -DCLU_NO_CACHE - OBJS = visiond_pc.o else # assume phone @@ -103,15 +102,13 @@ else OTHER_LIBS = -lz -lcutils -lm -llog -lui -ladreno_utils PLATFORM_OBJS = camera_qcom.o \ - ../common/visionbuf_ion.o \ - ../common/visionimg.o - + ../common/visionbuf_ion.o CFLAGS += -DQCOM CXXFLAGS += -DQCOM - OBJS = visiond.o endif +OBJS = visiond.o OUTPUT = visiond .PHONY: all @@ -123,6 +120,7 @@ OBJS += $(PLATFORM_OBJS) \ ../common/swaglog.o \ ../common/ipc.o \ ../common/visionipc.o \ + ../common/visionimg.o \ ../common/util.o \ ../common/params.o \ ../common/efd.o \ diff --git a/selfdrive/visiond/camera_eon_stream.cc b/selfdrive/visiond/camera_eon_stream.cc deleted file mode 100644 index 6df22b82c04bd7..00000000000000 --- a/selfdrive/visiond/camera_eon_stream.cc +++ /dev/null @@ -1,228 +0,0 @@ -#include "camera_eon_stream.h" - -#include -#include -#include -#include - -#include -#include -#include -#include "cereal/gen/cpp/log.capnp.h" - -#include "common/util.h" -#include "common/timing.h" -#include "common/swaglog.h" -#include "buffering.h" - -extern "C" { -#include -} - -extern volatile int do_exit; - -#define FRAME_WIDTH 1164 -#define FRAME_HEIGHT 874 - -namespace { -void camera_open(CameraState *s, cl_mem *yuv_cls, bool rear, cl_device_id device_id, cl_context context, cl_command_queue q) { - assert(yuv_cls); - s->yuv_cls = yuv_cls; - s->device_id = device_id; - s->context = context; - s->q = q; -} - -void camera_close(CameraState *s) { - tbuffer_stop(&s->camera_tb); -} - -void camera_release_buffer(void *cookie, int buf_idx) { - CameraState *s = static_cast(cookie); -} - -void camera_init(CameraState *s, int camera_id, unsigned int fps) { - assert(camera_id < ARRAYSIZE(cameras_supported)); - s->ci = cameras_supported[camera_id]; - assert(s->ci.frame_width != 0); - - s->frame_size = s->ci.frame_height * s->ci.frame_stride; - s->fps = fps; - - tbuffer_init2(&s->camera_tb, FRAME_BUF_COUNT, "frame", camera_release_buffer, - s); -} - -void run_eon_stream(DualCameraState *s) { - int err; - uint8_t stream_start[74] = -{0x00,0x00,0x00,0x01,0x40,0x01,0x0c,0x01,0xff,0xff,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5d,0xac,0x59,0x00,0x00,0x00,0x01,0x42,0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5d,0xa0,0x02,0x50,0x80,0x38,0x1c,0x5c,0x66,0x5a,0xee,0x4c,0x92,0xec,0x80,0x00,0x00,0x00,0x01,0x44,0x01,0xc0,0xf1,0x80,0x04,0x20}; - - avcodec_register_all(); - const AVCodec *codec = avcodec_find_decoder_by_name("hevc"); - if(!codec) { - LOG("hevc decoder not found\n"); - return; - } - AVCodecParserContext *parser = av_parser_init(codec->id); - if (!parser) { - LOG("parser not found\n"); - return; - } - AVCodecContext *dec_ctx = avcodec_alloc_context3(codec); - assert(dec_ctx); - err = avcodec_open2(dec_ctx, codec, NULL); - assert(err >= 0); - AVFrame *frame = av_frame_alloc(); - assert(frame); - - std::string zmq_uri(">tcp://"); - const char *eon_ip = getenv("EON_IP"); - if(eon_ip) - zmq_uri += eon_ip; - else - zmq_uri += "192.168.1.105"; - zmq_uri += ":9002"; - LOG("Connecting to Eon stream: %s", zmq_uri.c_str()); - zsock_t *frame_sock = zsock_new_sub(zmq_uri.c_str(), ""); - assert(frame_sock); - void *frame_sock_raw = zsock_resolve(frame_sock); - - CameraState *const rear_camera = &s->rear; - - auto *tb = &rear_camera->camera_tb; - AVPacket avpkt; - av_init_packet(&avpkt); - // send stream start bytes - avpkt.size = sizeof(stream_start); - avpkt.data = &stream_start[0]; - while (avpkt.size > 0) { - int got_frame = 0; - int len = avcodec_decode_video2(dec_ctx, frame, &got_frame, &avpkt); - if (len < 0) { - LOGD("Error while decoding frame\n"); - return; - } - avpkt.size -= len; - avpkt.data += len; - } - while (!do_exit) { - zmq_msg_t t_msg; - err = zmq_msg_init(&t_msg); - assert(err == 0); - - zmq_msg_t frame_msg; - err = zmq_msg_init(&frame_msg); - assert(err == 0); - - err = zmq_msg_recv(&t_msg, frame_sock_raw, 0); - if(err == -1) - break; - err = zmq_msg_recv(&frame_msg, frame_sock_raw, 0); - if(err == -1) - break; - - av_init_packet(&avpkt); - avpkt.size = zmq_msg_size(&frame_msg); - if (avpkt.size == 0) { - LOGD("Empty frame msg recved.\n"); - continue; - } - avpkt.data = (uint8_t *)zmq_msg_data(&frame_msg);; - while (avpkt.size > 0) { - int got_frame = 0; - int len = avcodec_decode_video2(dec_ctx, frame, &got_frame, &avpkt); - assert(len >= 0); - if (got_frame) { - assert(frame->width == FRAME_WIDTH); - assert(frame->height == FRAME_HEIGHT); - const int buf_idx = tbuffer_select(tb); - rear_camera->camera_bufs_metadata[buf_idx] = { - .frame_id = (uint32_t)dec_ctx->frame_number, - .timestamp_eof = nanos_since_boot(), - .frame_length = 0, - .integ_lines = 0, - .global_gain = 0, - }; - cl_mem yuv_cl = rear_camera->yuv_cls[buf_idx]; - cl_event map_event; - void *yuv_buf = (void *)clEnqueueMapBuffer(rear_camera->q, yuv_cl, CL_TRUE, - CL_MAP_WRITE, 0, frame->width * frame->height * 3 / 2, - 0, NULL, &map_event, &err); - assert(err == 0); - clWaitForEvents(1, &map_event); - clReleaseEvent(map_event); - uint8_t *write_ptr = (uint8_t *)yuv_buf; - for(int line_idx = 0; line_idx < frame->height; line_idx++) { - memcpy(write_ptr, frame->data[0] + line_idx * frame->linesize[0], frame->width); - write_ptr += frame->width; - } - for(int line_idx = 0; line_idx < frame->height / 2; line_idx++) { - memcpy(write_ptr, frame->data[1] + line_idx * frame->linesize[1], frame->width / 2); - write_ptr += frame->width / 2; - } - for(int line_idx = 0; line_idx < frame->height / 2;line_idx++) { - memcpy(write_ptr, frame->data[2] + line_idx * frame->linesize[2], frame->width / 2); - write_ptr += frame->width / 2; - } - clEnqueueUnmapMemObject(rear_camera->q, yuv_cl, yuv_buf, 0, NULL, &map_event); - clWaitForEvents(1, &map_event); - clReleaseEvent(map_event); - tbuffer_dispatch(tb, buf_idx); - - } - avpkt.size -= len; - avpkt.data += len; - } - err = zmq_msg_close(&frame_msg); - assert(err == 0); - err = zmq_msg_close(&t_msg); - assert(err == 0); - } - zsock_destroy(&frame_sock); - av_parser_close(parser); - avcodec_free_context(&dec_ctx); - av_frame_free(&frame); -} - -} // namespace - -CameraInfo cameras_supported[CAMERA_ID_MAX] = { - [CAMERA_ID_IMX298] = { - .frame_width = FRAME_WIDTH, - .frame_height = FRAME_HEIGHT, - .frame_stride = FRAME_WIDTH*3, - .bayer = false, - .bayer_flip = false, - }, -}; - -void cameras_init(DualCameraState *s) { - memset(s, 0, sizeof(*s)); - - camera_init(&s->rear, CAMERA_ID_IMX298, 20); - s->rear.transform = (mat3){{ - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - }}; -} - -void camera_autoexposure(CameraState *s, float grey_frac) {} - -void cameras_open(DualCameraState *s, cl_mem *yuv_cls_rear, cl_device_id device_id, cl_context context, cl_command_queue q) { - assert(yuv_cls_rear); - int err; - - camera_open(&s->rear, yuv_cls_rear, true, device_id, context, q); -} - -void cameras_close(DualCameraState *s) { - camera_close(&s->rear); -} - -void cameras_run(DualCameraState *s) { - set_thread_name("Eon streaming"); - run_eon_stream(s); - cameras_close(s); -} diff --git a/selfdrive/visiond/camera_eon_stream.h b/selfdrive/visiond/camera_eon_stream.h deleted file mode 100644 index 81f0195dd260eb..00000000000000 --- a/selfdrive/visiond/camera_eon_stream.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef FAKE_CAMERA_H -#define FAKE_CAMERA_H - -#include - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#include "common/mat.h" - -#include "buffering.h" -#include "common/visionbuf.h" -#include "camera_common.h" - -#define FRAME_BUF_COUNT 16 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct CameraState { - int camera_id; - CameraInfo ci; - int frame_size; - - cl_mem *yuv_cls; - cl_device_id device_id; - cl_context context; - cl_command_queue q; - - FrameMetadata camera_bufs_metadata[FRAME_BUF_COUNT]; - TBuffer camera_tb; - - int fps; - float digital_gain; - - mat3 transform; -} CameraState; - - -typedef struct DualCameraState { - int ispif_fd; - - CameraState rear; - CameraState front; -} DualCameraState; - -void cameras_init(DualCameraState *s); -void cameras_open(DualCameraState *s, cl_mem *yuv_cls_rear, cl_device_id device_id, cl_context context, cl_command_queue q); -void cameras_run(DualCameraState *s); -void cameras_close(DualCameraState *s); -void camera_autoexposure(CameraState *s, float grey_frac); -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/selfdrive/visiond/model.cc b/selfdrive/visiond/model.cc index 975ce7d6cfb351..ef1a7df9f07b90 100644 --- a/selfdrive/visiond/model.cc +++ b/selfdrive/visiond/model.cc @@ -1,7 +1,3 @@ -#include -#include -#include -#include #include "common/timing.h" #include "model.h" @@ -96,6 +92,5 @@ ModelData model_eval_frame(ModelState* s, cl_command_queue q, void model_free(ModelState* s) { model_input_free(&s->in); delete s->m; - free(s->output); } diff --git a/selfdrive/visiond/monitoring.cc b/selfdrive/visiond/monitoring.cc index 6e907253da83e2..84ed9e8c5bb27d 100644 --- a/selfdrive/visiond/monitoring.cc +++ b/selfdrive/visiond/monitoring.cc @@ -1,4 +1,3 @@ -#include #include "monitoring.h" #include "common/mat.h" diff --git a/selfdrive/visiond/snpemodel.cc b/selfdrive/visiond/snpemodel.cc index ee5e7b019e8cf5..ae7b7f10a1531e 100644 --- a/selfdrive/visiond/snpemodel.cc +++ b/selfdrive/visiond/snpemodel.cc @@ -1,4 +1,3 @@ -#include #include "snpemodel.h" void PrintErrorStringAndExit() { @@ -8,9 +7,8 @@ void PrintErrorStringAndExit() { } SNPEModel::SNPEModel(const uint8_t *model_data, const size_t model_size, float *output, size_t output_size) { -#ifdef QCOM assert(zdl::SNPE::SNPEFactory::isRuntimeAvailable(zdl::DlSystem::Runtime_t::GPU)); -#endif + // load model std::unique_ptr container = zdl::DlContainer::IDlContainer::open(model_data, model_size); if (!container) { PrintErrorStringAndExit(); } @@ -19,18 +17,11 @@ SNPEModel::SNPEModel(const uint8_t *model_data, const size_t model_size, float * // create model runner zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); while (!snpe) { -#ifdef QCOM snpe = snpeBuilder.setOutputLayers({}) .setRuntimeProcessor(zdl::DlSystem::Runtime_t::GPU) .setUseUserSuppliedBuffers(true) .setPerformanceProfile(zdl::DlSystem::PerformanceProfile_t::HIGH_PERFORMANCE) .build(); -#else - snpe = snpeBuilder.setOutputLayers({}) - .setUseUserSuppliedBuffers(true) - .setPerformanceProfile(zdl::DlSystem::PerformanceProfile_t::HIGH_PERFORMANCE) - .build(); -#endif if (!snpe) std::cerr << zdl::DlSystem::getLastErrorString() << std::endl; } diff --git a/selfdrive/visiond/visiond_pc.cc b/selfdrive/visiond/visiond_pc.cc deleted file mode 100644 index f30ddd78d8260b..00000000000000 --- a/selfdrive/visiond/visiond_pc.cc +++ /dev/null @@ -1,537 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#include -#include - -#include "common/version.h" -#include "common/util.h" -#include "common/timing.h" -#include "common/mat.h" -#include "common/swaglog.h" -#include "common/buffering.h" - -#include "clutil.h" -#include "bufs.h" - -#include "camera_eon_stream.h" - -#include "model.h" - -#include "cereal/gen/cpp/log.capnp.h" - -#define M_PI 3.14159265358979323846 - -// send net input on port 9000 -//#define SEND_NET_INPUT - -#define MAX_CLIENTS 5 - -#ifdef __APPLE__ -typedef void (*sighandler_t) (int); -#endif - -extern "C" { -volatile int do_exit = 0; -} - -namespace { -struct VisionState { - - int frame_width, frame_height; - - // cl state - cl_device_id device_id; - cl_context context; - - mat3 yuv_transform; - // OpenCL buffers for storing yuv frames from Eon stream - cl_mem yuv_cl[FRAME_BUF_COUNT]; - size_t yuv_buf_size; - int yuv_width, yuv_height; - - - ModelState model; - ModelData model_bufs[FRAME_BUF_COUNT]; - - // Protected by transform_lock. - bool run_model; - mat3 cur_transform; - pthread_mutex_t transform_lock; - - DualCameraState cameras; - - zsock_t *terminate_pub; - zsock_t *recorder_sock; - void* recorder_sock_raw; - - zsock_t *posenet_sock; - void* posenet_sock_raw; -}; - -void cl_init(VisionState *s) { - int err; - cl_platform_id platform_id = NULL; - cl_uint num_devices; - cl_uint num_platforms; - - err = clGetPlatformIDs(1, &platform_id, &num_platforms); - assert(err == 0); - err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, - &s->device_id, &num_devices); - assert(err == 0); - - cl_print_info(platform_id, s->device_id); - printf("\n"); - - s->context = clCreateContext(NULL, 1, &s->device_id, NULL, NULL, &err); - assert(err == 0); -} - -void cl_free(VisionState *s) { - int err; - - err = clReleaseContext(s->context); - assert(err == 0); -} - -void init_buffers(VisionState *s) { - int err; - - s->yuv_width = s->frame_width; - s->yuv_height = s->frame_height; - s->yuv_buf_size = s->frame_width * s->frame_height * 3 / 2; - for (int i=0; iyuv_cl[i] = clCreateBuffer(s->context, CL_MEM_READ_WRITE, - s->yuv_buf_size, NULL, &err); - assert(err == 0); - } - - s->yuv_transform = s->cameras.rear.transform; -} - -void free_buffers(VisionState *s) { - // free bufs - for (int i=0; iyuv_cl[i]); - } -} - -#define POSENET - -#ifdef POSENET -#include "snpemodel.h" -extern const uint8_t posenet_model_data[] asm("_binary_posenet_dlc_start"); -extern const uint8_t posenet_model_end[] asm("_binary_posenet_dlc_end"); -const size_t posenet_model_size = posenet_model_end - posenet_model_data; -#endif - -void* processing_thread(void *arg) { - int err; - VisionState *s = (VisionState*)arg; - set_thread_name("processing"); - err = set_realtime_priority(1); - LOG("setpriority returns %d", err); - - zsock_t *model_sock = zsock_new_pub("@tcp://*:8009"); - assert(model_sock); - void *model_sock_raw = zsock_resolve(model_sock); - -#ifdef SEND_NET_INPUT - zsock_t *img_sock = zsock_new_pub("@tcp://*:9000"); - assert(img_sock); - void *img_sock_raw = zsock_resolve(img_sock); -#else - void *img_sock_raw = NULL; -#endif - -#ifdef POSENET - int posenet_counter = 0; - float pose_output[12]; - float *posenet_input = (float*)malloc(2*200*532*sizeof(float)); - SNPEModel *posenet = new SNPEModel(posenet_model_data, posenet_model_size, - pose_output, sizeof(pose_output)/sizeof(float)); -#endif - - LOG("processing start!"); - - for (int cnt = 0; !do_exit; cnt++) { - int buf_idx = tbuffer_acquire(&s->cameras.rear.camera_tb); - if (buf_idx < 0) { - break; - } - - double t1 = millis_since_boot(); - - FrameMetadata frame_data = s->cameras.rear.camera_bufs_metadata[buf_idx]; - uint32_t frame_id = frame_data.frame_id; - - if (frame_id == -1) { - LOGE("no frame data? wtf"); - tbuffer_release(&s->cameras.rear.camera_tb, buf_idx); - continue; - } - - double t2 = millis_since_boot(); - - // Frames from Eon streaming is in yuv420 format - cl_mem yuv_cl = s->yuv_cl[buf_idx]; - pthread_mutex_lock(&s->transform_lock); - mat3 transform = s->cur_transform; - const bool run_model_this_iter = s->run_model; - pthread_mutex_unlock(&s->transform_lock); - - double mt1 = 0, mt2 = 0; - if (run_model_this_iter) { - mat3 model_transform = matmul3(s->yuv_transform, transform); - mt1 = millis_since_boot(); - s->model_bufs[buf_idx] = - model_eval_frame(&s->model, s->cameras.rear.q, yuv_cl, s->yuv_width, s->yuv_height, - model_transform, img_sock_raw); - mt2 = millis_since_boot(); - model_publish(model_sock_raw, frame_id, model_transform, s->model_bufs[buf_idx]); - } - cl_event map_event; - uint8_t* yuv_ptr_y = (uint8_t *)clEnqueueMapBuffer(s->cameras.rear.q, yuv_cl, CL_TRUE, - CL_MAP_READ, 0, s->yuv_buf_size, - 0, NULL, &map_event, &err); - clWaitForEvents(1, &map_event); - clReleaseEvent(map_event); - // send frame event - { - capnp::MallocMessageBuilder msg; - cereal::Event::Builder event = msg.initRoot(); - event.setLogMonoTime(nanos_since_boot()); - - auto framed = event.initFrame(); - framed.setFrameId(frame_data.frame_id); - framed.setEncodeId(cnt); - framed.setTimestampEof(frame_data.timestamp_eof); - framed.setFrameLength(frame_data.frame_length); - framed.setIntegLines(frame_data.integ_lines); - framed.setGlobalGain(frame_data.global_gain); - framed.setLensPos(frame_data.lens_pos); - framed.setLensSag(frame_data.lens_sag); - framed.setLensErr(frame_data.lens_err); - framed.setLensTruePos(frame_data.lens_true_pos); - - framed.setImage(kj::arrayPtr((const uint8_t*)yuv_ptr_y, s->yuv_buf_size)); - - kj::ArrayPtr transform_vs(&s->yuv_transform.v[0], 9); - framed.setTransform(transform_vs); - - auto words = capnp::messageToFlatArray(msg); - auto bytes = words.asBytes(); - zmq_send(s->recorder_sock_raw, bytes.begin(), bytes.size(), ZMQ_DONTWAIT); - } - - -#ifdef POSENET - double pt1 = 0, pt2 = 0, pt3 = 0; - pt1 = millis_since_boot(); - - // move second frame to first frame - memmove(&posenet_input[0], &posenet_input[1], sizeof(float)*(200*532*2 - 1)); - - // fill posenet input - float a; - // posenet uses a half resolution cropped frame - // with upper left corner: [50, 237] and - // bottom right corner: [1114, 637] - // So the resulting crop is 532 X 200 - for (int y=237; y<637; y+=2) { - int yy = (y-237)/2; - for (int x = 50; x < 1114; x+=2) { - int xx = (x-50)/2; - a = 0; - a += yuv_ptr_y[s->yuv_width*(y+0) + (x+1)]; - a += yuv_ptr_y[s->yuv_width*(y+1) + (x+1)]; - a += yuv_ptr_y[s->yuv_width*(y+0) + (x+0)]; - a += yuv_ptr_y[s->yuv_width*(y+1) + (x+0)]; - // The posenet takes a normalized image input - // like the driving model so [0,255] is remapped - // to [-1,1] - posenet_input[(yy*532+xx)*2 + 1] = (a/512.0 - 1.0); - } - } - //FILE *fp; - //fp = fopen( "testing" , "r" ); - //fread(posenet_input , sizeof(float) , 200*532*2 , fp); - //fclose(fp); - //sleep(5); - - pt2 = millis_since_boot(); - - posenet_counter++; - - if (posenet_counter % 5 == 0){ - // run posenet - //printf("avg %f\n", pose_output[0]); - posenet->execute(posenet_input); - - - // fix stddevs - for (int i = 6; i < 12; i++) { - pose_output[i] = log1p(exp(pose_output[i])) + 1e-6; - } - // to radians - for (int i = 3; i < 6; i++) { - pose_output[i] = M_PI * pose_output[i] / 180.0; - } - // to radians - for (int i = 9; i < 12; i++) { - pose_output[i] = M_PI * pose_output[i] / 180.0; - } - - // send posenet event - { - capnp::MallocMessageBuilder msg; - cereal::Event::Builder event = msg.initRoot(); - event.setLogMonoTime(nanos_since_boot()); - - auto posenetd = event.initCameraOdometry(); - kj::ArrayPtr trans_vs(&pose_output[0], 3); - posenetd.setTrans(trans_vs); - kj::ArrayPtr rot_vs(&pose_output[3], 3); - posenetd.setRot(rot_vs); - kj::ArrayPtr trans_std_vs(&pose_output[6], 3); - posenetd.setTransStd(trans_std_vs); - kj::ArrayPtr rot_std_vs(&pose_output[9], 3); - posenetd.setRotStd(rot_std_vs); - - auto words = capnp::messageToFlatArray(msg); - auto bytes = words.asBytes(); - zmq_send(s->posenet_sock_raw, bytes.begin(), bytes.size(), ZMQ_DONTWAIT); - } - pt3 = millis_since_boot(); - LOGD("pre: %.2fms | posenet: %.2fms", (pt2-pt1), (pt3-pt1)); - } -#endif - - - // auto exposure over big box - const int exposure_x = 290; - const int exposure_y = 282 + 40; - const int exposure_height = 314; - const int exposure_width = 560; - if (cnt % 3 == 0) { - // find median box luminance for AE - uint32_t lum_binning[256] = {0,}; - for (int y=0; yyuv_width) + exposure_x + x]; - lum_binning[lum]++; - } - } - const unsigned int lum_total = exposure_height * exposure_width; - unsigned int lum_cur = 0; - int lum_med = 0; - for (lum_med=0; lum_med<256; lum_med++) { - // shouldn't be any values less than 16 - yuv footroom - lum_cur += lum_binning[lum_med]; - if (lum_cur >= lum_total / 2) { - break; - } - } - // double avg = (double)acc / (big_box_width * big_box_height) - 16; - // printf("avg %d\n", lum_med); - - camera_autoexposure(&s->cameras.rear, lum_med / 256.0); - } - - clEnqueueUnmapMemObject(s->cameras.rear.q, yuv_cl, yuv_ptr_y, 0, NULL, &map_event); - clWaitForEvents(1, &map_event); - clReleaseEvent(map_event); - tbuffer_release(&s->cameras.rear.camera_tb, buf_idx); - double t5 = millis_since_boot(); - LOGD("queued: %.2fms, model: %.2fms | processing: %.3fms", - (t2-t1), (mt2-mt1), (t5-t1)); - } - - zsock_destroy(&model_sock); - - return NULL; -} - -void* live_thread(void *arg) { - int err; - VisionState *s = (VisionState*)arg; - - set_thread_name("live"); - - zsock_t *terminate = zsock_new_sub(">inproc://terminate", ""); - assert(terminate); - - zsock_t *liveCalibration_sock = zsock_new_sub(">tcp://127.0.0.1:8019", ""); - assert(liveCalibration_sock); - - zpoller_t *poller = zpoller_new(liveCalibration_sock, terminate, NULL); - assert(poller); - - while (!do_exit) { - zsock_t *which = (zsock_t*)zpoller_wait(poller, -1); - if (which == terminate || which == NULL) { - break; - } - - zmq_msg_t msg; - err = zmq_msg_init(&msg); - assert(err == 0); - - err = zmq_msg_recv(&msg, zsock_resolve(which), 0); - assert(err >= 0); - size_t len = zmq_msg_size(&msg); - - // make copy due to alignment issues, will be freed on out of scope - auto amsg = kj::heapArray((len / sizeof(capnp::word)) + 1); - memcpy(amsg.begin(), (const uint8_t*)zmq_msg_data(&msg), len); - - // track camera frames to sync to encoder - capnp::FlatArrayMessageReader cmsg(amsg); - cereal::Event::Reader event = cmsg.getRoot(); - - if (event.isLiveCalibration()) { - pthread_mutex_lock(&s->transform_lock); -#ifdef BIGMODEL - auto wm2 = event.getLiveCalibration().getWarpMatrixBig(); -#else - auto wm2 = event.getLiveCalibration().getWarpMatrix2(); -#endif - assert(wm2.size() == 3*3); - for (int i=0; i<3*3; i++) { - s->cur_transform.v[i] = wm2[i]; - } - s->run_model = true; - pthread_mutex_unlock(&s->transform_lock); - } - - zmq_msg_close(&msg); - } - - zpoller_destroy(&poller); - zsock_destroy(&terminate); - - zsock_destroy(&liveCalibration_sock); - - return NULL; -} - -void set_do_exit(int sig) { - do_exit = 1; -} - -void party(VisionState *s, bool nomodel) { - int err; - - s->terminate_pub = zsock_new_pub("@inproc://terminate"); - assert(s->terminate_pub); - - pthread_t proc_thread_handle; - err = pthread_create(&proc_thread_handle, NULL, - processing_thread, s); - assert(err == 0); - - pthread_t live_thread_handle; - err = pthread_create(&live_thread_handle, NULL, - live_thread, s); - assert(err == 0); - - // priority for cameras - err = set_realtime_priority(1); - LOG("setpriority returns %d", err); - - cameras_run(&s->cameras); - - zsock_signal(s->terminate_pub, 0); - - LOG("joining proc_thread"); - err = pthread_join(proc_thread_handle, NULL); - assert(err == 0); - - LOG("joining live_thread"); - err = pthread_join(live_thread_handle, NULL); - assert(err == 0); - - zsock_destroy (&s->terminate_pub); -} - -} - -int main(int argc, char **argv) { - int err; - - zsys_handler_set(NULL); - signal(SIGINT, (sighandler_t)set_do_exit); - signal(SIGTERM, (sighandler_t)set_do_exit); - - // boringssl via curl via the calibration api can sometimes - // try to write to a closed socket. just ignore SIGPIPE - signal(SIGPIPE, SIG_IGN); - - bool no_model = false; - if (argc > 1 && strcmp(argv[1], "--no-model") == 0) { - no_model = true; - } - - VisionState state = {0}; - VisionState *s = &state; - - clu_init(); - cl_init(s); - - model_init(&s->model, s->device_id, s->context, true); - - cameras_init(&s->cameras); - - s->frame_width = s->cameras.rear.ci.frame_width; - s->frame_height = s->cameras.rear.ci.frame_height; - - // Do not run the model until we receive valid calibration. - s->run_model = false; - pthread_mutex_init(&s->transform_lock, NULL); - - init_buffers(s); - - s->recorder_sock = zsock_new_pub("@tcp://*:8002"); - assert(s->recorder_sock); - s->recorder_sock_raw = zsock_resolve(s->recorder_sock); - - s->posenet_sock = zsock_new_pub("@tcp://*:8066"); - assert(s->posenet_sock); - s->posenet_sock_raw = zsock_resolve(s->posenet_sock); - - const cl_queue_properties props[] = {0}; - cl_command_queue q = clCreateCommandQueueWithProperties(s->context, s->device_id, props, &err); - cameras_open(&s->cameras, &s->yuv_cl[0], s->device_id, s->context, q); - - party(s, no_model); - - zsock_destroy(&s->recorder_sock); - - model_free(&s->model); - free_buffers(s); - - cl_free(s); - - return 0; -}