11#include < cstdio>
22#include < cstdlib>
33#include < mutex>
4+ #include < cmath>
45
56#include < eigen3/Eigen/Dense>
67
1516
1617ExitHandler do_exit;
1718
18- mat3 update_calibration (cereal::LiveCalibrationData::Reader live_calib, bool wide_camera) {
19+ mat3 update_calibration (Eigen::Matrix< float , 3 , 4 > &extrinsics, bool wide_camera, bool bigmodel_frame ) {
1920 /*
2021 import numpy as np
2122 from common.transformations.model import medmodel_frame_from_road_frame
2223 medmodel_frame_from_ground = medmodel_frame_from_road_frame[:, (0, 1, 3)]
2324 ground_from_medmodel_frame = np.linalg.inv(medmodel_frame_from_ground)
2425 */
25- static const auto ground_from_medmodel_frame = (Eigen::Matrix<float , 3 , 3 >() <<
26- 0.00000000e+00 , 0.00000000e+00 , 1.00000000e+00 ,
26+ static const auto ground_from_medmodel_frame = (Eigen::Matrix<float , 3 , 3 >() <<
27+ 0.00000000e+00 , 0.00000000e+00 , 1.00000000e+00 ,
2728 -1.09890110e-03 , 0.00000000e+00 , 2.81318681e-01 ,
2829 -1.84808520e-20 , 9.00738606e-04 , -4.28751576e-02 ).finished ();
2930
31+ static const auto ground_from_sbigmodel_frame = (Eigen::Matrix<float , 3 , 3 >() <<
32+ 0.00000000e+00 , 7.31372216e-19 , 1.00000000e+00 ,
33+ -2.19780220e-03 , 4.11497335e-19 , 5.62637363e-01 ,
34+ -5.46146580e-20 , 1.80147721e-03 , -2.73464241e-01 ).finished ();
35+
3036 static const auto cam_intrinsics = Eigen::Matrix<float , 3 , 3 , Eigen::RowMajor>(wide_camera ? ecam_intrinsic_matrix.v : fcam_intrinsic_matrix.v );
3137 static const mat3 yuv_transform = get_model_yuv_transform ();
3238
33- auto extrinsic_matrix = live_calib.getExtrinsicMatrix ();
34- Eigen::Matrix<float , 3 , 4 > extrinsic_matrix_eigen;
35- for (int i = 0 ; i < 4 *3 ; i++) {
36- extrinsic_matrix_eigen (i / 4 , i % 4 ) = extrinsic_matrix[i];
37- }
38-
39- auto camera_frame_from_road_frame = cam_intrinsics * extrinsic_matrix_eigen;
39+ auto ground_from_model_frame = bigmodel_frame ? ground_from_sbigmodel_frame : ground_from_medmodel_frame;
40+ auto camera_frame_from_road_frame = cam_intrinsics * extrinsics;
4041 Eigen::Matrix<float , 3 , 3 > camera_frame_from_ground;
4142 camera_frame_from_ground.col (0 ) = camera_frame_from_road_frame.col (0 );
4243 camera_frame_from_ground.col (1 ) = camera_frame_from_road_frame.col (1 );
4344 camera_frame_from_ground.col (2 ) = camera_frame_from_road_frame.col (3 );
4445
45- auto warp_matrix = camera_frame_from_ground * ground_from_medmodel_frame ;
46+ auto warp_matrix = camera_frame_from_ground * ground_from_model_frame ;
4647 mat3 transform = {};
4748 for (int i=0 ; i<3 *3 ; i++) {
4849 transform.v [i] = warp_matrix (i / 3 , i % 3 );
4950 }
5051 return matmul3 (yuv_transform, transform);
5152}
5253
53- void run_model (ModelState &model, VisionIpcClient &vipc_client, bool wide_camera ) {
54+ void run_model (ModelState &model, VisionIpcClient &vipc_client_main, VisionIpcClient &vipc_client_extra, bool main_wide_camera, bool use_extra, bool use_extra_client ) {
5455 // messaging
5556 PubMaster pm ({" modelV2" , " cameraOdometry" });
5657 SubMaster sm ({" lateralPlan" , " roadCameraState" , " liveCalibration" });
@@ -62,20 +63,80 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
6263 double last = 0 ;
6364 uint32_t run_count = 0 ;
6465
65- mat3 model_transform = {};
66+ mat3 model_transform_main = {};
67+ mat3 model_transform_extra = {};
6668 bool live_calib_seen = false ;
6769
70+ VisionBuf *buf_main = nullptr ;
71+ VisionBuf *buf_extra = nullptr ;
72+
73+ VisionIpcBufExtra meta_main = {0 };
74+ VisionIpcBufExtra meta_extra = {0 };
75+
6876 while (!do_exit) {
69- VisionIpcBufExtra extra = {};
70- VisionBuf *buf = vipc_client.recv (&extra);
71- if (buf == nullptr ) continue ;
77+ // TODO: change sync logic to use timestamp start of frame in case camerad skips a frame
78+ // log frame id in model packet
79+
80+ // Keep receiving frames until we are at least 1 frame ahead of previous extra frame
81+ while (meta_main.frame_id <= meta_extra.frame_id ) {
82+ buf_main = vipc_client_main.recv (&meta_main);
83+ if (meta_main.frame_id <= meta_extra.frame_id ) {
84+ LOGE (" main camera behind! main: %d (%.5f), extra: %d (%.5f)" ,
85+ meta_main.frame_id , double (meta_main.timestamp_sof ) / 1e9 ,
86+ meta_extra.frame_id , double (meta_extra.timestamp_sof ) / 1e9 );
87+ }
88+
89+ if (buf_main == nullptr ) break ;
90+ }
91+
92+ if (buf_main == nullptr ) {
93+ LOGE (" vipc_client_main no frame" );
94+ continue ;
95+ }
96+
97+ if (use_extra_client) {
98+ // Keep receiving extra frames until frame id matches main camera
99+ do {
100+ buf_extra = vipc_client_extra.recv (&meta_extra);
101+
102+ if (meta_main.frame_id > meta_extra.frame_id ) {
103+ LOGE (" extra camera behind! main: %d (%.5f), extra: %d (%.5f)" ,
104+ meta_main.frame_id , double (meta_main.timestamp_sof ) / 1e9 ,
105+ meta_extra.frame_id , double (meta_extra.timestamp_sof ) / 1e9 );
106+ }
107+ } while (buf_extra != nullptr && meta_main.frame_id > meta_extra.frame_id );
108+
109+ if (buf_extra == nullptr ) {
110+ LOGE (" vipc_client_extra no frame" );
111+ continue ;
112+ }
113+
114+ if (meta_main.frame_id != meta_extra.frame_id || std::abs ((int64_t )meta_main.timestamp_sof - (int64_t )meta_extra.timestamp_sof ) > 10000000ULL ) {
115+ LOGE (" frames out of sync! main: %d (%.5f), extra: %d (%.5f)" ,
116+ meta_main.frame_id , double (meta_main.timestamp_sof ) / 1e9 ,
117+ meta_extra.frame_id , double (meta_extra.timestamp_sof ) / 1e9 );
118+ }
119+ } else {
120+ // Use single camera
121+ buf_extra = buf_main;
122+ meta_extra = meta_main;
123+ }
72124
73125 // TODO: path planner timeout?
74126 sm.update (0 );
75127 int desire = ((int )sm[" lateralPlan" ].getLateralPlan ().getDesire ());
76128 frame_id = sm[" roadCameraState" ].getRoadCameraState ().getFrameId ();
77129 if (sm.updated (" liveCalibration" )) {
78- model_transform = update_calibration (sm[" liveCalibration" ].getLiveCalibration (), wide_camera);
130+ auto extrinsic_matrix = sm[" liveCalibration" ].getLiveCalibration ().getExtrinsicMatrix ();
131+ Eigen::Matrix<float , 3 , 4 > extrinsic_matrix_eigen;
132+ for (int i = 0 ; i < 4 *3 ; i++) {
133+ extrinsic_matrix_eigen (i / 4 , i % 4 ) = extrinsic_matrix[i];
134+ }
135+
136+ model_transform_main = update_calibration (extrinsic_matrix_eigen, main_wide_camera, false );
137+ if (use_extra) {
138+ model_transform_extra = update_calibration (extrinsic_matrix_eigen, Hardware::TICI (), true );
139+ }
79140 live_calib_seen = true ;
80141 }
81142
@@ -85,13 +146,12 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
85146 }
86147
87148 double mt1 = millis_since_boot ();
88- ModelOutput *model_output = model_eval_frame (&model, buf->buf_cl , buf->width , buf->height ,
89- model_transform, vec_desire);
149+ ModelOutput *model_output = model_eval_frame (&model, buf_main, buf_extra, model_transform_main, model_transform_extra, vec_desire);
90150 double mt2 = millis_since_boot ();
91151 float model_execution_time = (mt2 - mt1) / 1000.0 ;
92152
93153 // tracked dropped frames
94- uint32_t vipc_dropped_frames = extra .frame_id - last_vipc_frame_id - 1 ;
154+ uint32_t vipc_dropped_frames = meta_main .frame_id - last_vipc_frame_id - 1 ;
95155 float frames_dropped = frame_dropped_filter.update ((float )std::min (vipc_dropped_frames, 10U ));
96156 if (run_count < 10 ) { // let frame drops warm up
97157 frame_dropped_filter.reset (0 );
@@ -101,13 +161,13 @@ void run_model(ModelState &model, VisionIpcClient &vipc_client, bool wide_camera
101161
102162 float frame_drop_ratio = frames_dropped / (1 + frames_dropped);
103163
104- model_publish (pm, extra .frame_id , frame_id, frame_drop_ratio, *model_output, extra .timestamp_eof , model_execution_time,
164+ model_publish (pm, meta_main .frame_id , frame_id, frame_drop_ratio, *model_output, meta_main .timestamp_eof , model_execution_time,
105165 kj::ArrayPtr<const float >(model.output .data (), model.output .size ()), live_calib_seen);
106- posenet_publish (pm, extra .frame_id , vipc_dropped_frames, *model_output, extra .timestamp_eof , live_calib_seen);
166+ posenet_publish (pm, meta_main .frame_id , vipc_dropped_frames, *model_output, meta_main .timestamp_eof , live_calib_seen);
107167
108168 // printf("model process: %.2fms, from last %.2fms, vipc_frame_id %u, frame_id, %u, frame_drop %.3f\n", mt2 - mt1, mt1 - last, extra.frame_id, frame_id, frame_drop_ratio);
109169 last = mt1;
110- last_vipc_frame_id = extra .frame_id ;
170+ last_vipc_frame_id = meta_main .frame_id ;
111171 }
112172}
113173
@@ -120,28 +180,42 @@ int main(int argc, char **argv) {
120180 assert (ret == 0 );
121181 }
122182
123- bool wide_camera = Hardware::TICI () ? Params ().getBool (" EnableWideCamera" ) : false ;
183+ bool main_wide_camera = Hardware::TICI () ? Params ().getBool (" EnableWideCamera" ) : false ;
184+ bool use_extra = USE_EXTRA;
185+ bool use_extra_client = Hardware::TICI () && use_extra && !main_wide_camera;
124186
125187 // cl init
126188 cl_device_id device_id = cl_get_device_id (CL_DEVICE_TYPE_DEFAULT);
127189 cl_context context = CL_CHECK_ERR (clCreateContext (NULL , 1 , &device_id, NULL , NULL , &err));
128190
129191 // init the models
130192 ModelState model;
131- model_init (&model, device_id, context);
193+ model_init (&model, device_id, context, use_extra );
132194 LOGW (" models loaded, modeld starting" );
133195
134- VisionIpcClient vipc_client = VisionIpcClient (" camerad" , wide_camera ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD, true , device_id, context);
135- while (!do_exit && !vipc_client.connect (false )) {
196+ VisionIpcClient vipc_client_main = VisionIpcClient (" camerad" , main_wide_camera ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD, true , device_id, context);
197+ VisionIpcClient vipc_client_extra = VisionIpcClient (" camerad" , VISION_STREAM_WIDE_ROAD, false , device_id, context);
198+
199+ while (!do_exit && !vipc_client_main.connect (false )) {
200+ util::sleep_for (100 );
201+ }
202+
203+ while (!do_exit && use_extra_client && !vipc_client_extra.connect (false )) {
136204 util::sleep_for (100 );
137205 }
138206
139207 // run the models
140208 // vipc_client.connected is false only when do_exit is true
141- if (vipc_client.connected ) {
142- const VisionBuf *b = &vipc_client.buffers [0 ];
143- LOGW (" connected with buffer size: %d (%d x %d)" , b->len , b->width , b->height );
144- run_model (model, vipc_client, wide_camera);
209+ if (!do_exit) {
210+ const VisionBuf *b = &vipc_client_main.buffers [0 ];
211+ LOGW (" connected main cam with buffer size: %d (%d x %d)" , b->len , b->width , b->height );
212+
213+ if (use_extra_client) {
214+ const VisionBuf *wb = &vipc_client_extra.buffers [0 ];
215+ LOGW (" connected extra cam with buffer size: %d (%d x %d)" , wb->len , wb->width , wb->height );
216+ }
217+
218+ run_model (model, vipc_client_main, vipc_client_extra, main_wide_camera, use_extra, use_extra_client);
145219 }
146220
147221 model_free (&model);
0 commit comments