Skip to content

Commit

Permalink
[meshcat] Add python bindings for Meshcat::SetCamera (RobotLocomotion…
Browse files Browse the repository at this point in the history
  • Loading branch information
RussTedrake authored Apr 21, 2022
1 parent 2d2ae82 commit b937fc0
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 5 deletions.
73 changes: 70 additions & 3 deletions bindings/pydrake/geometry_py_visualizers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,9 @@ void DoScalarIndependentDefinitions(py::module m) {
{
using Class = Meshcat;
constexpr auto& cls_doc = doc.Meshcat;
py::class_<Class, std::shared_ptr<Class>> cls(m, "Meshcat", cls_doc.doc);
cls // BR
py::class_<Class, std::shared_ptr<Class>> meshcat(
m, "Meshcat", cls_doc.doc);
meshcat // BR
.def(py::init<std::optional<int>>(), py::arg("port") = std::nullopt,
cls_doc.ctor.doc_1args_port)
.def(py::init<const MeshcatParams&>(), py::arg("params"),
Expand Down Expand Up @@ -256,7 +257,16 @@ void DoScalarIndependentDefinitions(py::module m) {
py::arg("rgba") = Rgba(0.1, 0.1, 0.1, 1.0),
py::arg("wireframe") = false, py::arg("wireframe_line_width") = 1.0,
cls_doc.SetTriangleMesh.doc)
// TODO(russt): Bind SetCamera.
.def("SetCamera",
py::overload_cast<Meshcat::PerspectiveCamera, std::string>(
&Class::SetCamera),
py::arg("camera"), py::arg("path") = "/Cameras/default/rotated",
cls_doc.SetCamera.doc_perspective)
.def("SetCamera",
py::overload_cast<Meshcat::OrthographicCamera, std::string>(
&Class::SetCamera),
py::arg("camera"), py::arg("path") = "/Cameras/default/rotated",
cls_doc.SetCamera.doc_orthographic)
.def("Set2dRenderMode", &Class::Set2dRenderMode,
py::arg("X_WC") = RigidTransformd{Eigen::Vector3d{0, -1, 0}},
py::arg("xmin") = -1.0, py::arg("xmax") = 1.0,
Expand Down Expand Up @@ -312,6 +322,63 @@ void DoScalarIndependentDefinitions(py::module m) {
.def("HasPath", &Class::HasPath, py::arg("path"), cls_doc.HasPath.doc);
// Note: we intentionally do not bind the advanced methods (GetPacked...)
// which were intended primarily for testing in C++.

const auto& perspective_camera_doc = doc.Meshcat.PerspectiveCamera;
py::class_<Meshcat::PerspectiveCamera>(
meshcat, "PerspectiveCamera", perspective_camera_doc.doc)
.def(ParamInit<Meshcat::PerspectiveCamera>())
.def_readwrite("fov", &Meshcat::PerspectiveCamera::fov,
perspective_camera_doc.fov.doc)
.def_readwrite("aspect", &Meshcat::PerspectiveCamera::aspect,
perspective_camera_doc.aspect.doc)
.def_readwrite("near", &Meshcat::PerspectiveCamera::near,
perspective_camera_doc.near.doc)
.def_readwrite("far", &Meshcat::PerspectiveCamera::far,
perspective_camera_doc.far.doc)
.def_readwrite("zoom", &Meshcat::PerspectiveCamera::zoom,
perspective_camera_doc.zoom.doc)
.def("__repr__", [](const Meshcat::PerspectiveCamera& self) {
return py::str(
"PerspectiveCamera("
"fov={}, "
"aspect={}, "
"near={}, "
"far={}, "
"zoom={})")
.format(self.fov, self.aspect, self.near, self.far, self.zoom);
});

const auto& orthographic_camera_doc = doc.Meshcat.OrthographicCamera;
py::class_<Meshcat::OrthographicCamera>(
meshcat, "OrthographicCamera", orthographic_camera_doc.doc)
.def(ParamInit<Meshcat::OrthographicCamera>())
.def_readwrite("left", &Meshcat::OrthographicCamera::left,
orthographic_camera_doc.left.doc)
.def_readwrite("right", &Meshcat::OrthographicCamera::right,
orthographic_camera_doc.right.doc)
.def_readwrite("top", &Meshcat::OrthographicCamera::top,
orthographic_camera_doc.top.doc)
.def_readwrite("bottom", &Meshcat::OrthographicCamera::bottom,
orthographic_camera_doc.bottom.doc)
.def_readwrite("near", &Meshcat::OrthographicCamera::near,
orthographic_camera_doc.near.doc)
.def_readwrite("far", &Meshcat::OrthographicCamera::far,
orthographic_camera_doc.far.doc)
.def_readwrite("zoom", &Meshcat::OrthographicCamera::zoom,
orthographic_camera_doc.zoom.doc)
.def("__repr__", [](const Meshcat::OrthographicCamera& self) {
return py::str(
"OrthographicCamera("
"left={}, "
"right={}, "
"top={}, "
"bottom={}, "
"near={}, "
"far={}, "
"zoom={})")
.format(self.left, self.right, self.top, self.bottom, self.near,
self.far, self.zoom);
});
}

// MeshcatAnimation
Expand Down
46 changes: 46 additions & 0 deletions bindings/pydrake/test/geometry_visualizers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,52 @@ def test_meshcat(self):
meshcat.StaticHtml())
meshcat.Flush()

# PerspectiveCamera
camera = mut.Meshcat.PerspectiveCamera(fov=80,
aspect=1.2,
near=0.2,
far=200,
zoom=1.3)
self.assertEqual(camera.fov, 80)
self.assertEqual(camera.aspect, 1.2)
self.assertEqual(camera.near, 0.2)
self.assertEqual(camera.far, 200)
self.assertEqual(camera.zoom, 1.3)
self.assertEqual(repr(camera), "".join([
r"PerspectiveCamera(",
r"fov=80.0, "
r"aspect=1.2, ",
r"near=0.2, ",
r"far=200.0, ",
r"zoom=1.3)"]))
meshcat.SetCamera(camera=camera, path="mypath")

# OrthographicCamera
camera = mut.Meshcat.OrthographicCamera(left=0.1,
right=1.3,
top=0.3,
bottom=1.4,
near=0.2,
far=200,
zoom=1.3)
self.assertEqual(camera.left, 0.1)
self.assertEqual(camera.right, 1.3)
self.assertEqual(camera.top, 0.3)
self.assertEqual(camera.bottom, 1.4)
self.assertEqual(camera.near, 0.2)
self.assertEqual(camera.far, 200)
self.assertEqual(camera.zoom, 1.3)
self.assertEqual(repr(camera), "".join([
r"OrthographicCamera(",
r"left=0.1, "
r"right=1.3, ",
r"top=0.3, "
r"bottom=1.4, ",
r"near=0.2, ",
r"far=200.0, ",
r"zoom=1.3)"]))
meshcat.SetCamera(camera=camera, path="mypath")

def test_meshcat_animation(self):
animation = mut.MeshcatAnimation(frames_per_second=64)
self.assertEqual(animation.frames_per_second(), 64)
Expand Down
10 changes: 8 additions & 2 deletions geometry/meshcat.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ class Meshcat {

/** Sets the Meshcat object on `path` to a perspective camera. We provide a
default value of `path` corresponding to the default camera object in
Meshcat. */
Meshcat.
@pydrake_mkdoc_identifier{perspective}
*/
void SetCamera(PerspectiveCamera camera,
std::string path = "/Cameras/default/rotated");

Expand All @@ -290,7 +293,10 @@ class Meshcat {

/** Sets the Meshcat object on `path` to an orthographic camera. We provide a
default value of `path` corresponding to the default camera object in
Meshcat. */
Meshcat.
@pydrake_mkdoc_identifier{orthographic}
*/
void SetCamera(OrthographicCamera camera,
std::string path = "/Cameras/default/rotated");

Expand Down

0 comments on commit b937fc0

Please sign in to comment.