Refactor camera intrinsic parameter handling.

Move logic from parser to compiler.

PiperOrigin-RevId: 847689906
Change-Id: I844746081973205e1b33a3845add842e8b8c3c07
This commit is contained in:
Yuval Tassa
2025-12-22 03:06:36 -08:00
committed by Copybara-Service
parent b77977a962
commit 158525269b
4 changed files with 54 additions and 63 deletions
+20 -12
View File
@@ -4116,15 +4116,23 @@ void mjCCamera::Compile(void) {
name.c_str(), id, fovy);
}
// check that specs are not duplicated
if ((principal_length[0] && principal_pixel[0]) ||
(principal_length[1] && principal_pixel[1])) {
throw mjCError(this, "principal length duplicated in camera");
// check for advanced camera intrinsic parameters
bool has_intrinsic = focal_length[0] || focal_length[1] ||
focal_pixel[0] || focal_pixel[1] ||
principal_length[0] || principal_length[1] ||
principal_pixel[0] || principal_pixel[1];
bool has_sensorsize = sensor_size[0] > 0 && sensor_size[1] > 0;
// intrinsic params require sensorsize
if (has_intrinsic && !has_sensorsize) {
throw mjCError(this, "focal/principal require sensorsize in camera '%s' (id = %d)",
name.c_str(), id);
}
if ((focal_length[0] && focal_pixel[0]) ||
(focal_length[1] && focal_pixel[1])) {
throw mjCError(this, "focal length duplicated in camera");
// sensorsize requires resolution
if (has_sensorsize && (resolution[0] <= 0 || resolution[1] <= 0)) {
throw mjCError(this, "sensorsize requires positive resolution in camera '%s' (id = %d)",
name.c_str(), id);
}
// compute number of pixels per unit length
@@ -4134,11 +4142,11 @@ void mjCCamera::Compile(void) {
(float)resolution[1] / sensor_size[1],
};
// defaults are zero, so only one term in each sum is nonzero
intrinsic[0] = focal_pixel[0] / pixel_density[0] + focal_length[0];
intrinsic[1] = focal_pixel[1] / pixel_density[1] + focal_length[1];
intrinsic[2] = principal_pixel[0] / pixel_density[0] + principal_length[0];
intrinsic[3] = principal_pixel[1] / pixel_density[1] + principal_length[1];
// pixel values override length values when both are specified
intrinsic[0] = focal_pixel[0] ? focal_pixel[0] / pixel_density[0] : focal_length[0];
intrinsic[1] = focal_pixel[1] ? focal_pixel[1] / pixel_density[1] : focal_length[1];
intrinsic[2] = principal_pixel[0] ? principal_pixel[0] / pixel_density[0] : principal_length[0];
intrinsic[3] = principal_pixel[1] ? principal_pixel[1] / pixel_density[1] : principal_length[1];
// fovy with principal point at (0, 0)
fovy = std::atan2(sensor_size[1]/2, intrinsic[1]) * 360.0 / mjPI;
+9 -18
View File
@@ -1937,24 +1937,15 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) {
camera->proj = (mjtProjection)n;
}
bool has_principal = ReadAttr(elem, "principalpixel", 2, camera->principal_pixel, text) ||
ReadAttr(elem, "principal", 2, camera->principal_length, text);
bool has_focal = ReadAttr(elem, "focalpixel", 2, camera->focal_pixel, text) ||
ReadAttr(elem, "focal", 2, camera->focal_length, text);
bool needs_sensorsize = has_principal || has_focal;
bool has_sensorsize = ReadAttr(elem, "sensorsize", 2, camera->sensor_size, text, needs_sensorsize);
bool has_fovy = ReadAttr(elem, "fovy", 1, &camera->fovy, text);
bool needs_resolution = has_focal || has_sensorsize;
ReadAttr(elem, "resolution", 2, camera->resolution, text, needs_resolution);
if (camera->resolution[0] < 0 || camera->resolution[1] < 0) {
throw mjXError(elem, "camera resolution cannot be negative");
}
if (has_fovy && has_sensorsize) {
throw mjXError(
elem,
"either 'fovy' or 'sensorsize' attribute can be specified, not both");
ReadAttr(elem, "principalpixel", 2, camera->principal_pixel, text);
ReadAttr(elem, "principal", 2, camera->principal_length, text);
ReadAttr(elem, "focalpixel", 2, camera->focal_pixel, text);
ReadAttr(elem, "focal", 2, camera->focal_length, text);
ReadAttr(elem, "resolution", 2, camera->resolution, text);
bool sensorsize = ReadAttr(elem, "sensorsize", 2, camera->sensor_size, text);
bool fovy = ReadAttr(elem, "fovy", 1, &camera->fovy, text);
if (fovy && sensorsize) {
throw mjXError(elem, "either 'fovy' or 'sensorsize' attribute can be specified, not both");
}
// read userdata