Source code for sapien.utils.viewer.articulation_window

from .plugin import Plugin, copy_to_clipboard
from sapien import internal_renderer as R
import sapien


[docs] class ArticulationWindow(Plugin): def __init__(self): self.reset()
[docs] def reset(self): self.articulation = None self.ui_window = None
[docs] def close(self): self.reset()
@property def selected_entity(self): return self.viewer.selected_entity
[docs] def notify_selected_entity_change(self): articulation = None if self.selected_entity: for c in self.selected_entity.components: if isinstance(c, sapien.physx.PhysxArticulationLinkComponent): articulation = c.articulation self.articulation = articulation if articulation: self.joint_details = [False] * self.articulation.dof
[docs] def set_joint_details(self, index, v): self.joint_details[index] = v
[docs] def build(self): if self.viewer.render_scene is None: self.ui_window = None return self.ui_window = R.UIWindow().Label("Articulation") if not self.articulation: self.ui_window.append(R.UIDisplayText().Text("No articulation selected.")) return art = self.articulation self.ui_window.append( R.UIDisplayText().Text( "Name: {}".format(art.name if art.name else "(no name)") ), R.UIDisplayText().Text( "Base Link Entity Id: {}".format(art.root.entity.per_scene_id) ), ) uijoints = R.UISection().Label("Joints") joints = [] for j in art.joints: if j.dof > 0: joints.append(j) def wrapper(art, i, qpos): def callback(slider): qpos[i] = slider.value art.set_qpos(qpos) return callback qpos = art.get_qpos() for i, (q, j) in enumerate(zip(qpos, joints)): line = R.UISameLine() uijoints.append(line) line.append( R.UISliderFloat() .WidthRatio(0.5) .Id("joint_{}".format(i)) .Min(max(j.limit[0, 0], -20)) .Max(min(j.limit[0, 1], 20)) .Value(q) .Callback(wrapper(art, i, qpos)), ) if self.joint_details[i]: line.append( R.UIButton() .Label("-") .Id(str(i)) .Width(40) .Callback( (lambda i: lambda _: self.set_joint_details(i, False))(i) ), R.UIDisplayText().Text(j.name), ) uijoints.append( R.UISliderFloat() .Label("Position Target") .Id(str(i)) .WidthRatio(0.5) .Min(max(j.limit[0, 0], -20)) .Max(min(j.limit[0, 1], 20)) .Value(j.drive_target) .Callback((lambda j: lambda p: j.set_drive_target(p.value))(j)), R.UISliderFloat() .Label("Velocity Target") .Id(str(i)) .WidthRatio(0.5) .Min(-1) .Max(1) .Value(j.drive_velocity_target) .Callback( (lambda j: lambda p: j.set_drive_velocity_target(p.value))(j) ), R.UIInputFloat() .Label("Damping") .Id(str(i)) .WidthRatio(0.5) .Value(j.damping) .Callback( ( lambda j: lambda p: j.set_drive_property( j.stiffness, p.value, j.force_limit, j.drive_mode, ) )(j) ), R.UIInputFloat() .Label("Stiffness") .Id(str(i)) .WidthRatio(0.5) .Value(j.stiffness) .Callback( ( lambda j: lambda p: j.set_drive_property( p.value, j.damping, j.force_limit, j.drive_mode, ) )(j) ), R.UIInputFloat() .Label("Force Limit") .Id(str(i)) .WidthRatio(0.5) .Value(j.force_limit) .Callback( ( lambda j: lambda p: j.set_drive_property( j.stiffness, j.damping, p.value, j.drive_mode, ) )(j) ), R.UIInputFloat() .Label("Friction") .Id(str(i)) .WidthRatio(0.5) .Value(j.friction) .Callback((lambda j: lambda p: j.set_friction(p.value))(j)), R.UICheckbox() .Label("Acceleration") .Id(str(i)) .Checked(j.drive_mode == "acceleration") .Callback( ( lambda j: lambda p: j.set_drive_property( j.stiffness, j.damping, j.force_limit, "acceleration" if p.checked else "force", ) )(j) ), R.UIDummy().Height(20), ) else: line.append( R.UIButton() .Label("+") .Id(str(i)) .Width(40) .Callback((lambda i: lambda _: self.set_joint_details(i, True))(i)), R.UIDisplayText().Text(j.name), ) self.ui_window.append(uijoints) def wrapper(art): def wrapped(_): copy_to_clipboard(f"[{', '.join([str(x) for x in art.get_qpos()])}]") return wrapped self.ui_window.append( R.UIButton().Label("Copy Joint Positions").Callback(wrapper(art)) ) def wrapper(art, show): def show_link_collision(_): for plugin in self.viewer.plugins: if plugin.__class__.__name__ == "EntityWindow": for link in art.links: if show: plugin.enable_collision_visual(link.entity) else: plugin.disable_collision_visual(link.entity) return show_link_collision self.ui_window.append( R.UISameLine().append( R.UIButton().Label("Show").Callback(wrapper(art, True)), R.UIButton().Label("Hide").Callback(wrapper(art, False)), R.UIDisplayText().Text("Collision"), ), )
[docs] def get_ui_windows(self): self.build() if self.ui_window: return [self.ui_window] return []