Source code for klampt.io.html

from klampt import *
from klampt.model import trajectory
from klampt import robotsim
import json

_title_id = '__TITLE__'
_scene_id = '__SCENE_JSON__'
_path_id = '__PATH_JSON__'
_rpc_id = '__RPC_JSON__'
_compressed_id = '__COMPRESSED__'
_dt_id = '__TIMESTEP__'

[docs]def make_fixed_precision(obj,digits): if isinstance(obj,float): return round(obj,digits) elif isinstance(obj,list): for i in xrange(len(obj)): obj[i] = make_fixed_precision(obj[i],digits) elif isinstance(obj,tuple): return [make_fixed_precision(val,digits) for val in obj] elif isinstance(obj,dict): for i,v in obj.iteritems(): obj[i] = make_fixed_precision(v,digits) return obj
[docs]class HTMLSharePath: """An exporter that converts animations to shareable HTML files. Examples:: sharer = HTMLSharePath("mypath.html",name="My spiffy path") sharer.start(sim) #or world while [simulation is running]: #do whatever control you wish to do here sim.simulate(...) sharer.animate() sharer.end() #this saves to the given filename """ def __init__(self,filename="path.html",name="Klamp't Three.js app",boilerplate='auto'): """ Args: filename (str): the HTML file to generate name (str): the title of the HTML page boilerplate (str): the location of the boilerplate HTML file. If 'auto', it's automatically found in the ``klampt/data`` folder. """ self.name = name if boilerplate == 'auto': import pkg_resources boilerplate = pkg_resources.resource_filename('klampt','data/share_path_boilerplate.html') f = open(boilerplate,'r') self.boilerplate_file = ''.join(f.readlines()) f.close() if any(v not in self.boilerplate_file for v in [_title_id,_scene_id,_path_id,_rpc_id,_compressed_id,_dt_id]): raise RuntimeError("Boilerplate file does not contain the right tags") self.fn = filename self.scene = [] self.transforms = {} self.rpc = [] self.dt = 0 self.last_t = 0
[docs] def start(self,world): """Begins the path saving with the given WorldModel or Simulator""" if isinstance(world,Simulator): self.sim = world self.world = world.world self.last_t = world.getTime() else: self.sim = None self.world = world self.scene = robotsim.ThreeJSGetScene(self.world)
[docs] def animate(self,time=None): """Updates the path from the world. If the world wasn't a simulator, the time argument needs to be provided""" if self.sim != None and time == None: time = self.sim.getTime() self.sim.updateWorld() dt = time - self.last_t if self.dt == 0: self.dt = dt if self.dt == 0: return if abs(dt - self.dt) <= 1e-6: dt = self.dt numadd = 0 while dt >= self.dt: numadd += 1 transforms = json.loads(robotsim.ThreeJSGetTransforms(self.world)) for update in transforms['object']: n = update['name'] mat = make_fixed_precision(update['matrix'],4) matpath = self.transforms.setdefault(n,[]) assert len(matpath) == len(self.rpc) lastmat = None for m in matpath[::-1]: if m != None: lastmat = m break if lastmat != mat: matpath.append(mat) else: matpath.append(None) self.rpc.append('null') dt -= self.dt self.last_t += self.dt if numadd > 1: print "Uneven time spacing, duplicating frame",numadd,"times"
[docs] def end(self): data = self.boilerplate_file.replace(_title_id,self.name) data = data.replace(_scene_id,self.scene) data = data.replace(_path_id,json.dumps(self.transforms)) data = data.replace(_rpc_id,'['+','.join(self.rpc)+']') data = data.replace(_compressed_id,'true') data = data.replace(_dt_id,str(self.dt)) print "Path with",len(self.rpc),"frames saved to",self.fn f = open(self.fn,'w') f.write(data) f.close()
if __name__ == '__main__': import sys import os from klampt import trajectory world = WorldModel() if len(sys.argv) == 1: world.readFile("../../data/athlete_plane.xml") q = world.robot(0).getConfig() q[2] = 2 world.robot(0).setConfig(q) sim = Simulator(world) share = HTMLSharePath(name="Klamp't simulation path") share.start(sim) for i in range(100): sim.simulate(0.02) share.animate() share.end() else: assert len(sys.argv) == 3,"Usage: sharepath.py world.xml robot_path" world.readFile(sys.argv[1]) traj = trajectory.RobotTrajectory(world.robot(0)) traj.load(sys.argv[2]) world.robot(0).setConfig(traj.milestones[0]) dt = 0.02 excess = 1.0 share = HTMLSharePath(name="Klamp't path "+os.path.split(sys.argv[2])[1]) share.start(world) share.dt = dt t = traj.times[0] while t < traj.times[-1] + excess: world.robot(0).setConfig(traj.eval(t)) share.animate(t) t += dt share.end()