Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 1 | #!/usr/bin/python3 |
| 2 | |
| 3 | import camera_definition |
| 4 | import cv2 |
| 5 | import flatbuffers |
| 6 | import glog |
| 7 | import numpy as np |
| 8 | import sys |
| 9 | |
| 10 | import frc971.vision.calibration.CalibrationData as CalibrationData |
| 11 | import frc971.vision.calibration.CameraCalibration as CameraCalibration |
| 12 | import frc971.vision.calibration.TransformationMatrix as TransformationMatrix |
| 13 | |
| 14 | import gflags |
| 15 | import glog |
| 16 | |
| 17 | FLAGS = gflags.FLAGS |
| 18 | |
| 19 | |
| 20 | # Takes a 3x3 rotation matrix and 3x1 translation vector, and outputs 12 |
| 21 | # element list, suitable for outputing to flatbuffer |
| 22 | def rot_and_trans_to_list(R, T): |
| 23 | output_list = [] |
| 24 | for row in range(3): |
| 25 | for col in range(3): |
| 26 | output_list.append(R[row][col]) |
| 27 | output_list.append(T[row]) |
| 28 | |
| 29 | output_list = output_list + [0., 0., 0., 1.] |
| 30 | return output_list |
| 31 | |
| 32 | |
| 33 | def list_to_transformation_matrix(values, fbb): |
| 34 | """Puts a list of values into an FBB TransformationMatrix.""" |
| 35 | |
| 36 | TransformationMatrix.TransformationMatrixStartDataVector(fbb, len(values)) |
| 37 | for n in reversed(values): |
| 38 | fbb.PrependFloat32(n) |
James Kuszmaul | dac091f | 2022-03-22 09:35:06 -0700 | [diff] [blame^] | 39 | list_offset = fbb.EndVector() |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 40 | |
| 41 | TransformationMatrix.TransformationMatrixStart(fbb) |
| 42 | TransformationMatrix.TransformationMatrixAddData(fbb, list_offset) |
| 43 | return TransformationMatrix.TransformationMatrixEnd(fbb) |
| 44 | |
| 45 | |
| 46 | def main(): |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 47 | camera_calib_list = camera_definition.load_camera_definitions() |
| 48 | |
Jim Ostrowski | fec0c33 | 2022-02-06 23:28:26 -0800 | [diff] [blame] | 49 | output_path = sys.argv[1] |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 50 | glog.debug("Writing file to %s", output_path) |
| 51 | |
| 52 | fbb = flatbuffers.Builder(0) |
| 53 | |
| 54 | images_vector = [] |
| 55 | |
| 56 | # Create camera calibration data |
| 57 | camera_calibration_vector = [] |
| 58 | for camera_calib in camera_calib_list: |
| 59 | fixed_extrinsics_list = rot_and_trans_to_list( |
| 60 | camera_calib.camera_ext.R, camera_calib.camera_ext.T) |
| 61 | fixed_extrinsics_vector = list_to_transformation_matrix( |
| 62 | fixed_extrinsics_list, fbb) |
| 63 | |
| 64 | turret_extrinsics_vector = None |
| 65 | if camera_calib.turret_ext is not None: |
| 66 | turret_extrinsics_list = rot_and_trans_to_list( |
| 67 | camera_calib.turret_ext.R, camera_calib.turret_ext.T) |
| 68 | turret_extrinsics_vector = list_to_transformation_matrix( |
| 69 | turret_extrinsics_list, fbb) |
| 70 | |
| 71 | camera_int_list = camera_calib.camera_int.camera_matrix.ravel().tolist( |
| 72 | ) |
| 73 | CameraCalibration.CameraCalibrationStartIntrinsicsVector( |
| 74 | fbb, len(camera_int_list)) |
| 75 | for n in reversed(camera_int_list): |
| 76 | fbb.PrependFloat32(n) |
James Kuszmaul | dac091f | 2022-03-22 09:35:06 -0700 | [diff] [blame^] | 77 | intrinsics_vector = fbb.EndVector() |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 78 | |
| 79 | dist_coeffs_list = camera_calib.camera_int.dist_coeffs.ravel().tolist() |
| 80 | CameraCalibration.CameraCalibrationStartDistCoeffsVector( |
| 81 | fbb, len(dist_coeffs_list)) |
| 82 | for n in reversed(dist_coeffs_list): |
| 83 | fbb.PrependFloat32(n) |
James Kuszmaul | dac091f | 2022-03-22 09:35:06 -0700 | [diff] [blame^] | 84 | dist_coeffs_vector = fbb.EndVector() |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 85 | |
| 86 | node_name_offset = fbb.CreateString(camera_calib.node_name) |
| 87 | CameraCalibration.CameraCalibrationStart(fbb) |
| 88 | CameraCalibration.CameraCalibrationAddNodeName(fbb, node_name_offset) |
| 89 | CameraCalibration.CameraCalibrationAddTeamNumber( |
| 90 | fbb, camera_calib.team_number) |
| 91 | CameraCalibration.CameraCalibrationAddIntrinsics( |
| 92 | fbb, intrinsics_vector) |
| 93 | CameraCalibration.CameraCalibrationAddDistCoeffs( |
| 94 | fbb, dist_coeffs_vector) |
| 95 | CameraCalibration.CameraCalibrationAddFixedExtrinsics( |
| 96 | fbb, fixed_extrinsics_vector) |
| 97 | if turret_extrinsics_vector is not None: |
| 98 | CameraCalibration.CameraCalibrationAddTurretExtrinsics( |
| 99 | fbb, turret_extrinsics_vector) |
| 100 | camera_calibration_vector.append( |
| 101 | CameraCalibration.CameraCalibrationEnd(fbb)) |
| 102 | |
| 103 | CalibrationData.CalibrationDataStartCameraCalibrationsVector( |
| 104 | fbb, len(camera_calibration_vector)) |
| 105 | for camera_calibration in reversed(camera_calibration_vector): |
| 106 | fbb.PrependUOffsetTRelative(camera_calibration) |
James Kuszmaul | dac091f | 2022-03-22 09:35:06 -0700 | [diff] [blame^] | 107 | camera_calibration_vector_table = fbb.EndVector() |
Jim Ostrowski | 007e2ea | 2022-01-30 13:13:26 -0800 | [diff] [blame] | 108 | |
| 109 | # Fill out TrainingData |
| 110 | CalibrationData.CalibrationDataStart(fbb) |
| 111 | CalibrationData.CalibrationDataAddCameraCalibrations( |
| 112 | fbb, camera_calibration_vector_table) |
| 113 | fbb.Finish(CalibrationData.CalibrationDataEnd(fbb)) |
| 114 | |
| 115 | bfbs = fbb.Output() |
| 116 | |
| 117 | output_prefix = [ |
| 118 | b'#ifndef Y2022_VISION_CALIBRATION_DATA_H_', |
| 119 | b'#define Y2022_VISION_CALIBRATION_DATA_H_', |
| 120 | b'#include <stdint.h>', |
| 121 | b'#include "absl/types/span.h"', |
| 122 | b'namespace frc971 {', |
| 123 | b'namespace vision {', |
| 124 | b'inline absl::Span<const uint8_t> CalibrationData() {', |
| 125 | ] |
| 126 | output_suffix = [ |
| 127 | b' return absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(kData), sizeof(kData));', |
| 128 | b'}', |
| 129 | b'} // namespace vision', |
| 130 | b'} // namespace frc971', |
| 131 | b'#endif // Y2022_VISION_CALIBRATION_DATA_H_', |
| 132 | ] |
| 133 | |
| 134 | # Write out the header file |
| 135 | with open(output_path, 'wb') as output: |
| 136 | for line in output_prefix: |
| 137 | output.write(line) |
| 138 | output.write(b'\n') |
| 139 | output.write(b'alignas(64) static constexpr char kData[] = "') |
| 140 | for byte in fbb.Output(): |
| 141 | output.write(b'\\x' + (b'%x' % byte).zfill(2)) |
| 142 | output.write(b'";\n') |
| 143 | for line in output_suffix: |
| 144 | output.write(line) |
| 145 | output.write(b'\n') |
| 146 | |
| 147 | |
| 148 | if __name__ == '__main__': |
| 149 | argv = FLAGS(sys.argv) |
| 150 | glog.init() |
| 151 | main() |