Exemple #1
0
def main():
    w = WorldModel()
    w.readFile("../data/robots/kinova_gen3_7dof.urdf")
    robot = w.robot(0)
    #put a "pen" geometry on the end effector
    gpen = Geometry3D()
    res = gpen.loadFile("../data/objects/cylinder.off")
    assert res
    gpen.scale(0.01,0.01,0.15)
    gpen.rotate(so3.rotation((0,1,0),math.pi/2))
    robot.link(7).geometry().setCurrentTransform(*se3.identity())
    gpen.transform(*robot.link(8).getParentTransform())
    robot.link(7).geometry().set(merge_geometry.merge_triangle_meshes(gpen,robot.link(7).geometry()))
    robot.setConfig(robot.getConfig())
    
    trajs = get_paths()
    #place on a reasonable height and offset
    tableh = 0.1
    for traj in trajs:
        for m in traj.milestones:
            m[0] = m[0]*0.4 + 0.35
            m[1] = m[1]*0.4
            m[2] = tableh
            if len(m) == 6:
                m[3] *= 0.4
                m[4] *= 0.4

    return run_cartesian(w,trajs)
Exemple #2
0
    def loadForceSamples(self,directory):
        """Loads from [directory]/wrench_slices.csv and associated obj files"""
        f = open("%s/wrench_slices.csv"%(directory,),'r')
        lines = f.readlines()
        f.close()

        pts = []
        volumes = []
        numNonConvex = 0
        for i in xrange(1,len(lines)):
            entries = lines[i].split(',')
            assert len(entries) == 4
            ind,x,y,z = int(entries[0]),float(entries[1]),float(entries[2]),float(entries[3])
            geom = Geometry3D()
            geom.loadFile("%s/wrench_slice_%d.obj"%(directory,ind))
            V = Volume()
            V.setGeom(geom)
            if len(V.convex_decomposition) > 1:
                print "Encountered a non-convex force volume on CH point",i
                numNonConvex += 1
            
            pts.append((x,y,z))
            volumes.append(V)

        print "# of non-convex force volumes:",numNonConvex
        self.setFromForceSamples(volumes,pts)
Exemple #3
0
def merge_triangle_meshes(*items):
    merged_geom = Geometry3D()
    verts = []
    tris = []
    nverts = 0
    for i, item in enumerate(items):
        if isinstance(item, Geometry3D):
            xform, (iverts, itris) = numpy_convert.to_numpy(item)
        elif hasattr(item, 'geometry'):
            xform, (iverts, itris) = numpy_convert.to_numpy(item.geometry())
        else:
            raise ValueError(
                "Don't know how to merge trimesh from item of type " +
                item.__class__.__name__)
        verts.append(
            np.dot(np.hstack((iverts, np.ones((len(iverts), 1)))),
                   xform.T)[:, :3])
        tris.append(itris + nverts)
        nverts += len(iverts)
    verts = np.vstack(verts)
    tris = np.vstack(tris)
    for t in tris:
        assert all(v >= 0 and v < len(verts) for v in t)
    mesh = numpy_convert.from_numpy((verts, tris), 'TriangleMesh')
    merged_geom.setTriangleMesh(mesh)
    return merged_geom
Exemple #4
0
 def create_geometry_cache(self, robot, link_index, geom_index):
     """Copy into triangle mesh format"""
     self.link_cache = {}
     link_geom_info = []  # stores the (hull, geom_idx, link_idx) tuple
     for i, geom_idx in enumerate(geom_index):
         link_idx = geom_idx
         while link_idx not in link_index:  # Here it's important to find the minimum link that controls this geometry
             link_idx = robot.link(
                 link_idx).getParent()  # find its parent... makes sense
             assert link_idx != -1  # error may occur
         link = self.robot.link(geom_idx)
         geom = link.geometry().convert('ConvexHull', 0)
         link_geom_info.append((geom, geom_idx, link_idx))
     assert self.compute_point_collision or self.compute_sweep_collision, "You have to at least consider one link collision"
     self.link_cache['link'] = link_geom_info
     # do the sweep part
     if self.compute_sweep_collision:
         link_sweep_geoms = []
         for geom, geom_idx, link_idx in link_geom_info:
             sweep_geom = Geometry3D()
             sweep_geom.asConvexHull().fromTransform(geom.asConvexHull())
             link_sweep_geoms.append((sweep_geom, geom_idx, link_idx))
         self.link_cache['sweep'] = link_sweep_geoms
     # consider the rigidly mounted part
     mount_cache = []
     for i in range(len(self.mounted)):
         link_idx, relT, geom = self.mounted[i]
         geom = geom.convert('ConvexHull', 0)
         mount_cache.append((link_idx, relT, geom))
     self.link_cache['mount'] = mount_cache
     # consider the sweep of mounted geometry
     if self.compute_sweep_collision:
         mount_sweep_geoms = []
         for link_idx, _, geom in mount_cache:
             sweep_geom = Geometry3D()
             sweep_geom.asConvexHull().fromTransform(geom.asConvexHull())
             mount_sweep_geoms.append((sweep_geom, None, link_idx))
         self.link_cache['sweepmount'] = mount_sweep_geoms
     # for obstacles, there is not much we have to do
     n_obs = len(self.world)
     obs_geoms = []
     for i in range(n_obs):
         terrain = self.world.terrain(i)
         geom = terrain.geometry().convert('ConvexHull', 0)
         obs_geoms.append(geom)
     self.obs_cache = obs_geoms
Exemple #5
0
 def _addTerrain(self, path, T, color, name):
     item_1_geom = Geometry3D()
     item_1_geom.loadFile(path)
     item_1_geom.transform(T[0], T[1])
     item_1 = self.w.makeTerrain(name)
     item_1.geometry().set(item_1_geom)
     item_1.appearance().setColor(color[0], color[1], color[2], color[3])
     return item_1
Exemple #6
0
def make_shelf(world,width,depth,height,wall_thickness=0.005):
    """Makes a new axis-aligned "shelf" centered at the origin with
    dimensions width x depth x height. Walls have thickness wall_thickness.
    """
    left = Geometry3D()
    right = Geometry3D()
    back = Geometry3D()
    bottom = Geometry3D()
    top = Geometry3D()
    left.loadFile(KLAMPT_Demo+"/data/objects/cube.off")
    left.transform([wall_thickness,0,0,0,depth,0,0,0,height],[-width*0.5,-depth*0.5,0])
    right.loadFile(KLAMPT_Demo+"/data/objects/cube.off")
    right.transform([wall_thickness,0,0,0,depth,0,0,0,height],[width*0.5,-depth*0.5,0])
    back.loadFile(KLAMPT_Demo+"/data/objects/cube.off")
    back.scale(width,wall_thickness,height)
    back.translate([-width*0.5,depth*0.5,0])
    bottom = primitives.box(width,depth,wall_thickness,center=[0,0,0])
    top = primitives.box(width,depth,wall_thickness,center=[0,0,height-wall_thickness*0.5])
    shelfgeom = Geometry3D()
    shelfgeom.setGroup()
    for i,elem in enumerate([left,right,back,bottom,top]):
        g = Geometry3D(elem)
        shelfgeom.setElement(i,g)
    shelf = world.makeTerrain("shelf")
    shelf.geometry().set(shelfgeom)
    shelf.appearance().setColor(0.2,0.6,0.3,1.0)
    return shelf
Exemple #7
0
def show_workspace(grid):
    vis.add("world",w)
    res = numpy_convert.from_numpy((lower_corner,upper_corner,grid),'VolumeGrid')
    g_workspace = Geometry3D(res)
    g_surface = g_workspace.convert('TriangleMesh',0.5)
    if g_surface.numElements() != 0:
        vis.add("reachable_boundary",g_surface,color=(1,1,0,0.5))
    else:
        print("Nothing reachable?")

    Tee = robot.link(ee_link).getTransform()
    gpen.setCurrentTransform(*Tee)
    box = GeometricPrimitive()
    box.setAABB(lower_corner,upper_corner)
    gbox = Geometry3D(box)
    #show this if you want to debug the size of the grid domain
    #vis.add("box",gbox,color=(1,1,1,0.2))

    vis.add("pen tip",se3.apply(Tee,ee_local_pos))
    vis.loop()
Exemple #8
0
 def _addRigidObject(self, path, T_g, T_p, color, object_mass, Com, name):
     item_1_geom = Geometry3D()
     item_1_geom.loadFile(path)
     item_1_geom.transform(T_g[0], T_g[1])
     item_1 = self.w.makeRigidObject(name)
     item_1.geometry().set(item_1_geom)
     item_1.appearance().setColor(color[0], color[1], color[2], color[3])
     bmass = item_1.getMass()
     bmass.setMass(object_mass)
     bmass.setCom(Com)
     item_1.setMass(bmass)
     item_1.setTransform(T_p[0], T_p[1])
     return item_1
Exemple #9
0
    def addTable(self, x=0, y=0):
        """
        Add a table to the world

        Parameters:
        --------------
        x,y: floats, the x,y position of the center of the table
        """
        table_top = Geometry3D()
        table_leg_1 = Geometry3D()
        table_leg_2 = Geometry3D()
        table_leg_3 = Geometry3D()
        table_leg_4 = Geometry3D()

        table_top.loadFile(model_path + "cube.off")
        table_leg_1.loadFile(model_path + "cube.off")
        table_leg_2.loadFile(model_path + "cube.off")
        table_leg_3.loadFile(model_path + "cube.off")
        table_leg_4.loadFile(model_path + "cube.off")

        table_top.transform([self.table_length,0,0,0,self.table_width,0,0,0,\
            self.table_top_thickness],[0,0,self.table_height - self.table_top_thickness])
        table_leg_1.transform([self.leg_width,0,0,0,self.leg_width,0,0,0,self.table_height\
            - self.table_top_thickness],[0,0,0])
        table_leg_2.transform([self.leg_width,0,0,0,self.leg_width,0,0,0,self.table_height - \
            self.table_top_thickness],[self.table_length-self.leg_width,0,0])
        table_leg_3.transform([
            self.leg_width, 0, 0, 0, self.leg_width, 0, 0, 0,
            self.table_height - self.table_top_thickness
        ], [
            self.table_length - self.leg_width,
            self.table_width - self.leg_width, 0
        ])
        table_leg_4.transform([
            self.leg_width, 0, 0, 0, self.leg_width, 0, 0, 0,
            self.table_height - self.table_top_thickness
        ], [0, self.table_width - self.leg_width, 0])

        table_geom = Geometry3D()
        table_geom.setGroup()
        for i, elem in enumerate(
            [table_top, table_leg_1, table_leg_2, table_leg_3, table_leg_4]):
            g = Geometry3D(elem)
            table_geom.setElement(i, g)
        #table_geom.transform([1,0,0,0,1,0,0,0,1],[x-self.table_length/2.0,y-self.table_width/2.0,0])
        table_geom.transform(
            so3.from_rpy([0, 0, math.pi / 2]),
            [x - self.table_length / 2.0, y - self.table_width / 2.0, 0])
        table = self.w.makeTerrain("table")
        table.geometry().set(table_geom)
        table.appearance().setColor(self.light_blue[0], self.light_blue[1],
                                    self.light_blue[2], self.light_blue[3])
Exemple #10
0
 def get_geometry(self,robot,qfinger=None,type='Group'):
     """Returns a Geometry of the gripper frozen at its configuration.
     If qfinger = None, the current configuration is used.  Otherwise,
     qfinger is a finger configuration.
     
     type can be 'Group' (most general and fastest) or 'TriangleMesh'
     (compatible with Jupyter notebook visualizer.)
     """
     if qfinger is not None:
         q0 = robot.getConfig()
         robot.setConfig(self.set_finger_config(q0,qfinger))
     res = Geometry3D()
     gripper_links = self.gripper_links if self.gripper_links is not None else [self.base_link] + self.descendant_links(robot)
     if type == 'Group':
         res.setGroup()
         Tbase = robot.link(self.base_link).getTransform()
         for i,link in enumerate(gripper_links):
             Trel = se3.mul(se3.inv(Tbase),robot.link(link).getTransform())
             g = robot.link(link).geometry().clone()
             if not g.empty():
                 g.setCurrentTransform(*se3.identity())
                 g.transform(*Trel)
             else:
                 print("Uh... link",robot.link(link).getName(),"has empty geometry?")
             res.setElement(i,g)
         if qfinger is not None:
             robot.setConfig(q0)
         return res
     else:
         import numpy as np
         from klampt.io import numpy_convert
         #merge the gripper parts into a static geometry
         verts = []
         tris = []
         nverts = 0
         for i,link in enumerate(gripper_links):
             xform,(iverts,itris) = numpy_convert.to_numpy(robot.link(link).geometry())
             verts.append(np.dot(np.hstack((iverts,np.ones((len(iverts),1)))),xform.T)[:,:3])
             tris.append(itris+nverts)
             nverts += len(iverts)
         verts = np.vstack(verts)
         tris = np.vstack(tris)
         for t in tris:
             assert all(v >= 0 and v < len(verts) for v in t)
         mesh = numpy_convert.from_numpy((verts,tris),'TriangleMesh')
         res.setTriangleMesh(mesh)
         if qfinger is not None:
             robot.setConfig(q0)
         return res
Exemple #11
0
def make_box(world,
             width,
             depth,
             height,
             wall_thickness=0.005,
             mass=float('inf')):
    """Makes a new axis-aligned open-top box with its bottom centered at the origin
    with dimensions width x depth x height. Walls have thickness wall_thickness. 
    If mass=inf, then the box is a TerrainModel, otherwise it's a RigidObjectModel
    with automatically determined inertia.
    """
    left = primitives.box(
        wall_thickness, depth, height,
        [-width * 0.5 - wall_thickness * 0.5, 0, height * 0.5])
    right = primitives.box(
        wall_thickness, depth, height,
        [width * 0.5 + wall_thickness * 0.5, 0, height * 0.5])
    front = primitives.box(
        width, wall_thickness, height,
        [0, -depth * 0.5 - wall_thickness * 0.5, height * 0.5])
    back = primitives.box(
        width, wall_thickness, height,
        [0, depth * 0.5 + wall_thickness * 0.5, height * 0.5])
    bottom = primitives.box(width, depth, wall_thickness,
                            [0, 0, wall_thickness * 0.5])
    boxgeom = Geometry3D()
    boxgeom.setGroup()
    for i, elem in enumerate([left, right, front, back, bottom]):
        boxgeom.setElement(i, elem)
    if mass != float('inf'):
        print("Making open-top box a rigid object")
        bmass = Mass()
        bmass.setMass(mass)
        bmass.setCom([0, 0, height * 0.3])
        bmass.setInertia([width / 12, depth / 12, height / 12])
        box = world.makeRigidObject("box")
        box.geometry().set(boxgeom)
        box.appearance().setColor(0.6, 0.3, 0.2, 1.0)
        box.setMass(bmass)
        return box
    else:
        print("Making open-top box a terrain")
        box = world.makeTerrain("box")
        box.geometry().set(boxgeom)
        box.appearance().setColor(0.6, 0.3, 0.2, 1.0)
        return box
Exemple #12
0
def main():
    w = WorldModel()
    w.readFile("../data/robots/kinova_gen3_7dof.urdf")

    robot = w.robot(0)
    #put a "pen" geometry on the end effector
    gpen = Geometry3D()
    res = gpen.loadFile("../data/objects/cylinder.off")
    assert res
    gpen.scale(0.01,0.01,0.15)
    gpen.rotate(so3.rotation((0,1,0),math.pi/2))
    robot.link(7).geometry().setCurrentTransform(*se3.identity())
    gpen.transform(*robot.link(8).getParentTransform())
    robot.link(7).geometry().set(merge_geometry.merge_triangle_meshes(gpen,robot.link(7).geometry()))
    robot.setConfig(robot.getConfig())

    return run_simulation(w)
def debug_stable_faces(obj, faces):
    from klampt import vis, Geometry3D, GeometricPrimitive
    from klampt.math import se3
    import random
    vis.createWindow()
    obj.setTransform(*se3.identity())
    vis.add("object", obj)
    for i, f in enumerate(faces):
        gf = GeometricPrimitive()
        gf.setPolygon(np.stack(f).flatten())
        color = (1, 0.5 + 0.5 * random.random(), 0.5 + 0.5 * random.random(),
                 0.5)
        vis.add("face{}".format(i),
                Geometry3D(gf),
                color=color,
                hide_label=True)
    vis.setWindowTitle("Stable faces")
    vis.dialog()
Exemple #14
0
    def __init__(self, floor_length=20, floor_width=20):
        self.w = WorldModel()
        self.floor = Geometry3D()
        self.floor.loadFile(model_path + "cube.off")
        self.floor.transform(
            [floor_length, 0, 0, 0, floor_width, 0, 0, 0, 0.01],
            [-floor_length / 2.0, -floor_width / 2.0, -0.01])
        floor_terrain = self.w.makeTerrain("floor")
        floor_terrain.geometry().set(self.floor)
        floor_terrain.appearance().setColor(0.4, 0.3, 0.2, 1.0)

        ###colors
        self.light_blue = [3.0 / 255.0, 140.0 / 255.0, 252.0 / 255.0, 1.0]
        self.wall_green = [50.0 / 255.0, 168.0 / 255.0, 143.0 / 255.0, 1.0]
        ###sizes
        self.table_length = 1.0
        self.table_width = 0.5
        self.table_top_thickness = 0.03
        self.table_height = 0.6
        self.leg_width = 0.05
        self.cube_width = 0.05
Exemple #15
0
def hull_to_klampt_geom(hull):
    """Converts a 3D hull to a Klamp't Geometry3D object."""
    if len(hull.points) != 0:
        if len(hull.points[0]) != 3:
            raise RuntimeError("Invalid hull, not 3D")
    mesh = TriangleMesh()
    ptov = dict()
    ind =  0
    for v in hull.vertices:
        p = hull.points[v] 
        mesh.vertices.append(p[0])
        mesh.vertices.append(p[1])
        mesh.vertices.append(p[2])
        ptov[v]=ind
        ind+=1
    for s in hull.simplices:
        assert len(s) == 3,"TODO: triangulate non-triangular facets"
        mesh.indices.append(ptov[s[0]])
        mesh.indices.append(ptov[s[1]])
        mesh.indices.append(ptov[s[2]])
    return Geometry3D(mesh)
Exemple #16
0
def camera_to_points(camera,
                     points_format='numpy',
                     all_points=False,
                     color_format='channels'):
    """Given a SimRobotSensor that is a CameraSensor, returns a point cloud
    associated with the current measurements.

    Points are triangulated with respect to the camera's intrinsic coordinates,
    and are returned in the camera local frame (+z backward, +x toward the
    right, +y toward up). 

    The arguments 

    Args:
        points_format (str, optional): configures the format of the return
            value. Can be:

            * 'numpy' (default): either an Nx3, Nx4, or Nx6 numpy array,
              depending on whether color is requested (and its format).  Will
              fall back to 'native' if numpy is not available.
            * 'native': same as numpy, but in list-of-lists format rather than
              numpy arrays.
            * 'PointCloud': a Klampt PointCloud object
            * 'Geometry3D': a Klampt Geometry3D point cloud object

        all_points (bool, optional): configures whether bad points should be
            stripped out.  If False (default), this strips out all pixels that
            don't have a good depth reading (i.e., the camera sensor's maximum
            reading.)  If True, these pixels are all set to (0,0,0).

        color_format (str):  If the sensor has an RGB component, then color
            channels may be produced.  This value configures the output format,
            and can take on the values:

            * 'channels': produces individual R,G,B channels in the range
              [0,1]. (note this is different from the interpretation of
              camera_to_images)
            * 'rgb': produces a single 32-bit integer channel packing the 8-bit
              color channels together in the format 0xrrggbb.
            * None: no color is produced.

    Returns:
        object: the point cloud in the requested format.
    """
    assert isinstance(camera,
                      SimRobotSensor), "Must provide a SimRobotSensor instance"
    assert camera.type(
    ) == 'CameraSensor', "Must provide a camera sensor instance"
    assert int(camera.getSetting(
        'depth')) == 1, "Camera sensor must have a depth channel"
    has_numpy = _try_numpy_import()
    if points_format == 'numpy' and not has_numpy:
        points_format = 'native'

    images = camera_to_images(camera, 'numpy', color_format)
    assert images != None

    rgb, depth = None, None
    if int(camera.getSetting('rgb')) == 0:
        depth = images
        color_format = None
    else:
        rgb, depth = images

    w = int(camera.getSetting('xres'))
    h = int(camera.getSetting('yres'))
    xfov = float(camera.getSetting('xfov'))
    yfov = float(camera.getSetting('yfov'))
    zmin = float(camera.getSetting('zmin'))
    zmax = float(camera.getSetting('zmax'))
    xshift = -w * 0.5
    yshift = -h * 0.5
    xscale = math.tan(xfov * 0.5) / (w * 0.5)
    #yscale = -1.0/(math.tan(yfov*0.5)*h/2)
    yscale = xscale  #square pixels are assumed
    xs = [(j + xshift) * xscale for j in range(w)]
    ys = [(i + yshift) * yscale for i in range(h)]
    if has_numpy:
        if all_points:
            depth[depth >= zmax] = 0
        if color_format == 'channels':
            #scale to range [0,1]
            rgb = rgb * (1.0 / 255.0)
        xgrid = np.repeat(np.array(xs).reshape((1, w)), h, 0)
        ygrid = np.repeat(np.array(ys).reshape((h, 1)), w, 1)
        assert xgrid.shape == (h, w)
        assert ygrid.shape == (h, w)
        pts = np.dstack((np.multiply(xgrid, depth), np.multiply(ygrid,
                                                                depth), depth))
        assert pts.shape == (h, w, 3)
        if color_format is not None:
            if len(rgb.shape) == 2:
                rgb = rgb.reshape(rgb.shape[0], rgb.shape[1], 1)
            pts = np.concatenate((pts, rgb), 2)
        #now have a nice array containing all points, shaped h x w x (3+c)
        #extract out the valid points from this array
        if all_points:
            pts = pts.reshape(w * h, pts.shape[2])
        else:
            pts = pts[depth < zmax]

        if points_format == 'native':
            return pts.tolist()
        elif points_format == 'numpy':
            return pts
        elif points_format == 'PointCloud' or points_format == 'Geometry3D':
            res = PointCloud()
            if all_points:
                res.setSetting('width', str(w))
                res.setSetting('height', str(h))
            res.setPoints(pts.shape[0], pts[:, 0:3].flatten().tolist())
            if color_format == 'rgb':
                res.addProperty('rgb')
                res.setProperties(pts[:, 3].flatten().tolist())
            elif color_format == 'channels':
                res.addProperty('r')
                res.addProperty('g')
                res.addProperty('b')
                res.setProperties(pts[:, 3:6].flatten().tolist())
            elif color_format == 'bgr':
                raise ValueError(
                    "bgr color format not supported with PointCloud output")
            if points_format == 'PointCloud':
                return res
            else:
                from klampt import Geometry3D
                g = Geometry3D()
                g.setPointCloud(res)
                return g
        else:
            raise ValueError("Invalid points_format " + points_format)
        return Nnoe
    else:
        raise NotImplementedError(
            "Native format depth image processing not done yet")
Exemple #17
0
def image_to_points(depth,
                    color,
                    xfov,
                    yfov=None,
                    depth_scale=None,
                    depth_range=None,
                    color_format='auto',
                    points_format='numpy',
                    all_points=False):
    """Given a depth and optionally color image, returns a point cloud
    representing the depth or RGB-D scene.  

    Args:
        depth (list of lists or numpy array): the w x h depth image (rectified).
        color (list of lists or numpy array, optional): the w x h color image. 
            Assumed that color maps directly onto depth pixels.  If None,
            an uncolored point cloud will be produced. 
        xfov (float): horizontal field of view, in radians.
        yfov (float, optional): vertical field of view, in radians.  If not
            given, square pixels are assumed.
        depth_scale (float, optional): a scaling from depth image values to
            absolute depth values.
        depth_range (pair of floats, optional): if given, only points within 
            this depth range (non-inclusive) will be extracted.  If
            all_points=False, points that fail the range test will be stripped
            from the output.  E.g., (0.5,8.0) only extracts points with
            z > 0.5 and z < 8 units.
        color_format (str): governs how pixels in the RGB result are packed. 
            Can be:

            * 'auto' (default): if it's a 3D array, it assumes elements are in
              'channels' format, otherwise it assumes 'rgb'.
            * 'channels': a 3D array with 3 channels corresponding to R, G,
              B values in the range [0,255] if uint8 type, otherwise in the
              range [0,1]. 
            * 'rgb' a 2D array with a 32-bit integer channel, with
              R,G,B channels packed in hex format 0xrrggbb.

        points_format (str, optional): configures the format of the return
            value. Can be:

            * 'numpy' (default): either an Nx3, Nx4, or Nx6 numpy array,
              depending on whether color is requested (and its format).  Will
              fall back to 'native' if numpy is not available.
            * 'native': same as numpy, but in list-of-lists format rather than
              numpy arrays.
            * 'PointCloud': a Klampt PointCloud object
            * 'Geometry3D': a Klampt Geometry3D point cloud object

        all_points (bool, optional): configures whether bad points should be
            stripped out.  If False (default), this strips out all pixels that
            don't have a good depth reading (i.e., the camera sensor's maximum
            reading.)  If True, these pixels are all set to (0,0,0).

    Returns:
        numpy ndarray or Geometry3D: the point cloud.  Represented as being local to the standard
        camera frame with +x to the right, +y down, +z forward.

    """
    has_numpy = _try_numpy_import()
    if not has_numpy:
        raise NotImplementedError("TODO image_to_points without numpy")
    depth = np.asarray(depth)
    assert len(depth.shape) == 2
    h, w = depth.shape
    if color is not None:
        color = np.asarray(color)
        if h != color.shape[0] or w != color.shape[1]:
            raise ValueError("color and depth need to have same dimensions")
        if color_format == 'auto':
            if len(color.shape) == 3:
                color_format = 'channels'
            else:
                assert len(color.shape) == 2
                color_format = 'rgb'
    if depth_scale is not None:
        depth *= depth_scale
    if depth_range is not None:
        valid = np.logical_and((depth > depth_range[0]),
                               (depth < depth_range[1]))
        if all_points:
            depth[~valid] = 0
        valid = (depth > 0)
    else:
        valid = (depth > 0)

    xshift = -w * 0.5
    yshift = -h * 0.5
    xscale = math.tan(xfov * 0.5) / (w * 0.5)
    if yfov is not None:
        yscale = -1.0 / (math.tan(yfov * 0.5) * h / 2)
    else:
        yscale = xscale  #square pixels are assumed
    xs = [(j + xshift) * xscale for j in range(w)]
    ys = [(i + yshift) * yscale for i in range(h)]
    if color_format == 'channels' and color.dtype == np.uint8:
        #scale to range [0,1]
        color = color * (1.0 / 255.0)

    xgrid = np.repeat(np.array(xs).reshape((1, w)), h, 0)
    ygrid = np.repeat(np.array(ys).reshape((h, 1)), w, 1)
    assert xgrid.shape == (h, w)
    assert ygrid.shape == (h, w)
    pts = np.dstack((np.multiply(xgrid, depth), np.multiply(ygrid,
                                                            depth), depth))
    assert pts.shape == (h, w, 3)
    if color_format is not None:
        if len(color.shape) == 2:
            color = color.reshape(color.shape[0], color.shape[1], 1)
        pts = np.concatenate((pts, color), 2)
    #now have a nice array containing all points, shaped h x w x (3+c)
    #extract out the valid points from this array
    if all_points:
        pts = pts.reshape(w * h, pts.shape[2])
    else:
        pts = pts[valid]

    if points_format == 'native':
        return pts.tolist()
    elif points_format == 'numpy':
        return pts
    elif points_format == 'PointCloud' or points_format == 'Geometry3D':
        res = PointCloud()
        if all_points:
            res.setSetting('width', str(w))
            res.setSetting('height', str(h))
        res.setPoints(pts.shape[0], pts[:, 0:3].flatten().tolist())
        if color_format == 'rgb':
            res.addProperty('rgb')
            res.setProperties(pts[:, 3].flatten().tolist())
        elif color_format == 'channels':
            res.addProperty('r')
            res.addProperty('g')
            res.addProperty('b')
            res.setProperties(pts[:, 3:6].flatten().tolist())
        if points_format == 'PointCloud':
            return res
        else:
            from klampt import Geometry3D
            g = Geometry3D()
            g.setPointCloud(res)
            return g
    else:
        raise ValueError(
            "Invalid points_format, must be either native, numpy, PointCloud, or Geometry3D"
        )
Exemple #18
0
    #initiate the world
    w = WorldModel()

    #add a floor
    # floor =  Geometry3D()
    # floor.loadFile("cube.off")
    # floor_length = 0.2
    # floor_width = 0.2
    # floor.transform([floor_length,0,0,0,floor_width,0,0,0,0.01],[-floor_length/2.0,-floor_width/2.0,-0.01])
    # floor_terrain = w.makeTerrain("floor")
    # floor_terrain.geometry().set(floor)
    # floor_terrain.appearance().setColor(0.4,0.3,0.2,1.0)

    #add the probe
    item_1_geom = Geometry3D()
    item_1_geom.loadFile('Contact_Probe_linear2.STL')
    #item_1_geom.transform(T_g[0],T_g[1])
    item_1 = w.makeRigidObject('probe')
    item_1.geometry().set(item_1_geom)
    item_1.appearance().setColor(1, 0, 0, 0.2)

    ###################Load data for line probe#################################################
    exp_path = '../data_final/exp_' + str(exp_N) + '/'
    exp_path_2 = '../data_final/exp_' + str(exp_N) + '_debiased/'
    #load line geometry data
    lineStarts, lineEnds, lineNormals, lineTorqueAxes = cal_line_data(exp_path)
    #load visual model
    pcd = load_pcd(exp_path_2 + 'originalPcd.txt', pcdtype='return_lines')
    points = np.array(pcd)
Exemple #19
0
    def make_cube(self,
                  world,
                  width,
                  depth,
                  height,
                  x,
                  y,
                  z,
                  wall_thickness,
                  color,
                  name,
                  object_file="cube.off",
                  object_type="terrain"):
        """
        This function created a cube object based on the given dimension and position
        :param world: world object
        :param width: width of the cube
        :param depth: depth of the cube
        :param height: height of the cube
        :param x: X coordinate of the  of the cube center
        :param y: Y coordinate of the  of the cube center
        :param z: Z coordinate of the  of the cube center
        :param wall_thickness: wall thickness of the cube
        :param object_file: file of the cube object
        :return:
        """
        object_path = self.objects_dir + object_file

        # create the Geometry for all the faces of the object
        left = Geometry3D()
        right = Geometry3D()
        front = Geometry3D()
        back = Geometry3D()
        bottom = Geometry3D()
        top = Geometry3D()

        left.loadFile(object_path)
        right.loadFile(object_path)
        front.loadFile(object_path)
        back.loadFile(object_path)
        bottom.loadFile(object_path)
        top.loadFile(object_path)

        left.transform([wall_thickness, 0, 0, 0, depth, 0, 0, 0, height],
                       [-width * 0.5, -depth * 0.5, 0])
        right.transform([wall_thickness, 0, 0, 0, depth, 0, 0, 0, height],
                        [width * 0.5, -depth * 0.5, 0])
        front.transform([-width, 0, 0, 0, wall_thickness, 0, 0, 0, height],
                        [width * 0.5, -depth * 0.5, 0])
        back.transform([width, 0, 0, 0, wall_thickness, 0, 0, 0, height],
                       [-width * 0.5, depth * 0.5, 0])
        bottom.transform([width, 0, 0, 0, depth, 0, 0, 0, wall_thickness],
                         [-width * 0.5, -depth * 0.5, 0])
        top.transform([width, 0, 0, 0, depth, 0, 0, 0, wall_thickness],
                      [-width * 0.5, -depth * 0.5, height - wall_thickness])
        cubegeom = Geometry3D()

        cubegeom.setGroup()
        for i, elem in enumerate([left, right, front, back, bottom, top]):
            g = Geometry3D(elem)
            cubegeom.setElement(i, g)

        if object_type == "rigid" or object_type == "goal":
            cube = world.makeRigidObject(name)
        else:
            cube = world.makeTerrain(name)
        cube.geometry().set(cubegeom)
        cube.appearance().setColor(color[0], color[1], color[2], color[3])
        cube.geometry().translate((x, y, z))

        return cube
Exemple #20
0
    def find_collision_pair(self, thetas, dcheck):
        """
        Given current solution, find all possible collision pairs.
        """
        link_trans, mount_trans = self.all_linkgeom_transforms(thetas)
        point_collisions = []
        sweep_collisions = []
        # Just iterate through all stuff and see what happens... We can safely ignore first and last
        n_theta = thetas.shape[0]
        setting = DistanceQuerySettings()
        setting.upperBound = dcheck  # value greater than this is not considered

        def add_point(link_idx, geom_idx, rst, i, oj):
            # This function add point collision information...
            p1, p2 = np.array(rst.cp1), np.array(rst.cp2)
            if rst.d > 0:
                normal = (p1 - p2)
            else:
                normal = p2 - p1
            normal /= np.linalg.norm(normal)
            # find p1 in local coordinate
            self.robot.setConfig(thetas[i])
            p1_local = self.robot.link(link_idx).getLocalPosition(list(p1))
            jacobian = self.robot.positionJacobian(link_idx, lcl_pos=p1_local)
            point_collisions.append(
                JointObjectInfo(geom_idx, oj, thetas[i].copy(), i, jacobian,
                                normal, rst.d))

        def add_sweep(link_idx, geom_idx, sgl_lv, ltran1, ltran2, rst, i, oj):
            # This function add sweep collision information
            p2, pswept = np.array(rst.cp2), np.array(rst.cp1)
            if rst.d > 0:
                normal = pswept - p2
            else:
                normal = p2 - pswept
            normal /= np.linalg.norm(normal)
            # I have to find the two points on two seperate geometry
            sgl_lv.setCurrentTransform(*ltran1)
            p0 = np.array(sgl_lv.support(-normal))
            sgl_lv.setCurrentTransform(*ltran2)
            p1 = np.array(sgl_lv.support(-normal))
            dist1 = np.linalg.norm(p1 - pswept)
            dist0 = np.linalg.norm(p0 - pswept)
            alpha = dist1 / (dist0 + dist1)
            # print(f'Sweep link {li} obj {oj} step {i} dist {dist:.3f} dist0 {dist0:.3f} dist1 {dist1:.3f}')
            # compute the two jacobians
            self.robot.setConfig(thetas[i])
            the_link = self.robot.link(link_idx)
            p0_local = the_link.getLocalPosition(p0)
            # jac0 = np.array(self.robot.link(li_).getPositionJacobian(p0_local))
            jac0 = self.robot.positionJacobian(link_idx, None, p0_local)
            self.robot.setConfig(thetas[i + 1])
            p1_local = the_link.getLocalPosition(p1)
            # jac1 = np.array(self.robot.link(li_).getPositionJacobian(p1_local))
            jac1 = self.robot.positionJacobian(link_idx, None, p1_local)
            sweep_collisions.append(
                SweepJointObjectInfo(geom_idx, oj, thetas[i].copy(),
                                     thetas[i + 1].copy(), i, alpha, jac0,
                                     jac1, normal, rst.d))
            sweep_collisions[-1].point1 = p0
            sweep_collisions[-1].point2 = p1
            sweep_collisions[-1].pswept = pswept
            sweep_collisions[-1].pobs = p2

        # outer loop is for obstacles
        for oj_, oj in enumerate(self.world.index):
            ov = self.geom_cache['obs'][
                oj_]  # transformation information is already contained in Geometry3D
            for li_, (lv, lv_copy, geom_idx,
                      link_idx) in enumerate(self.geom_cache['link']):
                # first step is to compute point violation...
                if self.compute_point_collision:
                    for i in range(1, n_theta - 1):
                        ltran = link_trans[i][li_]
                        lv.setCurrentTransform(*ltran)
                        rst = lv.distance_ext(ov, setting)
                        # append if dist is smaller than dcheck
                        if rst.d < dcheck:
                            add_point(link_idx, geom_idx, rst, i, oj)
                # the next step is to compute sweep information
                if self.compute_sweep_collision:
                    for i in range(n_theta - 1):
                        ltran1, ltran2 = link_trans[i][li_], link_trans[i +
                                                                        1][li_]
                        lv.setCurrentTransform(
                            *ltran1)  # set transformation of link start
                        lv_copy.setCurrentTransform(
                            *ltran2)  # set transform of link end
                        cvxhull = Geometry3D()
                        cvxhull.setConvexHullGroup(lv, lv_copy)
                        rst = cvxhull.distance_ext(ov, setting)
                        if rst.d < dcheck:
                            add_sweep(link_idx, geom_idx, lv, ltran1, ltran2,
                                      rst, i, oj)
            # now I consider attached geometries
            for li_, (link_idx, relT, geom,
                      geom_copy) in enumerate(self.geom_cache['mount']):
                # start with point ocllision
                if self.compute_point_collision:
                    for i in range(1, n_theta - 1):
                        ltran = mount_trans[i][li_]
                        geom.setCurrentTransform(*ltran)
                        rst = geom.distance_ext(ov, setting)
                        if rst.d < dcheck:
                            add_point(link_idx, -1 - li_, rst, i, oj)
                # then sweep one
                if self.compute_sweep_collision:
                    for i in range(n_theta - 1):
                        ltran1, ltran2 = mount_trans[i][li_], mount_trans[
                            i + 1][li_]
                        geom.setCurrentTransform(*ltran1)
                        geom_copy.setCurrentTransform(*ltran2)
                        cvxhull = Geometry3D()
                        cvxhull.setConvexHullGroup(geom, geom_copy)
                        rst = cvxhull.distance_ext(ov, setting)
                        if rst.d < dcheck:
                            add_sweep(link_idx, -1 - li_, geom, ltran1, ltran2,
                                      rst, i, oj)
        return point_collisions, sweep_collisions
Exemple #21
0
def from_numpy(obj, type='auto', template=None):
    """Converts a numpy array or multiple numpy arrays to a Klamp't object.

    Supports:

    * lists and tuples
    * RigidTransform: accepts a 4x4 homogeneous coordinate transform
    * Matrix3, Rotation: accepts a 3x3 matrix.
    * Configs
    * Trajectory: accepts a pair (times,milestones)
    * TriangleMesh: accepts a pair (verts,indices)
    * PointCloud: accepts a n x (3+k) array, where k is the # of properties
    * VolumeGrid: accepts a triple (bmin,bmax,array)
    * Geometry3D: accepts a pair (T,geomdata)
    """
    global supportedTypes
    if type == 'auto' and template is not None:
        otype = types.objectToTypes(template)
        if isinstance(otype, (list, tuple)):
            for t in otype:
                if t in supportedTypes:
                    type = t
                    break
            if type == 'auto':
                raise ValueError('obj is not a supported type: ' +
                                 ', '.join(otype))
        else:
            type = otype
    if type == 'auto':
        if isinstance(obj, (tuple, list)):
            if all(isinstance(v, np.ndarray) for v in obj):
                if len(obj) == 2:
                    if len(obj[0].shape) == 1 and len(obj[1].shape) == 2:
                        type = 'Trajectory'
                    elif len(obj[0].shape) == 2 and len(
                            obj[1].shape
                    ) == 2 and obj[0].shape[1] == 3 and obj[1].shape[1] == 3:
                        type = 'TriangleMesh'
                if len(obj) == 3:
                    if obj[0].shape == (3, ) and obj[1].shape == (3, ):
                        type = 'VolumeGrid'
                if type == 'auto':
                    raise ValueError(
                        "Can't auto-detect type of list of shapes" +
                        ', '.join(str(v.shape) for v in obj))
            else:
                if isinstance(obj[0], np.ndarray) and obj[0].shape == (4, 4):
                    type = 'Geometry3D'
                else:
                    raise ValueError(
                        "Can't auto-detect type of irregular list")
        else:
            assert isinstance(
                obj, np.ndarray
            ), "Can only convert lists, tuples, and arrays from numpy"
            if obj.shape == (3, 3):
                type = 'Matrix3'
            elif obj.shape == (4, 4):
                type = 'RigidTransform'
            elif len(obj.shape) == 1:
                type = 'Config'
            else:
                raise ValueError("Can't auto-detect type of matrix of shape " +
                                 str(obj.shape))
    if type not in supportedTypes:
        raise ValueError(type + ' is not a supported type')
    if type == 'RigidTransform':
        return se3.from_homogeneous(obj)
    elif type == 'Rotation' or type == 'Matrix3':
        return so3.from_matrix(obj)
    elif type == 'Trajectory':
        assert len(obj) == 2, "Trajectory format is (times,milestones)"
        times = obj[0].tolist()
        milestones = obj[1].tolist()
        if template is not None:
            return template.constructor()(times, milestones)
        from klampt.model.trajectory import Trajectory
        return Trajectory(times, milestones)
    elif type == 'TriangleMesh':
        from klampt import TriangleMesh
        res = TriangleMesh()
        vflat = obj[0].flatten()
        res.vertices.resize(len(vflat))
        for i, v in enumerate(vflat):
            res.vertices[i] = float(v)
        iflat = obj[1].flatten()
        res.indices.resize(len(iflat))
        for i, v in enumerate(iflat):
            res.indices[i] = int(v)
        return res
    elif type == 'PointCloud':
        from klampt import PointCloud
        assert len(obj.shape) == 2, "PointCloud array must be a 2D array"
        assert obj.shape[1] >= 3, "PointCloud array must have at least 3 values"
        points = obj[:, :3]
        properties = obj[:, 3:]
        res = PointCloud()
        res.setPoints(points.shape[0], points.flatten())
        if template is not None:
            if len(template.propertyNames) != properties.shape[1]:
                raise ValueError(
                    "Template object doesn't have the same properties as the numpy object"
                )
            for i in range(len(template.propertyNames)):
                res.propertyNames[i] = template.propertyNames[i]
        else:
            for i in range(properties.shape[1]):
                res.propertyNames.append('property %d' % (i + 1))
        if len(res.propertyNames) > 0:
            res.properties.resize(len(res.propertyNames) * points.shape[0])
        if obj.shape[1] >= 3:
            res.setProperties(properties.flatten())
        return res
    elif type == 'VolumeGrid':
        from klampt import VolumeGrid
        assert len(obj) == 3, "VolumeGrid format is (bmin,bmax,values)"
        assert len(obj[2].shape) == 3, "VolumeGrid values must be a 3D array"
        bmin = obj[0]
        bmax = obj[1]
        values = obj[2]
        res = VolumeGrid()
        res.bbox.append(bmin[0])
        res.bbox.append(bmin[1])
        res.bbox.append(bmin[2])
        res.bbox.append(bmax[0])
        res.bbox.append(bmax[1])
        res.bbox.append(bmax[2])
        res.dims.append(values.shape[0])
        res.dims.append(values.shape[1])
        res.dims.append(values.shape[2])
        vflat = values.flatten()
        res.values.resize(len(vflat))
        for i, v in enumerate(vflat):
            res.values[i] = v
        return res
    elif type == 'Group':
        from klampt import Geometry3D
        res = Geometry3D()
        assert isinstance(
            obj,
            (list, tuple)), "Group format is a list or tuple of Geometry3D's"
        for i in range(len(obj)):
            res.setElement(i, from_numpy(obj[i], 'Geometry3D'))
        return res
    elif type == 'Geometry3D':
        from klampt import Geometry3D
        if not isinstance(obj, (list, tuple)) or len(obj) != 2:
            raise ValueError("Geometry3D must be a (transform,geometry) tuple")
        T = from_numpy(obj[0], 'RigidTransform')
        geomdata = obj[1]
        subtype = None
        if template is not None:
            subtype = template.type()
            if subtype == 'PointCloud':
                g = Geometry3D(
                    from_numpy(geomdata, subtype, template.getPointCloud()))
            else:
                g = Geometry3D(from_numpy(geomdata, subtype))
            g.setCurrentTransform(*T)
            return g
        subtype = 'Group'
        if all(isinstance(v, np.ndarray) for v in geomdata):
            if len(geomdata) == 2:
                if len(geomdata[0].shape) == 1 and len(geomdata[1].shape) == 2:
                    subtype = 'Trajectory'
                elif len(geomdata[0].shape) == 2 and len(
                        geomdata[1].shape) == 2 and geomdata[0].shape[
                            1] == 3 and geomdata[1].shape[1] == 3:
                    subtype = 'TriangleMesh'
            if len(geomdata) == 3:
                if geomdata[0].shape == (3, ) and geomdata[1].shape == (3, ):
                    subtype = 'VolumeGrid'
        g = Geometry3D(from_numpy(obj, subtype))
        g.setCurrentTransform(*T)
        return g
    else:
        return obj.flatten()
Exemple #22
0
def box(width,
        depth,
        height,
        center=None,
        R=None,
        t=None,
        world=None,
        name=None,
        mass=float('inf'),
        type='TriangleMesh'):
    """Makes a box with dimensions width x depth x height.  The box is centered
    at (0,0,0) by default.

    Args:
        width,depth,height (float): x,y,z dimensions of the box
        center (list of 3 floats, optional): if None (typical),
            the *geometry* of the box is centered at 0. Otherwise,
            the *geometry* of the box is shifted relative to the
            box's local coordinate system.
        R,t (se3 transform, optional): if given, the box's world coordinates
            will be rotated and shifted by this transform.
        world (WorldModel, optional): If given, then the box will be a
            RigidObjectModel or TerrainModel will be created in this world
        name (str, optional): If world is given, this is the name of the object. 
            Default is 'box'.
        mass (float, optional): If world is given and this is inf, then a
            TerrainModel will be created. Otherwise, a RigidObjectModel
            will be created with automatically determined inertia.
        type (str, optional): the geometry type.  Defaults to 'TriangleMesh',
            but also 'GeometricPrimitive' and 'VolumeGrid' are accepted.

    Returns:
        Geometry3D, RigidObjectModel, or TerrainModel: A representation
        of the box.  If a world is given, then either a RigidObjectModel
        or TerrainModel is added to the world and returned.
    """
    if center is None:
        center = [0, 0, 0]
    prim = GeometricPrimitive()
    prim.setAABB([
        center[0] - width * 0.5, center[1] - depth * 0.5,
        center[2] - height * 0.5
    ], [
        center[0] + width * 0.5, center[1] + depth * 0.5,
        center[2] + height * 0.5
    ])
    geom = Geometry3D(prim)
    if type != 'GeometricPrimitive':
        geom = geom.convert(type)
    if world is None:
        if R is not None and t is not None:
            geom.setCurrentTransform(R, t)
        return geom

    #want a RigidObjectModel or TerrainModel
    if name is None:
        name = 'box'
    if mass != float('inf'):
        bmass = Mass()
        bmass.setMass(mass)
        bmass.setCom(center)
        bmass.setInertia([
            mass * (depth**2 + height**2) / 12,
            mass * (width**2 + height**2) / 12,
            mass * (width**2 + height**2) / 12
        ])
        robj = world.makeRigidObject(name)
        robj.geometry().set(geom)
        robj.setMass(bmass)
        if R is not None and t is not None:
            robj.setTransform(R, t)
        return robj
    else:
        tobj = world.makeTerrain(name)
        if R is not None and t is not None:
            geom.transform(R, t)
        tobj.geometry().set(geom)
        return tobj
Exemple #23
0
def sphere(radius,
           center=None,
           R=None,
           t=None,
           world=None,
           name=None,
           mass=float('inf'),
           type='TriangleMesh'):
    """Makes a sphere with the given radius

    Args:
        radius (float): radius of the sphere
        center (list of 3 floats, optional): if None (typical), the *geometry*
            of the sphere is centered at 0. Otherwise, the *geometry* of
            the sphere is shifted relative to the sphere's local coordinate system.
        R,t (se3 transform, optional): if given, the sphere's world coordinates
            will be rotated and shifted by this transform.
        world (WorldModel, optional): If given, then the sphere will be a
            RigidObjectModel or TerrainModel will be created in this world
        name (str, optional): If world is given, this is the name of the object. 
            Default is 'sphere'.
        mass (float, optional): If world is given and this is inf, then a
            TerrainModel will be created. Otherwise, a RigidObjectModel
            will be created with automatically determined inertia.
        type (str, optional): the geometry type.  Defaults to 'TriangleMesh',
            but also 'GeometricPrimitive' and 'VolumeGrid' are accepted.

    Returns:
        Geometry3D, RigidObjectModel, or TerrainModel: A representation
        of the sphere.  If a world is given, then either a RigidObjectModel
        or TerrainModel is added to the world and returned.
    """
    if center is None:
        center = [0, 0, 0]
    prim = GeometricPrimitive()
    prim.setSphere(center, radius)
    geom = Geometry3D(prim)
    if type != 'GeometricPrimitive':
        geom = geom.convert(type)
    if world is None:
        if R is not None and t is not None:
            geom.setCurrentTransform(R, t)
        return geom

    #want a RigidObjectModel or TerrainModel
    if name is None:
        name = 'sphere'
    if mass != float('inf'):
        bmass = Mass()
        bmass.setMass(mass)
        bmass.setCom(center)
        bmass.setInertia([0.4 * mass * radius**2] * 3)
        robj = world.makeRigidObject(name)
        robj.geometry().set(geom)
        robj.setMass(bmass)
        if R is not None and t is not None:
            robj.setTransform(R, t)
        return robj
    else:
        tobj = world.makeTerrain(name)
        if R is not None and t is not None:
            geom.transform(R, t)
        tobj.geometry().set(geom)
        return tobj
Exemple #24
0
 def loadGeom(self,fn):
     """Loads a nonconvex volume from a Klamp't readable mesh (must be watertight)"""
     g = Geometry3D()
     g.loadFile(fn)
     self.setGeom(g)
Exemple #25
0
                robot.setConfig(orig_config)

    return reachable

w = WorldModel()
w.readFile("../data/robots/kinova_gen3_7dof.urdf")
w.readFile("../data/terrains/plane.env")
robot = w.robot(0)
obstacles = [w.terrain(0)]

ee_link = 'EndEffector_Link'
ee_local_pos = (0.15,0,0)
ee_local_axis = (1,0,0)

#put a "pen" geometry on the end effector
gpen = Geometry3D()
res = gpen.loadFile("../data/objects/cylinder.off")
assert res
gpen.scale(0.01,0.01,0.15)
gpen.rotate(so3.rotation((0,1,0),math.pi/2))
robot.link(7).geometry().setCurrentTransform(*se3.identity())
gpen.transform(*robot.link(8).getParentTransform())
robot.link(7).geometry().set(merge_geometry.merge_triangle_meshes(gpen,robot.link(7).geometry()))
robot.setConfig(robot.getConfig())

def show_workspace(grid):
    vis.add("world",w)
    res = numpy_convert.from_numpy((lower_corner,upper_corner,grid),'VolumeGrid')
    g_workspace = Geometry3D(res)
    g_surface = g_workspace.convert('TriangleMesh',0.5)
    if g_surface.numElements() != 0:
Exemple #26
0
 def add_to_vis(self,robot=None,animate=True,base_xform=None):
     """Adds the gripper to the klampt.vis scene."""
     from klampt import vis
     from klampt import WorldModel,Geometry3D,GeometricPrimitive
     from klampt.model.trajectory import Trajectory
     prefix = "gripper_"+self.name
     if robot is None and self.klampt_model is not None:
         w = WorldModel()
         if w.readFile(self.klampt_model):
             robot = w.robot(0)
             vis.add(prefix+"_gripper",w)
             robotPath = (prefix+"_gripper",robot.getName())
     elif robot is not None:
         vis.add(prefix+"_gripper",robot)
         robotPath = prefix+"_gripper"
     if robot is not None:
         assert self.base_link >= 0 and self.base_link < robot.numLinks()
         robot.link(self.base_link).appearance().setColor(1,0.75,0.5)
         if base_xform is None:
             base_xform = robot.link(self.base_link).getTransform()
         else:
             if robot.link(self.base_link).getParent() >= 0:
                 print("Warning, setting base link transform for an attached gripper base")
             #robot.link(self.base_link).setParent(-1)
             robot.link(self.base_link).setParentTransform(*base_xform)
             robot.setConfig(robot.getConfig())
         for l in self.finger_links:
             assert l >= 0 and l < robot.numLinks()
             robot.link(l).appearance().setColor(1,1,0.5)
     if robot is not None and animate:
         q0 = robot.getConfig()
         for i in self.finger_drivers:
             if isinstance(i,(list,tuple)):
                 for j in i:
                     robot.driver(j).setValue(1)
             else:
                 robot.driver(i).setValue(1)
         traj = Trajectory([0],[robot.getConfig()])
         for i in self.finger_drivers:
             if isinstance(i,(list,tuple)):
                 for j in i:
                     robot.driver(j).setValue(0)
                     traj.times.append(traj.endTime()+0.5)
                     traj.milestones.append(robot.getConfig())
             else:
                 robot.driver(i).setValue(0)
                 traj.times.append(traj.endTime()+1)
                 traj.milestones.append(robot.getConfig())
         traj.times.append(traj.endTime()+1)
         traj.milestones.append(traj.milestones[0])
         traj.times.append(traj.endTime()+1)
         traj.milestones.append(traj.milestones[0])
         assert len(traj.times) == len(traj.milestones)
         traj.checkValid()
         vis.animate(robotPath,traj)
         robot.setConfig(q0)
     if self.center is not None:
         vis.add(prefix+"_center",se3.apply(base_xform,self.center))
     center_point = (0,0,0) if self.center is None else self.center
     outer_point = (0,0,0)
     if self.primary_axis is not None:
         length = 0.1 if self.finger_length is None else self.finger_length
         outer_point = vectorops.madd(self.center,self.primary_axis,length)
         line = Trajectory([0,1],[self.center,outer_point])
         line.milestones = [se3.apply(base_xform,m) for m in line.milestones]
         vis.add(prefix+"_primary",line,color=(1,0,0,1))
     if self.secondary_axis is not None:
         width = 0.1 if self.maximum_span is None else self.maximum_span
         line = Trajectory([0,1],[vectorops.madd(outer_point,self.secondary_axis,-0.5*width),vectorops.madd(outer_point,self.secondary_axis,0.5*width)])
         line.milestones = [se3.apply(base_xform,m) for m in line.milestones]
         vis.add(prefix+"_secondary",line,color=(0,1,0,1))
     elif self.maximum_span is not None:
         #assume vacuum gripper?
         p = GeometricPrimitive()
         p.setSphere(outer_point,self.maximum_span)
         g = Geometry3D()
         g.set(p)
         vis.add(prefix+"_opening",g,color=(0,1,0,0.25))
prim.setSegment((0.05, 0.2, 0.0), (0.05, 0.2, 0.1))
point.geometry().setGeometricPrimitive(prim)
point.appearance().setColor(random.uniform(0., 1.), random.uniform(0., 1.),
                            random.uniform(0., 1.), 1.)

#example AABB
aabb = world.makeRigidObject("AABB")
prim = GeometricPrimitive()
prim.setAABB((0., 0.3, 0.), (0.1, 0.4, 0.1))
aabb.geometry().setGeometricPrimitive(prim)
aabb.appearance().setColor(random.uniform(0., 1.), random.uniform(0., 1.),
                           random.uniform(0., 1.), 0.5)

#example TriangleMesh
ladder = world.makeTerrain("TriangleMesh")
mesh = Geometry3D()
mesh.loadFile("../../data/terrains/drc_ladder.off")
mesh.transform([.033, 0, 0, 0, .033, 0, 0, 0, .033], [0.05, 0.5, 0])
ladder.geometry().set(mesh)
ladder.appearance().setColor(random.uniform(0., 1.), random.uniform(0., 1.),
                             random.uniform(0., 1.), 1.)

#example Group
ladders = world.makeTerrain("Group")
ladders_geom = Geometry3D()
ladders_geom.setGroup()
for d in range(4):
    mesh = Geometry3D()
    mesh.loadFile("../../data/terrains/drc_ladder.off")
    mesh.transform(so3.from_axis_angle(([0, 0, 1], math.pi / 2 * d)),
                   [0, 0, 0])