Example #1
0
    def DoPublish(self, context, event):
        # TODO(SeanCurtis-TRI) We want to be able to use this visualizer to
        # draw without having it part of a Simulator. That means we'd like
        # vis.Publish(context) to work. Currently, pydrake offers no mechanism
        # to declare a forced event. However, by overriding DoPublish and
        # putting the forced event callback code in the override, we can
        # simulate it.
        # We need to bind a mechanism for declaring forced events so we don't
        # have to resort to overriding the dispatcher.

        LeafSystem.DoPublish(self, context, event)
        point_cloud_P = self.EvalAbstractInput(context, 0).get_value()

        # `Q` is a point in the point cloud.
        p_PQs = point_cloud_P.xyzs()
        # Use only valid points.
        valid = np.logical_not(np.isnan(p_PQs))
        valid = np.all(valid, axis=0)  # Reduce along XYZ axis.
        p_PQs = p_PQs[:, valid]
        if point_cloud_P.has_rgbs():
            rgbs = point_cloud_P.rgbs()[:, valid]
        else:
            # Need manual broadcasting.
            count = p_PQs.shape[1]
            rgbs = np.tile(np.array([self._default_rgb]).T, (1, count))
        # pydrake `PointCloud.rgbs()` are on [0..255], while meshcat
        # `PointCloud` colors are on [0..1].
        rgbs = rgbs / 255.  # Do not use in-place so we can promote types.
        # Send to meshcat.
        self._meshcat_viz[self._name].set_object(g.PointCloud(p_PQs, rgbs))
        self._meshcat_viz[self._name].set_transform(self._X_WP.GetAsMatrix4())
Example #2
0
    def DoPublish(self, context, event):
        # TODO(SeanCurtis-TRI) We want to be able to use this visualizer to
        # draw without having it part of a Simulator. That means we'd like
        # vis.Publish(context) to work. Currently, pydrake offers no mechanism
        # to declare a forced event. However, by overriding DoPublish and
        # putting the forced event callback code in the override, we can
        # simulate it.
        # We need to bind a mechanism for declaring forced events so we don't
        # have to resort to overriding the dispatcher.

        LeafSystem.DoPublish(self, context, event)

        vis = self.vis[self.prefix]

        query_object = self.get_geometry_query_input_port().Eval(context)

        for frame in self._dynamic_frames:
            frame_vis = vis[frame['name']]
            X_WF = query_object.GetPoseInWorld(frame['id'])
            frame_vis.set_transform(X_WF.GetAsMatrix4())
            if self._is_recording:
                with self._animation.at_frame(frame_vis,
                                              self._recording_frame_num) as f:
                    f.set_transform(X_WF.GetAsMatrix4())

        if self._is_recording:
            self._recording_frame_num += 1
Example #3
0
    def DoPublish(self, context, event):
        # TODO(russt): Change this to declare a periodic event with a
        # callback instead of overriding DoPublish, pending #9992.
        LeafSystem.DoPublish(self, context, event)

        pose_bundle = self.EvalAbstractInput(context, 0).get_value()

        for frame_i in range(pose_bundle.get_num_poses()):
            # SceneGraph currently sets the name in PoseBundle as
            #    "get_source_name::frame_name".
            [source_name,
             frame_name] = self._parse_name(pose_bundle.get_name(frame_i))
            model_id = pose_bundle.get_model_instance_id(frame_i)
            # The MBP parsers only register the plant as a nameless source.
            # TODO(russt): Use a more textual naming convention here?
            pose_matrix = pose_bundle.get_transform(frame_i)
            cur_vis = (
                self.vis[self.prefix][source_name][str(model_id)][frame_name])
            cur_vis.set_transform(pose_matrix.GetAsMatrix4())
            if self._is_recording:
                with self._animation.at_frame(
                        cur_vis, self._recording_frame_num) as cur_vis_frame:
                    cur_vis_frame.set_transform(pose_matrix.GetAsMatrix4())

        if self._is_recording:
            self._recording_frame_num += 1
 def DoPublish(self, context, events):
     # Call base method to ensure we do not get recursion.
     LeafSystem.DoPublish(self, context, events)
     # N.B. We do not test for a singular call to `DoPublish`
     # (checking `assertFalse(self.called_publish)` first) because
     # the above `_DeclareInitializationEvent` will call both its
     # callback and this event when invoked via
     # `Simulator::Initialize` from `call_leaf_system_overrides`,
     # even when we explicitly say not to publish at initialize.
     self.called_publish = True
 def DoPublish(self, context, event):
     LeafSystem.DoPublish(self, context, event)
     if self._show:
         self.draw(context)
         self.fig.canvas.draw()
         plt.pause(1e-10)
     if self._is_recording:
         snapshot = self.AllocateContext()
         snapshot.SetTimeStateAndParametersFrom(context)
         self.FixInputPortsFrom(self, context, snapshot)
         self._recorded_contexts.append(snapshot)
Example #6
0
    def DoPublish(self, context, event):

        LeafSystem.DoPublish(self, context, event)

        if (not self._warned_pose_bundle_input_port_connected
                and self._lcm_visualization_input_port.HasValue(context)):
            _warn_deprecated(
                "The pose_bundle input port is deprecated.  Use e.g.\n"
                "builder.Connect("
                "scene_graph.get_query_output_port(), "
                "visualizer.get_geometry_query_input_port())\n"
                "instead.",
                date="2021-04-01")
            self._warned_pose_bundle_input_port_connected = True

        vis = self.vis[self.prefix]
        if self.get_geometry_query_input_port().HasValue(context):
            # New workflow, using SceneGraph's QueryObject.
            query_object = self.get_geometry_query_input_port().Eval(context)

            for frame in self._dynamic_frames:
                frame_vis = vis[frame['name']]
                X_WF = query_object.GetPoseInWorld(frame['id'])
                frame_vis.set_transform(X_WF.GetAsMatrix4())
                if self._is_recording:
                    with self._animation.at_frame(
                            frame_vis, self._recording_frame_num) as f:
                        f.set_transform(X_WF.GetAsMatrix4())
        else:
            # Deprecated workflow.
            pose_bundle = self._lcm_visualization_input_port.Eval(context)

            for frame_i in range(pose_bundle.get_num_poses()):
                # Note: MBP declares frames with SceneGraph using `::`, we
                # replace those with `/` here to expose the full tree to
                # meshcat.
                name = pose_bundle.get_name(frame_i).replace("::", "/")
                frame_vis = vis[name]
                pose_matrix = pose_bundle.get_transform(frame_i)
                frame_vis.set_transform(pose_matrix.GetAsMatrix4())
                if self._is_recording:
                    with self._animation.at_frame(
                            frame_vis, self._recording_frame_num) as f:
                        f.set_transform(pose_matrix.GetAsMatrix4())

        if self._is_recording:
            self._recording_frame_num += 1
Example #7
0
 def DoPublish(self, context, event):
     # TODO(SeanCurtis-TRI) We want to be able to use this visualizer to
     # draw without having it part of a Simulator. That means we'd like
     # vis.Publish(context) to work. Currently, pydrake offers no mechanism
     # to declare a forced event. However, by overriding DoPublish and
     # putting the forced event callback code in the override, we can
     # simulate it.
     # We need to bind a mechanism for declaring forced events so we don't
     # have to resort to overriding the dispatcher.
     LeafSystem.DoPublish(self, context, event)
     if self._show:
         self.draw(context)
         self.fig.canvas.draw()
         self._plt.pause(1e-10)
     if self._is_recording:
         snapshot = self.AllocateContext()
         snapshot.SetTimeStateAndParametersFrom(context)
         self.FixInputPortsFrom(self, context, snapshot)
         self._recorded_contexts.append(snapshot)
    def DoPublish(self, context, event):

        LeafSystem.DoPublish(self, context, event)

        vis = self.vis[self.prefix]

        query_object = self.get_geometry_query_input_port().Eval(context)

        for frame in self._dynamic_frames:
            frame_vis = vis[frame['name']]
            X_WF = query_object.GetPoseInWorld(frame['id'])
            frame_vis.set_transform(X_WF.GetAsMatrix4())
            if self._is_recording:
                with self._animation.at_frame(
                        frame_vis, self._recording_frame_num) as f:
                    f.set_transform(X_WF.GetAsMatrix4())

        if self._is_recording:
            self._recording_frame_num += 1
    def DoPublish(self, context, event):
        # TODO(russt): Copied from meshcat_visualizer.py.
        # Change this to declare a periodic event with a
        # callback instead of overriding DoPublish, pending #9992.
        LeafSystem.DoPublish(self, context, event)

        self.callback_lock.acquire()

        if self.stop:
            self.stop = False
            if context.get_time() > 0.5:
                self.callback_lock.release()
                raise StopIteration

        #query_object = self.EvalAbstractInput(context, 0).get_value()
        pose_bundle = self.EvalAbstractInput(context, 0).get_value()
        x_in = self.EvalVectorInput(context, 1).get_value()
        self.mbp.SetPositionsAndVelocities(self.mbp_context, x_in)

        if self.grab_needs_update:
            hydra_tf = self.grab_update_hydra_pose
            self.grab_needs_update = False
            # If grab point is colliding...
            #print [x.distance for x in query_object.ComputeSignedDistanceToPoint(hydra_tf.matrix()[:3, 3])]
            # Find closest body to current pose

            grab_center = hydra_tf.matrix()[:3, 3]
            closest_distance = np.inf
            closest_body = self.mbp.get_body(BodyIndex(2))
            for body_id in self.all_manipulable_body_ids:
                body = self.mbp.get_body(body_id)
                offset = self.mbp.EvalBodyPoseInWorld(self.mbp_context, body)
                dist = np.linalg.norm(grab_center - offset.translation())
                if dist < closest_distance:
                    closest_distance = dist
                    closest_body = body

            self.selected_body = closest_body
            self.selected_body_init_offset = self.mbp.EvalBodyPoseInWorld(
                self.mbp_context, self.selected_body)
        self.callback_lock.release()
    def DoPublish(self, context, event):
        # TODO(russt): Change this to declare a periodic event with a
        # callback instead of overriding DoPublish, pending #9992.
        LeafSystem.DoPublish(self, context, event)

        mbp_state_vector = self.EvalVectorInput(context, 0).get_value()
        self.mbp.SetPositionsAndVelocities(self.mbp_context, mbp_state_vector)

        # Get pose of object
        for body_name in self.body_names:
            print(body_name, ": ")
            print(
                self.mbp.EvalBodyPoseInWorld(
                    self.mbp_context,
                    self.mbp.GetBodyByName(body_name)).matrix())

        rigid_transform_dict = {}
        for body_name in self.body_names:
            rigid_transform_dict[body_name] = self.mbp.EvalBodyPoseInWorld(
                self.mbp_context, self.mbp.GetBodyByName(body_name))
        self._symbol_logger.log_symbols(rigid_transform_dict)
        self._symbol_logger.print_curr_symbols()
Example #11
0
    def DoPublish(self, context, event):
        LeafSystem.DoPublish(self, context, event)
        point_cloud_P = self.EvalAbstractInput(context, 0).get_value()

        # `Q` is a point in the point cloud.
        p_PQs = point_cloud_P.xyzs()
        # Use only valid points.
        valid = np.logical_not(np.isnan(p_PQs))
        valid = np.all(valid, axis=0)  # Reduce along XYZ axis.
        p_PQs = p_PQs[:, valid]
        if point_cloud_P.has_rgbs():
            rgbs = point_cloud_P.rgbs()[:, valid]
        else:
            # Need manual broadcasting.
            count = p_PQs.shape[1]
            rgbs = np.tile(np.array([self._default_rgb]).T, (1, count))
        # pydrake `PointCloud.rgbs()` are on [0..255], while meshcat
        # `PointCloud` colors are on [0..1].
        rgbs = rgbs / 255.  # Do not use in-place so we can promote types.
        # Send to meshcat.
        self._meshcat_viz[self._name].set_object(g.PointCloud(p_PQs, rgbs))
        self._meshcat_viz[self._name].set_transform(self._X_WP.matrix())
Example #12
0
 def DoPublish(self, context, event):
     LeafSystem.DoPublish(self, context, event)
     pose_bundle = self.EvalAbstractInput(context, 0).get_value()
     X_WB_map = self._get_pose_map(pose_bundle)
     self._draw_contact_forces(context, X_WB_map)
Example #13
0
    def DoPublish(self, context, event):
        # TODO(SeanCurtis-TRI) We want to be able to use this visualizer to
        # draw without having it part of a Simulator. That means we'd like
        # vis.Publish(context) to work. Currently, pydrake offers no mechanism
        # to declare a forced event. However, by overriding DoPublish and
        # putting the forced event callback code in the override, we can
        # simulate it.
        # We need to bind a mechanism for declaring forced events so we don't
        # have to resort to overriding the dispatcher.

        LeafSystem.DoPublish(self, context, event)

        contact_results = self.EvalAbstractInput(context, 0).get_value()

        vis = self._meshcat_viz.vis[self._meshcat_viz.prefix]["contact_forces"]
        contacts = []

        for i_contact in range(contact_results.num_point_pair_contacts()):
            contact_info = contact_results.point_pair_contact_info(i_contact)

            # Do not display small forces.
            force_norm = np.linalg.norm(contact_info.contact_force())
            if force_norm < self._force_threshold:
                continue

            point_pair = contact_info.point_pair()
            key = (point_pair.id_A.get_value(), point_pair.id_B.get_value())
            cvis = vis[str(key)]
            contacts.append(key)
            arrow_height = self._radius * 2.0
            if key not in self._published_contacts:
                # New key, so create the geometry. Note: the height of the
                # cylinder is 2 and gets scaled to twice the contact force
                # length, because I am drawing both (equal and opposite)
                # forces.  Note also that meshcat (following three.js) puts
                # the height of the cylinder along the y axis.
                cvis["cylinder"].set_object(
                    meshcat.geometry.Cylinder(height=2.0, radius=self._radius),
                    meshcat.geometry.MeshLambertMaterial(color=0x33cc33))
                cvis["head"].set_object(
                    meshcat.geometry.Cylinder(height=arrow_height,
                                              radiusTop=0,
                                              radiusBottom=self._radius * 2.0),
                    meshcat.geometry.MeshLambertMaterial(color=0x00dd00))
                cvis["tail"].set_object(
                    meshcat.geometry.Cylinder(height=arrow_height,
                                              radiusTop=self._radius * 2.0,
                                              radiusBottom=0),
                    meshcat.geometry.MeshLambertMaterial(color=0x00dd00))

            height = force_norm / self._contact_force_scale
            cvis["cylinder"].set_transform(
                tf.scale_matrix(height, direction=[0, 1, 0]))
            cvis["head"].set_transform(
                tf.translation_matrix([0, height + arrow_height / 2.0, 0.0]))
            cvis["tail"].set_transform(
                tf.translation_matrix([0, -height - arrow_height / 2.0, 0.0]))

            # The contact frame's origin is located at contact_point and is
            # oriented such that Cy is aligned with the contact force.
            p_WC = contact_info.contact_point()  # documented as in world.
            if force_norm < 1e-6:
                # We cannot rely on self._force_threshold to determine if the
                # force can be normalized; that threshold can be zero.
                R_WC = RotationMatrix()
            else:
                fhat_C_W = contact_info.contact_force() / force_norm
                R_WC = RotationMatrix.MakeFromOneVector(b_A=fhat_C_W,
                                                        axis_index=1)
            X_WC = RigidTransform(R=R_WC, p=p_WC)
            cvis.set_transform(X_WC.GetAsMatrix4())

        # We only delete any contact vectors that did not persist into this
        # publish.  It is tempting to just delete() the root branch at the
        # beginning of this publish, but this leads to visual artifacts
        # (flickering) in the browser.
        for key in set(self._published_contacts) - set(contacts):
            vis[str(key)].delete()

        self._published_contacts = contacts
    def DoPublish(self, context, event):
        # TODO(russt): Change this to declare a periodic event with a
        # callback instead of overriding _DoPublish, pending #9992.
        LeafSystem.DoPublish(self, context, event)

        print("In publish at time ", context.get_time())
        if context.get_time() <= 1E-3:
            return

        pose_bundle = self.EvalAbstractInput(context, 0).get_value()
        bbox_bundle = self.EvalAbstractInput(context, 1)
        if bbox_bundle:
            bbox_bundle = bbox_bundle.get_value()
            for k in range(bbox_bundle.get_num_bboxes()):
                pose = self.global_transform.multiply(
                    bbox_bundle.get_bbox_pose(k))
                if (k + 1) > self.num_registered_bounding_boxes:
                    # Register a new one
                    color = bbox_bundle.get_bbox_color(k)
                    self.bsi.send_remote_call(
                        "register_material",
                        name="mat_bb_%d" % k,
                        material_type="color",
                        color=bbox_bundle.get_bbox_color(k))
                    self.bsi.send_remote_call("update_material_parameters",
                                              type="Principled BSDF",
                                              name="mat_bb_%d" % k,
                                              **{"Specular": 0.0})
                    self.bsi.send_remote_call("update_material_parameters",
                                              type=None,
                                              name="mat_bb_%d" % k,
                                              **{"blend_method": "ADD"})
                    self.bsi.send_remote_call(
                        "register_object",
                        name="obj_bb_%d" % k,
                        type="cube",
                        scale=[x / 2 for x in bbox_bundle.get_bbox_scale(k)],
                        location=pose.translation().tolist(),
                        quaternion=pose.quaternion().wxyz().tolist(),
                        material="mat_bb_%d" % k)
                    self.bsi.send_remote_call("apply_modifier_to_object",
                                              name="obj_bb_%d" % k,
                                              type="WIREFRAME",
                                              thickness=0.1)
                    self.num_registered_bounding_boxes = k + 1
                    self.num_visible_bounding_boxes = k + 1
                else:
                    # Update parameters of existing bbox + its material
                    self.bsi.send_remote_call(
                        "update_material_parameters",
                        type="Principled BSDF",
                        name="mat_bb_%d" % k,
                        **{"Base Color": bbox_bundle.get_bbox_color(k)})
                    self.bsi.send_remote_call(
                        "update_object_parameters",
                        name="obj_bb_%d" % k,
                        scale=[x / 2 for x in bbox_bundle.get_bbox_scale(k)],
                        location=pose.translation().tolist(),
                        rotation_mode='QUATERNION',
                        rotation_quaternion=pose.rotation().ToQuaternion(
                        ).wxyz().tolist(),
                        hide_render=False)
                    self.num_visible_bounding_boxes = k + 1
            for k in range(bbox_bundle.get_num_bboxes(),
                           self.num_visible_bounding_boxes):
                self.bsi.send_remote_call("update_object_parameters",
                                          name="obj_bb_%d" % k,
                                          hide_render=True)

        # print('pose_bundle type', type(pose_bundle))
        for frame_i in range(pose_bundle.get_num_poses()):
            link_name = pose_bundle.get_name(frame_i)
            # print('link_name', link_name)
            [source_name, frame_name] = self._parse_name(link_name)
            model_id = pose_bundle.get_model_instance_id(frame_i)
            # pose_matrix = pose_bundle.get_pose(frame_i)
            pose_matrix = pose_bundle.get_transform(frame_i)
            for j in range(self.num_link_geometries_by_link_name[link_name]):
                # I am sure this can be written shorter than this, this bloat is from
                # when this was isometry-based.
                offset = RigidTransform(
                    self.global_transform.GetAsMatrix4().dot(
                        # pose_matrix.matrix().dot(
                        pose_matrix.GetAsMatrix4().dot(
                            self.link_subgeometry_local_tfs_by_link_name[
                                link_name][j])))
                location = offset.translation()
                quaternion = offset.rotation().ToQuaternion().wxyz()
                geom_name = self._format_geom_name(source_name, frame_name, j)
                self.bsi.send_remote_call(
                    "update_object_parameters",
                    name="obj_" + geom_name,
                    location=location.tolist(),
                    rotation_mode='QUATERNION',
                    rotation_quaternion=quaternion.tolist())

        n_cams = len(self.camera_tfs)
        for i in range(len(self.camera_tfs)):
            out_filepath = self.out_prefix + "%02d_%08d.jpg" % (
                i, self.current_publish_num)
            self.last_out_filepath = out_filepath
            self.bsi.send_remote_call("render",
                                      camera_name="cam_%d" % i,
                                      filepath=out_filepath)

        if self.save_scene:
            scene_filepath = self.out_prefix + "_scene.blend"
            self.bsi.send_remote_call("save_current_scene",
                                      path=scene_filepath)
        self.current_publish_num += 1

        if self.show_figure:
            plt.pause(0.01)
        print("Rendered a frame at %f seconds sim-time." %
              (context.get_time()))
Example #15
0
    def DoPublish(self, context, event):
        LeafSystem.DoPublish(self, context, event)

        if (not self._warned_pose_bundle_input_port_connected
                and self.get_input_port(0).HasValue(context)):
            _warn_deprecated(
                "The pose_bundle input port of MeshcatContactVisualizer is"
                "deprecated; use the geometry_query inport port instead.",
                date="2021-04-01")
            self._warned_pose_bundle_input_port_connected = True

        contact_results = self.EvalAbstractInput(context, 1).get_value()

        vis = self._meshcat_viz.vis[self._meshcat_viz.prefix]["contact_forces"]
        contacts = []

        for i_contact in range(contact_results.num_point_pair_contacts()):
            contact_info = contact_results.point_pair_contact_info(i_contact)

            # Do not display small forces.
            force_norm = np.linalg.norm(contact_info.contact_force())
            if force_norm < self._force_threshold:
                continue

            point_pair = contact_info.point_pair()
            key = (point_pair.id_A.get_value(), point_pair.id_B.get_value())
            cvis = vis[str(key)]
            contacts.append(key)
            arrow_height = self._radius * 2.0
            if key not in self._published_contacts:
                # New key, so create the geometry. Note: the height of the
                # cylinder is 2 and gets scaled to twice the contact force
                # length, because I am drawing both (equal and opposite)
                # forces.  Note also that meshcat (following three.js) puts
                # the height of the cylinder along the y axis.
                cvis["cylinder"].set_object(
                    meshcat.geometry.Cylinder(height=2.0, radius=self._radius),
                    meshcat.geometry.MeshLambertMaterial(color=0x33cc33))
                cvis["head"].set_object(
                    meshcat.geometry.Cylinder(height=arrow_height,
                                              radiusTop=0,
                                              radiusBottom=self._radius * 2.0),
                    meshcat.geometry.MeshLambertMaterial(color=0x00dd00))
                cvis["tail"].set_object(
                    meshcat.geometry.Cylinder(height=arrow_height,
                                              radiusTop=self._radius * 2.0,
                                              radiusBottom=0),
                    meshcat.geometry.MeshLambertMaterial(color=0x00dd00))

            height = force_norm / self._contact_force_scale
            cvis["cylinder"].set_transform(
                tf.scale_matrix(height, direction=[0, 1, 0]))
            cvis["head"].set_transform(
                tf.translation_matrix([0, height + arrow_height / 2.0, 0.0]))
            cvis["tail"].set_transform(
                tf.translation_matrix([0, -height - arrow_height / 2.0, 0.0]))

            # Frame C is located at the contact point, but with the world frame
            # orientation.
            if force_norm < 1e-6:
                X_CGeom = tf.identity_matrix()
            else:
                # Rotates [0,1,0] to contact_force/force_norm.
                angle_axis = np.cross(
                    np.array([0, 1, 0]),
                    contact_info.contact_force() / force_norm)
                X_CGeom = tf.rotation_matrix(
                    np.arcsin(np.linalg.norm(angle_axis)), angle_axis)
            X_WC = tf.translation_matrix(contact_info.contact_point())
            cvis.set_transform(X_WC @ X_CGeom)

        # We only delete any contact vectors that did not persist into this
        # publish.  It is tempting to just delete() the root branch at the
        # beginning of this publish, but this leads to visual artifacts
        # (flickering) in the browser.
        for key in set(self._published_contacts) - set(contacts):
            vis[str(key)].delete()

        self._published_contacts = contacts
 def DoPublish(self, context, events):
     # N.B. Prevent recursion.
     LeafSystem.DoPublish(self, context, events)
     for func_declaration in self._func_declaration:
         func_declaration.maybe_publish(context)
Example #17
0
 def DoPublish(self, context, event):
     LeafSystem.DoPublish(self, context, event)
     if self._show:
         self.draw(context)
         self.fig.canvas.draw()
         plt.pause(1e-10)