Specify camera parameters using standard robotics conventions.
PiperOrigin-RevId: 569147555 Change-Id: I3443f95e5de56a17024f5e5c03f33888dd583edb
This commit is contained in:
committed by
Copybara-Service
parent
ca60de79c8
commit
36d2ffe4f2
+30
@@ -0,0 +1,30 @@
|
||||
<!-- Please activate Camera rendering when loading this model.
|
||||
The frustum should match exactly the fron face of the box. -->
|
||||
|
||||
<mujoco>
|
||||
<visual>
|
||||
<map znear="0.01"/>
|
||||
</visual>
|
||||
|
||||
<asset>
|
||||
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".8 .6 .4" rgb2=".2 .3 .4"/>
|
||||
<material name="grid" texture="grid" texrepeat="9 16" texuniform="false" reflectance=".2"/>
|
||||
</asset>
|
||||
|
||||
<worldbody>
|
||||
<light pos="0 0 3"/>
|
||||
<geom type="plane" size="10 10 .01"/>
|
||||
|
||||
<geom type="box" size=".375 .6 .1" pos="1.1 0 1" material="grid" euler="0 90 0"/>
|
||||
<!-- 8mm focal length lenses -->
|
||||
<camera pos="0 0 1" xyaxes="0 -1 0 0 0 1" focalpixel="1600 1600" resolution="1920 1200"
|
||||
sensorsize="9.6e-3 6e-3"/>
|
||||
|
||||
<body euler="0 0 90">
|
||||
<geom type="box" size=".375 .6 .1" pos="1.1 2 1" material="grid" euler="0 90 0"/>
|
||||
<!-- 8mm focal length lenses -->
|
||||
<camera pos="0 2 1" xyaxes="0 -1 0 0 0 1" focal="8e-3 8e-3" resolution="1920 1200"
|
||||
sensorsize="9.6e-3 6e-3" principalpixel="200 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
@@ -754,6 +754,81 @@ TEST_F(CameraSpecTest, FovyLimits) {
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
TEST_F(CameraSpecTest, DuplicatedFocalIgnorePixel) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<visual>
|
||||
<map znear="0.01"/>
|
||||
</visual>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<camera focal="8e-3 8e-3" focalpixel="100 100"
|
||||
resolution="1920 1200" sensorsize="9.6e-3 6e-3"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, NotNull()) << error.data();
|
||||
EXPECT_NEAR(m->cam_intrinsic[0], 5e-4, 1e-6); // focal length in meters (x)
|
||||
EXPECT_NEAR(m->cam_intrinsic[1], 5e-4, 1e-6); // focal length in meters (y)
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
TEST_F(CameraSpecTest, FovyFromResolution) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<visual>
|
||||
<map znear="0.01"/>
|
||||
</visual>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<!-- 8mm focal length lenses -->
|
||||
<camera focal="8e-3 8e-3" resolution="1920 1200" sensorsize="9.6e-3 6e-3"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, NotNull()) << error.data();
|
||||
EXPECT_NEAR(m->cam_fovy[0], 41.112, 1e-3);
|
||||
EXPECT_NEAR(m->cam_intrinsic[0], 8e-3, 1e-6); // focal length in meters (x)
|
||||
EXPECT_NEAR(m->cam_intrinsic[1], 8e-3, 1e-6); // focal length in meters (y)
|
||||
EXPECT_EQ(m->cam_intrinsic[2], 0); // principal point in meters (x)
|
||||
EXPECT_EQ(m->cam_intrinsic[3], 0); // principal point in meters (y)
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
TEST_F(CameraSpecTest, FovyFromResolutionPixel) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<visual>
|
||||
<map znear="0.01"/>
|
||||
</visual>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<!-- 8mm focal length lenses -->
|
||||
<camera focalpixel="1600 1600" resolution="1920 1200" sensorsize="9.6e-3 6e-3"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, NotNull()) << error.data();
|
||||
EXPECT_NEAR(m->cam_fovy[0], 41.112, 1e-3);
|
||||
EXPECT_NEAR(m->cam_intrinsic[0], 8e-3, 1e-6); // focal length in meters (x)
|
||||
EXPECT_NEAR(m->cam_intrinsic[1], 8e-3, 1e-6); // focal length in meters (y)
|
||||
EXPECT_EQ(m->cam_intrinsic[2], 0); // principal point in meters (x)
|
||||
EXPECT_EQ(m->cam_intrinsic[3], 0); // principal point in meters (y)
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
// ------------- test actuator order -------------------------------------------
|
||||
|
||||
using ActuatorTest = MujocoTest;
|
||||
|
||||
@@ -407,6 +407,61 @@ TEST_F(XMLReaderTest, InvalidDoubleOrientation) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- test camera parsing ---------------------------------
|
||||
|
||||
TEST_F(XMLReaderTest, CameraInvalidFovyAndSensorsize) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<camera fovy="1" sensorsize="1 1" resolution="100 100"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, testing::IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("either 'fovy' or 'sensorsize'"));
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, CameraPricipalRequiresSensorsize) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<camera principal="1 1"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, testing::IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("attribute missing: 'sensorsize'"));
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, CameraSensorsizeRequiresResolution) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<camera sensorsize="1 1"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(m, testing::IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("attribute missing: 'resolution'"));
|
||||
}
|
||||
|
||||
// ---------------------- test inertia parsing --------------------------------
|
||||
|
||||
TEST_F(XMLReaderTest, InvalidInertialOrientation) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
|
||||
Reference in New Issue
Block a user