import logging; logger = logging.getLogger("morsebuilder." + __name__)
from morse.builder.creator import ComponentCreator, ActuatorCreator
from morse.builder.blenderobjects import *
from morse.core.exceptions import MorseBuilderError
[docs]class Arucomarker(ActuatorCreator):
_classpath = "morse.actuators.arucomarker.Arucomarker"
_blendname = "arucomarker"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.append_meshes(['white_plane', 'arplane', 'arplane.back'])
[docs]class Destination(ActuatorCreator):
_classpath = "morse.actuators.destination.Destination"
[docs]class ForceTorque(ActuatorCreator):
_classpath = "morse.actuators.force_torque.ForceTorque"
[docs]class MocapControl(ActuatorCreator):
_classpath = "morse.actuators.mocap_control.MocapControl"
# Gripper uses Actuator from morse.builder
[docs]class Gripper(ActuatorCreator):
_classpath = "morse.actuators.gripper.Gripper"
_blendname = "gripper"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name,
action = ActuatorCreator.USE_BLEND,
make_morseable = False)
self.properties(Angle = 60.0, Distance = 0.5)
[docs] def properties(self, **kwargs):
radar = self._bpy_object.game.sensors["Radar"]
if 'Angle' in kwargs:
radar.angle = kwargs['Angle']
if 'Distance' in kwargs:
radar.distance = kwargs['Distance']
ActuatorCreator.properties(self, **kwargs)
[docs]class Keyboard(ActuatorCreator):
_classpath = "morse.actuators.keyboard.Keyboard"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.mark_unexportable()
[docs]class Joystick(ActuatorCreator):
_classpath = "morse.actuators.joystick.Joystick"
def __init__(self, name=None, index=0):
""" Create a new Joystick controller
:param index: Which joystick to use
:type index: int in [0, 7], default 0
"""
ActuatorCreator.__init__(self, name)
self.mark_unexportable()
obj = bpymorse.get_context_object()
# replace Always sensor by Joystick sensor
sensor = obj.game.sensors[-1]
sensor.type = 'JOYSTICK'
# need to get the new Joystick Sensor object
sensor = obj.game.sensors[-1]
sensor.use_pulse_true_level = True
sensor.joystick_index = index
sensor.event_type = 'AXIS'
sensor.use_all_events = True
[docs]class Orientation(ActuatorCreator):
_classpath = "morse.actuators.orientation.Orientation"
[docs]class PA10(ActuatorCreator):
_classpath = "morse.actuators.pa_10.PA10"
_blendname = "pa_10"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name,
action = ComponentCreator.USE_BLEND,
make_morseable = False)
self.properties(Speed = 1.0)
[docs]class PTU(ActuatorCreator):
_classpath = "morse.actuators.ptu.PTU"
_blendname = "ptu"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.properties(Speed = 1.0, Manual = False, Tolerance = 0.01)
# append PanBase with its logic
self.append_meshes(['PanBase', 'TiltBase'])
[docs]class RotorcraftAttitude(ActuatorCreator):
_classpath = "morse.actuators.rotorcraft_attitude.RotorcraftAttitude"
[docs]class RotorcraftVelocity(ActuatorCreator):
_classpath = "morse.actuators.rotorcraft_velocity.RotorcraftVelocity"
[docs]class RotorcraftWaypoint(ActuatorCreator):
_classpath = "morse.actuators.rotorcraft_waypoint.RotorcraftWaypoint"
[docs]class StabilizedQuadrotor(ActuatorCreator):
_classpath = "morse.actuators.stabilized_quadrotor.StabilizedQuadrotor"
[docs]class SteerForce(ActuatorCreator):
_classpath = "morse.actuators.steer_force.SteerForce"
[docs]class Teleport(ActuatorCreator):
_classpath = "morse.actuators.teleport.Teleport"
[docs]class MotionVW(ActuatorCreator):
_classpath = "morse.actuators.v_omega.MotionVW"
[docs]class MotionVWDiff(ActuatorCreator):
_classpath = "morse.actuators.v_omega_diff_drive.MotionVWDiff"
[docs]class Waypoint(ActuatorCreator):
_classpath = "morse.actuators.waypoint.Waypoint"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.properties(Target = "")
# append 2 Radar with logic
self.add_lr_radars()
[docs] def add_lr_radars(self):
self.add_radar('Radar.L', 'Lcollision', +1)
self.add_radar('Radar.R', 'Rcollision', -1)
[docs] def add_radar(self, name, collision, fact):
bpymorse.deselect_all()
bpymorse.add_object(type='EMPTY')
# bpymorse.add_empty(type='ARROWS')
obj = bpymorse.get_context_object()
obj.name = name
obj.location = (0.7, fact*0.4, 0.8)
obj.parent = self._bpy_object
bpymorse.new_game_property(type='BOOL', name=collision)
prop = obj.game.properties[-1]
prop.value = False
bpymorse.add_sensor(type="RADAR")
sensor = obj.game.sensors[-1]
sensor.angle = 5.0
sensor.distance = 3.0
sensor.axis = 'XAXIS'
sensor.use_pulse_true_level = True
self._set_sensor_frequency(sensor, 20)
self.radar_set_collision(obj, sensor, 'LOGIC_AND', collision, True)
self.radar_set_collision(obj, sensor, 'LOGIC_NAND', collision, False)
[docs] def radar_set_collision(self, obj, sensor, controller_type, collision, value):
bpymorse.add_controller(type=controller_type)
controller = obj.game.controllers[-1]
bpymorse.add_actuator(type='PROPERTY')
actuator = obj.game.actuators[-1]
actuator.mode = 'TOGGLE'
actuator.property = collision
actuator.mode = 'ASSIGN'
actuator.value = str(value)
controller.link(sensor = sensor, actuator = actuator)
[docs]class MotionXYW(ActuatorCreator):
_classpath = "morse.actuators.xy_omega.MotionXYW"
[docs]class Light(ActuatorCreator):
_classpath = "morse.actuators.light.Light"
def __init__(self, name=None):
self.light = None
ActuatorCreator.__init__(self, name)
self.light = Spot("LightSpot")
self.append(self.light)
self.properties(Emit=True)
[docs] def properties(self, **kwargs):
ActuatorCreator.properties(self, **kwargs)
if self.light:
spot = self.light._bpy_object.data
if spot.type == 'SPOT':
if "size" in kwargs.keys():
spot.spot_size = kwargs['size']
if "distance" in kwargs.keys():
spot.distance = kwargs['distance']
if "color" in kwargs.keys():
import re
spot.color = tuple(int(v) for v in re.findall("[0-9]+", kwargs['color']))
[docs]class Sound(ActuatorCreator):
_classpath = "morse.actuators.sound.Sound"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.properties(mode="play")
#self.select()
bpymorse.add_actuator(type="SOUND", name="MORSE_SOUND")
actuator = self._bpy_object.game.actuators[-1]
controller = self._bpy_object.game.controllers[-1]
controller.link(actuator=actuator)
[docs] def open(self, filepath):
# just to raise a FileNotFoundError
open(filepath).close()
actuator = self._bpy_object.game.actuators[-1]
#if bpy.ops.sound.open.poll():
bpymorse.open_sound(filepath=filepath)
actuator.sound = bpymorse.get_last_sound()
actuator.use_sound_3d = True
actuator.distance_3d_max = 10000.0
[docs]class Armature(ActuatorCreator):
_classpath = "morse.actuators.armature.Armature"
def __init__(self, name = None, armature_name = None, model_name = None):
""" Initialize an armature
Either `armature_name` or `model_name` or both must be specified.
:param armature_name: Armature object name
:param model_name: Armature model name, if any
"""
if not armature_name and not model_name:
raise MorseBuilderError("You need to specify either the name of " \
"an armature or a Blender model in order to create an " \
"armature actuator.")
if model_name:
ActuatorCreator.__init__(self,
name,
action = ComponentCreator.USE_BLEND,
blendfile = model_name,
blendobject = armature_name,
make_morseable = True)
else:
ActuatorCreator.__init__(self,
name,
action = ComponentCreator.LINK_EXISTING_OBJECT,
blendobject = armature_name,
make_morseable = True)
self.ik_targets = []
# the user may have created IK constraints on the armature, without
# setting an IK target. In that case, we add such a target
for bone in self._bpy_object.pose.bones:
for c in bone.constraints:
if c.type == 'IK' and c.ik_type == 'DISTANCE':
if not c.target:
self.create_ik_targets([bone.name])
def _get_posebone(self, bone_name):
""" Returns a given PoseBone in the armature.
If the joint does not exist, throw an exception.
"""
armature = self._bpy_object
if bone_name not in [c.name for c in armature.pose.bones]:
msg = "Joint <%s> does not exist in model %s." % (bone_name, armature.name)
msg += " Did you add a skeleton to your model in MakeHuman?"
raise MorseBuilderError(msg)
return armature.pose.bones[bone_name]
[docs] def create_ik_targets(self, bones):
# Bug with iTaSC! cf http://developer.blender.org/T37894
if bpymorse.version() < (2, 70, 0):
if self._bpy_object.pose.ik_solver == 'ITASC':
logger.warn("Due to a bug in Blender (T37894), only the standard " \
"IK solver can be used with IK targets. Switching " \
"from iTaSC to standard IK solver.")
self._bpy_object.pose.ik_solver = 'LEGACY'
for target in bones:
posebone = self._get_posebone(target)
bpymorse.add_morse_empty("ARROWS")
empty = bpymorse.get_first_selected_object()
empty.scale = [0.01, 0.01, 0.01]
empty.matrix_local = posebone.bone.matrix_local
empty.location = posebone.bone.tail_local
existing_ik = [c for c in posebone.constraints if c.type == 'IK']
if len(existing_ik) == 1:
ik_constraint = existing_ik[0]
elif existing_ik:
raise MorseBuilderError("Bone %s has several IK constraints." \
"MORSE supports only one IK constraint per bone. Please " \
"remove other ones.")
else:
ik_constraint = posebone.constraints.new("IK")
ik_constraint.ik_type = "DISTANCE"
ik_constraint.use_rotation = True
ik_constraint.use_tail = True
ik_constraint.target = empty
self.ik_targets.append((empty, target))
[docs] def after_renaming(self):
for empty, target in self.ik_targets:
empty.name = "ik_target." + self.name + "." + target
[docs]class KukaLWR(Armature):
"""
This actuator provides a KUKA LWR mesh with the associated kinematic chain.
An IK target is available on the last join, allowing for cartesian control of
the arm.
See :doc:`the general documentation on armatures <../actuators/armature>` for details.
"""
_name = "KUKA LWR"
_short_desc="7DoF KUKA Lightweight Robotic Arm (LWR)"
def __init__(self, name=None):
Armature.__init__(self, name, model_name = "kuka_lwr")
self.create_ik_targets(["kuka_7"])
[docs]class Drag(ActuatorCreator):
_classpath = "morse.actuators.drag.Drag"
def __init__(self, name=None):
ActuatorCreator.__init__(self, name)
self.mark_unexportable()
[docs]class ExternalForce(ActuatorCreator):
_classpath = "morse.actuators.external_force.ExternalForce"
[docs]class QuadrotorDynamicControl(ActuatorCreator):
_classpath = "morse.actuators.quadrotor_dynamic_control.QuadrotorDynamicControl"
# end morse.builder.actuators