Пример #1
0
 def createPolyLine(params):
     d = DebugData()
     points = [np.asarray(p) for p in params["points"]]
     color = params.get("color", DEFAULT_COLOR)[:3]
     radius = params.get("radius", 0.01)
     startHead = params.get("start_head", False)
     endHead = params.get("end_head", False)
     headRadius = params.get("head_radius", 0.05)
     headLength = params.get("head_length", headRadius)
     isClosed = params.get("closed", False)
     if startHead:
         normal = points[0] - points[1]
         normal = normal / np.linalg.norm(normal)
         points[0] = points[0] - 0.5 * headLength * normal
         d.addCone(origin=points[0],
                   normal=normal,
                   radius=headRadius,
                   height=headLength,
                   color=color,
                   fill=True)
     if endHead:
         normal = points[-1] - points[-2]
         normal = normal / np.linalg.norm(normal)
         points[-1] = points[-1] - 0.5 * headLength * normal
         d.addCone(origin=points[-1],
                   normal=normal,
                   radius=headRadius,
                   height=headLength,
                   color=color,
                   fill=True)
     d.addPolyLine(points, isClosed, radius=radius, color=color)
     return [d.getPolyData()]
Пример #2
0
 def createPolyLine(params):
     d = DebugData()
     points = [np.asarray(p) for p in params["points"]]
     color = params.get("color", DEFAULT_COLOR)[:3]
     radius = params.get("radius", 0.01)
     startHead = params.get("start_head", False)
     endHead = params.get("end_head", False)
     headRadius = params.get("head_radius", 0.05)
     headLength = params.get("head_length", headRadius)
     isClosed = params.get("closed", False)
     if startHead:
         normal = points[0] - points[1]
         normal = normal / np.linalg.norm(normal)
         points[0] = points[0] - 0.5 * headLength * normal
         d.addCone(origin=points[0], normal=normal, radius=headRadius,
                   height=headLength, color=color, fill=True)
     if endHead:
         normal = points[-1] - points[-2]
         normal = normal / np.linalg.norm(normal)
         points[-1] = points[-1] - 0.5 * headLength * normal
         d.addCone(origin=points[-1], normal=normal, radius=headRadius,
                   height=headLength, color=color, fill=True)
     d.addPolyLine(points, isClosed, radius=radius, color=color)
     return [d.getPolyData()]
    def handle_message(self, msg):
        # Limits the rate of message handling, since redrawing is done in the
        # message handler.
        self._sub.setSpeedLimit(30)

        # Removes the folder completely.
        om.removeFromObjectModel(om.findObjectByName(self._folder_name))

        # Recreates folder.
        folder = om.getOrCreateContainer(self._folder_name)

        # Though strangely named, DebugData() is the object through which
        # drawing is done in DrakeVisualizer.
        d = DebugData()

        # Set the color map.
        color_map = self.create_color_map()

        # The scale value attributable to auto-scale.
        auto_force_scale = 1.0
        auto_moment_scale = 1.0
        auto_traction_scale = 1.0
        auto_slip_velocity_scale = 1.0
        max_force = -1
        max_moment = -1
        max_traction = -1
        max_slip = -1

        # TODO(sean-curtis-TRI) Remove the following comment when this
        # code can be exercised.
        # The following code is not exercised presently because the
        # magnitude mode is always set to kFixedLength.
        # Determine scaling magnitudes if autoscaling is activated.
        if self.magnitude_mode == ContactVisModes.kAutoScale:
            if self.show_spatial_force:
                for surface in msg.hydroelastic_contacts:
                    force = np.array([
                        surface.force_C_W[0], surface.force_C_W[1],
                        surface.force_C_W[2]
                    ])
                    moment = np.array([
                        surface.moment_C_W[0], surface.moment_C_W[1],
                        surface.moment_C_W[2]
                    ])
                    force_mag = np.linalg.norm(force)
                    moment_mag = np.linalg.norm(moment)
                    if force_mag > max_force:
                        max_force = force_mag
                    if moment_mag > max_moment:
                        max_moment = moment_mag

            # Prepare scaling information for the traction vectors.
            if self.show_traction_vectors:
                for quad_point_data in surface.quadrature_point_data:
                    traction = np.array([
                        quad_point_data.traction_Aq_W[0],
                        quad_point_data.traction_Aq_W[1],
                        quad_point_data.traction_Aq_W[2]
                    ])
                    max_traction = max(max_traction, np.linalg.norm(traction))

            # Prepare scaling information for the slip velocity vectors.
            if self.show_slip_velocity_vectors:
                for quad_point_data in surface.quadrature_point_data:
                    slip_speed = np.array([
                        quad_point_data.vt_BqAq_W[0],
                        quad_point_data.vt_BqAq_W[1],
                        quad_point_data.vt_BqAq_W[2]
                    ])
                    max_slip_speed = max(max_slip_speed,
                                         np.linalg.norm(slip_speed))

            # Compute scaling factors.
            auto_force_scale = 1.0 / max_force
            auto_moment_scale = 1.0 / max_moment
            auto_traction_scale = 1.0 / max_traction
            auto_slip_velocity_scale = 1.0 / max_slip_speed

        # TODO(drum) Consider exiting early if no visualization options are
        # enabled.
        for surface in msg.hydroelastic_contacts:
            # Draw the spatial force.
            if self.show_spatial_force:
                point = np.array([
                    surface.centroid_W[0], surface.centroid_W[1],
                    surface.centroid_W[2]
                ])
                force = np.array([
                    surface.force_C_W[0], surface.force_C_W[1],
                    surface.force_C_W[2]
                ])
                moment = np.array([
                    surface.moment_C_W[0], surface.moment_C_W[1],
                    surface.moment_C_W[2]
                ])
                force_mag = np.linalg.norm(force)
                moment_mag = np.linalg.norm(moment)

                # Draw the force arrow if it's of sufficient magnitude.
                if force_mag > self.min_magnitude:
                    scale = self.global_scale
                    if self.magnitude_mode == ContactVisModes.kFixedLength:
                        # magnitude must be > 0 otherwise this force would be
                        # skipped.
                        scale /= force_mag

                    d.addArrow(start=point,
                               end=point + auto_force_scale * force * scale,
                               tubeRadius=0.005,
                               headRadius=0.01,
                               color=[1, 0, 0])

                # Draw the moment arrow if it's of sufficient magnitude.
                if moment_mag > self.min_magnitude:
                    scale = self.global_scale
                    if self.magnitude_mode == ContactVisModes.kFixedLength:
                        # magnitude must be > 0 otherwise this moment would be
                        # skipped.
                        scale /= moment_mag

                    d.addArrow(start=point,
                               end=point + auto_moment_scale * moment * scale,
                               tubeRadius=0.005,
                               headRadius=0.01,
                               color=[0, 0, 1])

            # Iterate over all quadrature points, drawing traction and slip
            # velocity vectors.
            if self.show_traction_vectors or self.show_slip_velocity_vectors:
                for quad_point_data in surface.quadrature_point_data:
                    origin = np.array([
                        quad_point_data.p_WQ[0], quad_point_data.p_WQ[1],
                        quad_point_data.p_WQ[2]
                    ])

                    if self.show_traction_vectors:
                        traction = np.array([
                            quad_point_data.traction_Aq_W[0],
                            quad_point_data.traction_Aq_W[1],
                            quad_point_data.traction_Aq_W[2]
                        ])
                        traction_mag = np.linalg.norm(traction)

                        # Draw the arrow only if it's of sufficient magnitude.
                        if traction_mag > self.min_magnitude:
                            scale = self.global_scale
                            if self.magnitude_mode ==\
                                    ContactVisModes.kFixedLength:
                                # magnitude must be > 0 otherwise this traction
                                #  would be skipped.
                                scale /= traction_mag

                            offset = auto_traction_scale * traction * scale
                            d.addArrow(start=origin,
                                       end=origin + offset,
                                       tubeRadius=0.000125,
                                       headRadius=0.00025,
                                       color=[1, 0, 1])
                        else:
                            d.addSphere(center=origin,
                                        radius=0.000125,
                                        color=[1, 0, 1])

                    if self.show_slip_velocity_vectors:
                        slip = np.array([
                            quad_point_data.vt_BqAq_W[0],
                            quad_point_data.vt_BqAq_W[1],
                            quad_point_data.vt_BqAq_W[2]
                        ])
                        slip_mag = np.linalg.norm(slip)

                        # Draw the arrow only if it's of sufficient magnitude.
                        if slip_mag > self.min_magnitude:
                            scale = self.global_scale
                            if self.magnitude_mode ==\
                                    ContactVisModes.kFixedLength:
                                # magnitude must be > 0 otherwise this slip
                                # vector would be skipped.
                                scale /= slip_mag

                            offset = auto_slip_velocity_scale * slip * scale
                            d.addArrow(start=origin,
                                       end=origin + offset,
                                       tubeRadius=0.000125,
                                       headRadius=0.00025,
                                       color=[0, 1, 1])
                        else:
                            d.addSphere(center=origin,
                                        radius=0.000125,
                                        color=[0, 1, 1])

            # Iterate over all triangles.
            for tri in surface.triangles:
                va = np.array([tri.p_WA[0], tri.p_WA[1], tri.p_WA[2]])
                vb = np.array([tri.p_WB[0], tri.p_WB[1], tri.p_WB[2]])
                vc = np.array([tri.p_WC[0], tri.p_WC[1], tri.p_WC[2]])

                # Save the maximum pressure.
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_A)
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_B)
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_C)

                # TODO(drum) Vertex color interpolation may be insufficiently
                # granular if a single triangle spans too large a range of
                # pressures. Suggested solution is to use a texture map.
                # Get the colors at the vertices.
                color_a = color_map.get_color(tri.pressure_A)
                color_b = color_map.get_color(tri.pressure_B)
                color_c = color_map.get_color(tri.pressure_C)

                if self.show_pressure:
                    # TODO(drum) Use a better method for this; the current
                    # approach is susceptible to z-fighting under certain
                    # zoom levels.

                    # Compute a normal to the triangle. We need this normal
                    # because the visualized pressure surface can be coplanar
                    # with parts of the visualized geometry, in which case a
                    # dithering type effect would appear. So we use the normal
                    # to draw two triangles slightly offset to both sides of
                    # the contact surface.

                    # Note that if the area of this triangle is very small, we
                    # won't waste time visualizing it, which also means that
                    # won't have to worry about degenerate triangles).

                    # TODO(edrumwri) Consider allowing the user to set these
                    # next two values programmatically.
                    min_area = 1e-8
                    offset_scalar = 1e-4
                    normal = np.cross(vb - va, vc - vb)
                    norm_normal = np.linalg.norm(normal)
                    if norm_normal >= min_area:
                        unit_normal = normal / np.linalg.norm(normal)
                        offset = unit_normal * offset_scalar

                        d.addPolygon([va + offset, vb + offset, vc + offset],
                                     color=[color_a, color_b, color_c])
                        d.addPolygon([va - offset, vb - offset, vc - offset],
                                     color=[color_a, color_b, color_c])

                # TODO(drum) Consider drawing shared edges just once.
                if self.show_contact_edges:
                    contrasting_color = color_map.get_contrasting_color()
                    d.addPolyLine(points=(va, vb, vc),
                                  isClosed=True,
                                  color=contrasting_color)

            item_name = '{}, {}'.format(surface.body1_name, surface.body2_name)
            cls = vis.PolyDataItem
            view = applogic.getCurrentRenderView()
            item = cls(item_name, d.getPolyData(), view)
            om.addToObjectModel(item, folder)
            item.setProperty('Visible', True)
            item.setProperty('Alpha', 1.0)

            # Conditional necessary to keep DrakeVisualizer from spewing
            # messages to the console when the contact surface is empty.
            if len(msg.hydroelastic_contacts) > 0:
                item.colorBy('RGB255')
Пример #4
0
view = app.createView()
view.show()


d = DebugData()
d.addLine((0,0,0), (1,0,0), radius=0.03)
show(d, (0, 0, 0))


d = DebugData()
d.addPolygon([[0,0,0], [0.8, 0, 0], [1, 0.6, 0], [0.4, 1, 0], [-0.2, 0.6, 0]])
show(d, (2, 0, 0))


d = DebugData()
d.addPolyLine(getHelixPoints(), radius=0.01)
show(d, (4, 0, 0))


d = DebugData()
d.addSphere([0, 0, 0], radius=0.3)
show(d, (6, 0, 0))


d = DebugData()
d.addFrame(vtk.vtkTransform(), scale=0.5, tubeRadius=0.03)
show(d, (0, 2, 0))


d = DebugData()
d.addArrow((0, 0, 0), (0, 1, 0))
Пример #5
0
    def drawShape(self, currShape, next_loc, msg, rotation_matrix=None):
        '''
        Function for drawing shapes. Currently this supports lines, points, and
        3D axes

        currShape: the current shape to be drawn
        next_loc: the location where to draw the shape
        msg: the message from the LCM hendler that called this function
        rotation_matrix: the rotation matrix to be used for the axis shape.
                         Mainly used by the abstract handler
        '''
        # draw a continuous line
        if (currShape.type == "line"):
            # check if the duration has been initialized
            if (currShape.duration == None or len(currShape.points) == 0):
                currShape.duration = msg.utime / 1000000

            # visualize and trace line for 'history' seconds, adding points at a distance at least 10e-5
            if (((msg.utime / 1000000) - currShape.duration <=
                 currShape.history) or currShape.history <= 0):
                # make sure to add at least 2 points before starting to check for the distance between points
                if (len(currShape.points) < 2):
                    currShape.points.append(next_loc)
                    d = DebugData()
                    d.addPolyLine(currShape.points,
                                  radius=currShape.thickness,
                                  color=currShape.color)

                    if (currShape.object == None):
                        currShape.object = vis.showPolyData(
                            d.getPolyData(), currShape.name)
                        currShape.object.setProperty('Color', currShape.color)
                    else:
                        currShape.object.setPolyData(d.getPolyData())

                else:
                    if (np.linalg.norm(
                            np.array(next_loc) -
                            np.array(currShape.points[-1])) >= 10e-5):
                        currShape.points.append(next_loc)
                        d = DebugData()
                        d.addPolyLine(currShape.points,
                                      radius=currShape.thickness,
                                      color=currShape.color)

                        if (currShape.object == None):
                            currShape.object = vis.showPolyData(
                                d.getPolyData(), currShape.name)
                        else:
                            currShape.object.setPolyData(d.getPolyData())

            elif (currShape.history > 0):
                if (len(currShape.points) == 0):
                    currShape.duration = msg.utime / 1000000
                else:
                    # visualize and trace line for 'history' seconds, adding points at a distance at least 10e-5
                    if (np.linalg.norm(
                            np.array(next_loc) -
                            np.array(currShape.points[-1])) >= 10e-5):
                        currShape.points.popleft()
                        currShape.points.append(next_loc)
                        d = DebugData()
                        d.addPolyLine(currShape.points,
                                      radius=currShape.thickness,
                                      color=currShape.color)
                        if (currShape.object == None):
                            currShape.object = vis.showPolyData(
                                d.getPolyData(), currShape.name)
                        else:
                            currShape.object.setPolyData(d.getPolyData())

        # draw a point
        elif (currShape.type == "point"):
            d = DebugData()
            d.addSphere(next_loc, radius=currShape.radius)
            # create a new point
            if (currShape.created == True):
                currShape.object = vis.showPolyData(d.getPolyData(),
                                                    currShape.name)
                # set color and transparency of point
                currShape.object.setProperty('Color', currShape.color)
                currShape.object.setProperty('Alpha', currShape.alpha)
                currShape.created = False
            else:
                # update the location of the last point
                currShape.object.setPolyData(d.getPolyData())

        # draw a set of axes
        elif (currShape.type == "axes"):
            # get the rotation matrix
            rot_matrix = None
            if (currShape.category != "lcm"):
                rigTrans = self.plant.EvalBodyPoseInWorld(
                    self.context, self.plant.GetBodyByName(currShape.frame))
                rot_matrix = rigTrans.rotation().matrix().transpose()
            else:
                rot_matrix = rotation_matrix

            colors = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

            d = DebugData()
            for i in range(3):
                d.addArrow(next_loc,
                           next_loc + (rot_matrix[i] * currShape.length),
                           headRadius=0.03,
                           color=colors[i])

            # create the 3 axes
            if (currShape.created == True):
                currShape.object = vis.showPolyData(d.getPolyData(),
                                                    currShape.name,
                                                    colorByName='RGB255')
                currShape.object.setProperty('Alpha', currShape.alpha)
                currShape.created = False
            else:
                # update the location of the last point
                currShape.object.setPolyData(d.getPolyData())
Пример #6
0
    def handle_message(self, msg):
        # Limits the rate of message handling, since redrawing is done in the
        # message handler.
        self._sub.setSpeedLimit(30)

        # Removes the folder completely.
        om.removeFromObjectModel(om.findObjectByName(self._folder_name))

        # Recreates folder.
        folder = om.getOrCreateContainer(self._folder_name)

        # Though strangely named, DebugData() is the object through which
        # drawing is done in DrakeVisualizer.
        d = DebugData()

        # Set the color map.
        color_map = self.create_color_map()

        # TODO(drum) Consider exiting early if no visualization options are
        # enabled.
        # Iterate over all triangles.
        for surface in msg.hydroelastic_contacts:
            for tri in surface.triangles:
                va = np.array([tri.p_WA[0], tri.p_WA[1], tri.p_WA[2]])
                vb = np.array([tri.p_WB[0], tri.p_WB[1], tri.p_WB[2]])
                vc = np.array([tri.p_WC[0], tri.p_WC[1], tri.p_WC[2]])

                # Save the maximum pressure.
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_A)
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_B)
                self.max_pressure_observed = max(self.max_pressure_observed,
                                                 tri.pressure_C)

                # TODO(drum) Vertex color interpolation may be insufficiently
                # granular if a single triangle spans too large a range of
                # pressures. Suggested solution is to use a texture map.
                # Get the colors at the vertices.
                color_a = color_map.get_color(tri.pressure_A)
                color_b = color_map.get_color(tri.pressure_B)
                color_c = color_map.get_color(tri.pressure_C)

                if self.show_pressure:
                    # TODO(drum) Use a better method for this; the current
                    # approach is susceptible to z-fighting under certain
                    # zoom levels.

                    # Compute a normal to the triangle. We need this normal
                    # because the visualized pressure surface can be coplanar
                    # with parts of the visualized geometry, in which case a
                    # dithering type effect would appear. So we use the normal
                    # to draw two triangles slightly offset to both sides of
                    # the contact surface.

                    # Note that if the area of this triangle is very small, we
                    # won't waste time visualizing it, which also means that
                    # won't have to worry about degenerate triangles).

                    # TODO(edrumwri) Consider allowing the user to set these
                    # next two values programmatically.
                    min_area = 1e-8
                    offset_scalar = 1e-4
                    normal = np.cross(vb - va, vc - vb)
                    norm_normal = np.linalg.norm(normal)
                    if norm_normal >= min_area:
                        unit_normal = normal / np.linalg.norm(normal)
                        offset = unit_normal * offset_scalar

                        d.addPolygon([va + offset, vb + offset, vc + offset],
                                     color=[color_a, color_b, color_c])
                        d.addPolygon([va - offset, vb - offset, vc - offset],
                                     color=[color_a, color_b, color_c])

                # TODO(drum) Consider drawing shared edges just once.
                if self.show_contact_edges:
                    contrasting_color = color_map.get_contrasting_color()
                    d.addPolyLine(points=(va, vb, vc),
                                  isClosed=True,
                                  color=contrasting_color)

            item_name = '{}, {}'.format(surface.body1_name, surface.body2_name)
            cls = vis.PolyDataItem
            view = applogic.getCurrentRenderView()
            item = cls(item_name, d.getPolyData(), view)
            om.addToObjectModel(item, folder)
            item.setProperty('Visible', True)
            item.setProperty('Alpha', 1.0)

            # Conditional necessary to keep DrakeVisualizer from spewing
            # messages to the console when the contact surface is empty.
            if len(surface.triangles) > 0:
                item.colorBy('RGB255')