def __init__(self): # create dancer body = new.cone(name='body',r1=0.2, r2=0.2, h=1.5) body.translate(z=0.75) body.scale((0.5, 1, 1)) body.apply_matrix() head = new.cone(name='head', r1=0.2, r2=0, h=0.3) head.rotate((0.,90.,0.)) head.translate(x=0.1) head.apply_matrix() head.translate(z=1.6) self.gp = [] self.gp.append(body.show_frame()) self.gp.append(head.show_frame()) # create markers m1 = new.sphere(name='m1', r=0.05) self.m1_pos = trf.PointCloud((-0.1, 0, 1)) # both body frame and world frame self.body = body self.head = head self.m1 = m1 self.screen = new.empty() self.screen.frame = self.head.frame self.screen.translate((1, 0, -0.3)) self.m1viz = new.sphere(name='m1viz', r=0.08) self._update_m1()
def handler1(): """Event handler example for manipulating one object based on the status of another.""" s1 = new.sphere('sph1', coll_name='handler') s2 = new.sphere('sph2', coll_name='handler') def receiver(x): # pylint: disable=unused-argument # event receiver functions need one input argument s2.show_frame() # when s1 changes location, show s2's frame pn.add_handler(s1, 'loc', receiver, 'post') s2.loc = (0, 2, 0) s1.loc = (0, -2, 0)
def handler2(): """Event handler demonstration to create a simple projection""" def receiver_func(self): # self is s1 if a handler is imposed on s1 s2.loc = (self.loc[0], self.loc[1], 0) # projection on the XY plane s1 = new.sphere('sph1', r=0.4) s2 = new.sphere('sph2', r=0.7) s1.add_handler('loc', receiver_func) s1.loc = (0, 0, 0) n_frames = 25 for kc in range(1, n_frames): s1.loc = (np.sin(kc * 2 * np.pi / n_frames), kc * 2 * np.pi / n_frames, 2 * np.cos(kc * 2 * np.pi / n_frames)) s1.key(kc, 'l') s2.key(kc, 'l') env.Key().auto_lim()
def spheres(): """ Demonstration for animating a sphere using blender's functions. """ # Animation with blender's keyframe_insert s1 = new.sphere(obj_name='sphere1', msh_name='sph', coll_name='Spheres') frameID = [1, 50, 100] loc = [(1, 1, 1), (1, 2, 1), (2, 2, 1)] attrs = ['location', 'rotation_euler', 'scale'] for thisFrame, thisLoc in zip(frameID, loc): bpy.context.scene.frame_set(thisFrame) for attr in attrs: setattr(s1(), attr, thisLoc) s1().keyframe_insert(data_path=attr, frame=thisFrame) # Animation with core.Object's 'key' function. s2 = new.sphere(name='sphere2', msh_name='sph', coll_name='Spheres') s2.key(1) s2.loc = (2, 2, 2) s2.key(26) s2.scl = (1, 0.2, 1) s2.key(51) s2.scl = (1, 2, 0.2) s2.key(76) # chaining absolute values (same as above) s3 = new.sphere(name='sphere3', msh_name='sph', coll_name='Spheres') s3.key(1, 's').key(26, 's', [(0.5, 0.5, 1)]).key(51, 's', [(1, 3, 0.3)]) # chaining transforms (relative) s4 = new.sphere(name='sphere4', msh_name='sph', coll_name='Spheres') s4.key(1).translate((0, 0, 2)).key(26).scale((1, 1, 0.3)).key(51).scale( (1, 1, 4)).key(101) env.Key().auto_lim() # coordinate frame display s5 = new.sphere('sphere5', msh_name='sph', coll_name='Spheres') s5.show_frame('sphere5_CoordFrame', coll_name='Spheres') s5.loc = (-2, -2, -1) s5.rotate((30, 90, 0)) s5.show_frame()
def spiral(): """ Animating along a path with a few lines of code. """ sp = new.spiral(name='spiral') sp.rotate((0, 30, 0)) s = new.sphere(name='sphere', r=0.3, u=4, v=2) s.key(1, 'l') for idx, loc in enumerate(list(sp.pts.in_world().co)): s.key(idx + 2, 'l', [tuple(loc)])
def zoo(): """ Create a zoo of primitives. """ new.sphere(obj_name='sph30', msh_name='sp30', r=0.7, u=3, v=2, coll_name='zoo') new.monkey(name='L', msh_name='M', coll_name='zoo') new.sphere(name='Sph', r=2, u=6, v=8, coll_name='zoo') new.cube(name='de', msh_name='e', size=0.4, coll_name='zoo') new.cone(name='mycone', segments=4, diameter1=2, diameter2=2, depth=2 * np.sqrt(2), cap_ends=True, cap_tris=False, coll_name='zoo') new.cone(name='mycone1', coll_name='zoo') new.cone(name='mycone2', seg=3, d=1, coll_name='zoo') new.cone(name='mycone3', seg=3, r1=3, r2=2, d=0, cap_ends=False, coll_name='zoo') new.polygon(name='hex', seg=6, coll_name='zoo') new.ngon('circle', n=32, r=1, coll_name='zoo') new.polygon(name='hex', seg=6, coll_name='zoo') for obj in bpy.data.collections['zoo'].objects: utils.enhance(obj).translate(np.random.randint(-6, 6, 3))
def draw_atom(): """Electron clouds-like structure.""" a = turtle.Draw('cloud', coll_name='atom') a.ngon(n=2, r=0.1) for vert in a.bm.verts[:]: vert.co += mathutils.Vector((0., -1., 0)) a.spin(angle=np.pi, steps=24, axis='x', cent=(0., 0., 0.)) a.spin(angle=2 * np.pi, steps=6, axis='y', cent=(0., 0., 0.), geom=turtle.Geom(a.bm).all, use_duplicate=True) cloud = +a cloud.scale((1, 0.6, 1)) nucleus = new.sphere('nucleus', r=0.2, coll_name='atom') return (nucleus, cloud)
def plane_slice(): """ Using the plane slicer to 'sculpt' simple objects. """ r = 1 n = 4 sph = new.sphere(name='sphere', r=r) subtended_angle = 2 * np.pi / n trans = r * np.cos(subtended_angle / 2) sph.translate(z=trans) for _ in range(n - 1): sph.slice_z().rotate(np.degrees((subtended_angle, 0, 0))) len_z = np.max(sph.v[:, -1]) - np.min(sph.v[:, -1]) sph.translate(z=-0.8 * len_z) sph.slice_z(slice_dir='pos') len_z = np.max(sph.v[:, -1]) - np.min(sph.v[:, -1]) sph.translate(z=len_z) sph.morph(frame_start=151) #pylint:disable=no-member return sph
def spiral2(): """ Animating along a path, with internal rotation. Demonstrates the use of Quaternions for rotation. """ sp = new.spiral('spiral', n_rot=6) sp.scl = (0.5, 1, 1) sp.frame = trf.Quat([1, 0, 0], np.pi / 6) * sp.frame s = new.sphere('sph', u=4, v=3) s.show_frame() # this one is just to create the gp object s.key(1) sp_pts = sp.pts.in_world().co for frame_number in range(0, np.shape(sp.pts.co)[0]): s.loc = sp_pts[frame_number, :] s.frame = trf.Quat([0, 0, 1], 5 * np.pi / 180, origin=s.loc) * s.frame s.frame_gp.keyframe = frame_number + 1 s.show_frame() s.key(frame_number + 1) env.Key().auto_lim()
def tongue(poly_smooth=True): """ Morph should look like a tongue in one direction, and an alien helmet in another. During this, I learned that vertices should always be selected in an interval (it can be with a small epsilon), but exact values don't seem to work. """ sph = new.sphere(name='tongue') sph.slice_x().slice_y().slice_z() eps = 0.002 v = sph.v sel = np.logical_and.reduce( (v[:, 0] > -eps, v[:, 0] < eps, v[:, 1] > -eps, v[:, 1] < eps)) #pylint: disable=no-member v[sel, 0:2] = v[sel, 0:2] - 0.2 sph.v = v sph.morph(n_frames=25, frame_start=100) #pylint:disable=no-member env.Key().goto(125) sph.subsurf(2, 2) if poly_smooth: sph.shade('smooth') #pylint:disable=no-member else: sph.shade('flat') #pylint:disable=no-member return sph
def capsule(): """Capsule for saving to URDF""" import os name = "capsule01" rel_dir_name = "robots" sav_dir = str(Path(utils.PATH["cache"]).parent.joinpath(rel_dir_name)) sav_file = ''.join([sav_dir, os.sep, name]) # create the capsule using the bpn.new module r = 0.25 h = 2 s1 = new.sphere(name, r=r, v=9) tmp1 = s1.v # elongate the lower half tmp1[tmp1[:, -1] < -0.001, -1] = tmp1[tmp1[:, -1] < -0.001, -1] - (h - 2 * r) s1.v = tmp1 s1.vertex_center = np.array([0, 0, 0]) # save STL file # Note that the STL file does not 'bake' the pose information in # Specify that info in the URDF file (3 times - for inertia, visuals and collisions) s1.export(sav_file + ".stl") # pose, mass, inertia tensor, mesh file name -> URDF file import urdfpy as u def make_link(link_name, mesh_name, mesh, density, pose, scale=None): if scale is None: scale = [1, 1, 1] mesh.density = density geometry = u.Geometry( mesh=u.Mesh(mesh_name, meshes=[mesh], scale=scale)) inertia = u.Inertial(mesh.mass, mesh.moment_inertia, pose) visuals = [u.Visual(geometry, origin=pose)] collisions = [u.Collision(link_name + "_coll", pose, geometry)] return u.Link(link_name, inertia, visuals, collisions) import trimesh st = trimesh.load_mesh(sav_file + ".stl") links = [] # For the first link, create a transformation matrix as you would in blender s1.frame = trf.CoordFrame(origin=[0, 0, -0.5 * (h + r)]) s1.frame = trf.Quat([1, 0, 0], np.pi / 4, trf.CoordFrame()) * s1.frame links.append(make_link("left", name + ".stl", st, 10, s1.frame.m)) # create the joint before creating the second link! j2 = new.empty("left_right") j2.frame = trf.Quat([1, 0, 0], -np.pi / 4, j2.frame) * j2.frame # the second link (child in joint 2) will have its coordinate frame defined in j2 s2 = s1.deepcopy() s2.frame = trf.CoordFrame(origin=[0, 0, -0.5 * (h + r)]) links.append( make_link("right", name + ".stl", st, 1, s2.frame.m, [1, 1, 1])) joints = [ u.Joint("left_right", "continuous", "left", "right", axis=[1, 0, 0], origin=j2.frame.m) ] r = u.URDF(name, links, joints) r.save(sav_file + ".urdf") # add friction and restitution information to the URDF file from lxml import etree tree = etree.parse(sav_file + ".urdf", etree.XMLParser(remove_blank_text=True)) root = tree.getroot() for link in root: if link.tag == 'link': contact = etree.SubElement(link, "contact") etree.SubElement(contact, "restitution").set("value", "1.0") etree.SubElement(contact, "rolling_friction").set("value", "0.001") etree.SubElement(contact, "spinning_friction").set("value", "0.001") f = open(sav_file + ".urdf", "w") f.write( etree.tostring(root, pretty_print=True, xml_declaration=True).decode("utf-8")) f.close()