Calibration between TarantulaX and Your Mobile Phone
Calibrating the TarantulaX and a mobile phone camera involves determining the intrinsic parameters of the mobile camera, the extrinsic parameters between the camera and the TarantulaX system.
Camera calibrations are made from two sets of numbers: Intrinsics parameters, and Extrinsic parameters.
Intrinsics compensate for properties of the camera itself, such as focal length and lens distortion. Extrinsics describe the position and rotation of the camera with respect to the vehicle/TarantulaX .
These values are unique to a camera, and should not be transplanted to other cameras or vehicles.
Intrinsics Parameters:
Camera intrinsics are structured as an array of floating-point values in the following order:
[fx,fy,cx,cy,k1,k2,k3,p1,p2]
plus a lens distortion model type, which could be "Tan" or "ArcTan":
[fₓ , fᵧ] = focal lengths in pixels. While the instructions above will produce correctly scaled values, the values in the EEPROM of the camera will be in millimeters. To convert these "actual focal lengths" into pixels, divide by the pixel-pitch of the camera (0.00375 mm/px). The focal lengths must also be scaled according to the image resolution that you are undistorting (ie. since vision uses half-sized frames, you must divide by 2).
[cₓ , cᵧ] = center of distortion, in absolute pixel values. The EEPROM values will be relative to the images center (ie, -2,). All cameras will have a tolerance of +/-15 px, hence, having a nominal value of zero is common.
The meaning of the other coefficients depends on the lens distortion model. When it is "Tan" model. In short,
[k₁, k₂, k₃] = radial distortion coefficients. These are ~arbitrary, resolution-independent values that distort the image as a function of radius from (cₓ , cᵧ). k₁ is the dominant term and generally defines the direction of the distortion correction.
x' = x(1 + k₁ r² + k₂ r⁴ + k₃ r⁶ )
k₁ > 0 = barrel distortion
k₁ < 0 = pincushion distortion
[p₁, p₂] = tangential distortion coefficients. These account for lenses that are slightly tilted. For nominal values, these are often set to zero
[k₁, k₂, k₃] = radial distortion coefficients. These are resolution-independent values that distort the image as a function of angle from the principal point.
Since we are using a mobile phone camera, which is generally a zoom camera, we need to first adjust the camera to a fixed-focus camera and set the focal length value. Below is the sample code for Samsung Camera SDK:
importcom.samsung.android.sdk.camera.SCamera;importcom.samsung.android.sdk.camera.SCameraManager;importcom.samsung.android.sdk.camera.SCameraCharacteristics;importcom.samsung.android.sdk.camera.SCaptureRequest;importcom.samsung.android.sdk.camera.SCaptureRequest.Builder;importcom.samsung.android.sdk.camera.SCaptureSession;importcom.samsung.android.sdk.camera.SCameraCaptureSession;importcom.samsung.android.sdk.camera.SCaptureResult;publicclassCameraActivityextendsAppCompatActivity {privateSCamera mCamera;privateSCameraManager mCameraManager;privateSCameraCharacteristics mCharacteristics;privateSCaptureRequest.Builder mCaptureRequestBuilder;privateSCaptureSession mCaptureSession; @OverrideprotectedvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera);// Initialize the camera mCamera =SCamera.getInstance(); mCameraManager =mCamera.getSCameraManager();// Get camera characteristicstry {String cameraId =getCameraId(); mCharacteristics =mCameraManager.getCameraCharacteristics(cameraId);// Set focus mode to manual focusmCaptureRequestBuilder.set(SCaptureRequest.CONTROL_AF_MODE,SCaptureRequest.CONTROL_AF_MODE_OFF);// Set focus distance (in millimeters)mCaptureRequestBuilder.set(SCaptureRequest.LENS_FOCUS_DISTANCE,50f); // For example, set focus distance to 50 millimeters// Create capture requestSCaptureRequest captureRequest =mCaptureRequestBuilder.build();// Create capture sessionmCamera.createCaptureSession(Arrays.asList(mSurface),new SCameraCaptureSession.StateCallback() { @OverridepublicvoidonConfigured(SCaptureSession session) { mCaptureSession = session;try {// Start capturemCaptureSession.setRepeatingRequest(captureRequest,null,null); } catch (SCameraAccessException e) {e.printStackTrace(); } } @OverridepublicvoidonConfigureFailed(SCaptureSession session) {// Handle configuration failure } },null); } catch (SCameraAccessException e) {e.printStackTrace(); } }// Get camera IDprivateStringgetCameraId() throwsSCameraAccessException {for (String cameraId :mCameraManager.getCameraIdList()) {SCameraCharacteristics characteristics =mCameraManager.getCameraCharacteristics(cameraId);// Check if it's a rear-facing cameraInteger facing =characteristics.get(SCameraCharacteristics.LENS_FACING);if (facing !=null&& facing ==SCameraCharacteristics.LENS_FACING_BACK) {return cameraId; } }returnnull; }}
While we set the camera to fixed-focus, we can also retrieve the camera's intrinsic parameters. Here's an example code using the Samsung Camera SDK:
importandroid.content.Context;importandroid.util.Log;importcom.samsung.android.sdk.camera.SCamera;importcom.samsung.android.sdk.camera.SCameraCharacteristics;importcom.samsung.android.sdk.camera.SCameraManager;importcom.samsung.android.sdk.SsdkUnsupportedException;publicclassSamsungCameraParameters {privateSCamera sCamera;privateSCameraManager sCameraManager;privateSCameraCharacteristics characteristics;publicSamsungCameraParameters(Context context) {// Initialize SCamera instance sCamera =newSCamera();try {sCamera.initialize(context); } catch (SsdkUnsupportedException e) {e.printStackTrace(); }// Get SCameraManager instance sCameraManager =sCamera.getSCameraManager(); }publicvoidgetCameraParameters(String cameraId) {try {// Get camera characteristics for the specified camera ID characteristics =sCameraManager.getCameraCharacteristics(cameraId);// Get focal lengthsfloat[] focalLengths =characteristics.get(SCameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);if (focalLengths !=null&&focalLengths.length>0) {Log.d("SamsungCamera","Focal Length: "+ focalLengths[0]); }// Get sensor sizeSizeF sensorSize =characteristics.get(SCameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);if (sensorSize !=null) {Log.d("SamsungCamera","Sensor Width: "+sensorSize.getWidth());Log.d("SamsungCamera","Sensor Height: "+sensorSize.getHeight()); }// Get principal point (assumed to be at the center of the sensor)float principalPointX =sensorSize.getWidth() /2;float principalPointY =sensorSize.getHeight() /2;Log.d("SamsungCamera","Principal Point X: "+ principalPointX);Log.d("SamsungCamera","Principal Point Y: "+ principalPointY);// Get distortion coefficientsfloat[] distortionCoefficients =characteristics.get(SCameraCharacteristics.LENS_DISTORTION);if (distortionCoefficients !=null) {Log.d("SamsungCamera","Distortion Coefficients: "+Arrays.toString(distortionCoefficients)); } else {Log.d("SamsungCamera","No distortion coefficients available."); } } catch (CameraAccessException e) {e.printStackTrace(); } }}
Extrinsics Parameters:
Camera extrinsics are also structured as an array of floating-point values:
[m₁₁ … m₃₄] is a 3x4 inverse RT matrix describing the camera's nominal position and rotation within respect to the car.
[pitch, yaw, roll] = radian values describing the calibrated rotation offsets from the nominals above.
For the calibration process of the extrinsics parameters for the TarantulaX and the smartphone, we will employ a hand-eye calibration method. To ensure that the initial extrinsics parameters are as close to the true parameters as possible, we will impose certain restrictions on the User Manual, such as installing the device in front of the car sunroof, etc. For detailed instructions, please refer to our User Manual.
Once the installation is complete, users can drive freely on the road. When the calibration is completed, we will prompt you through the mobile app (of course, if you want to complete the calibration quickly, you can choose an open space to drive in a figure-eight pattern).
After the mobile app prompts that The calibration is complete, please start your ROVR journey.