1import logging; logger = logging.getLogger("morserobots." + __name__)
2from morse.builder import bpymorse
3from morse.builder import GroundRobot
4from morse.builder.actuators import Armature
5from morse.builder.sensors import ArmaturePose
6
7class Human(GroundRobot):
8    """ Append a human model to the scene.
9
10    Usage example:
11
12    .. code-block:: python
13
14       #! /usr/bin/env morseexec
15
16       from morse.builder import *
17
18       human = Human()
19       human.translate(x=5.5, y=-3.2, z=0.0)
20       human.rotate(z=-3.0)
21
22       human.skeleton.add_stream('pocolibs')
23
24    Currently, only one human per simulation is supported.
25
26    Detailed documentation
27    ----------------------
28
29    The MORSE human avatar is based on a 3D model generated from MakeHuman, and
30    stored in human_rig.blend.
31
32    The model is rigged with an armature (`human.skeleton`), used to control the
33    postures of the human and to deform accordingly the human mesh.
34
35    This armature is used by MORSE as both a :doc:`sensor to read and export
36    the human pose <../sensors/armature_pose>` and :doc:`an actuator
37    <../actuators/armature>` to modify the pose.
38
39    TODO: give code examples to read and modify the pose
40
41    The armature defines 5 particular points (**IK targets**) that can be
42    manipulated to control the human model in a simpler way: the head, the two
43    wrists and the two feet.
44
45    """
46
47    # list of human bones that we want to control via IK targets
48    IK_TARGETS = ["head", "wrist_L", "wrist_R", "foot_L", "foot_R"]
49
50    def __init__(self, filename='human_rig', name = None):
51        """
52        :param filename: the human model. Default: 'human_rig'
53        """
54        GroundRobot.__init__(self, filename, name)
55        self.properties(classpath = "morse.robots.human.Human")
56
57        self.skeleton = None
58
59        try:
60            self.skeleton = Armature(armature_name = self.get_child("HumanSkeleton").name)
61            self.append(self.skeleton)
62        except KeyError:
63            logger.error("Could not find the human armature! (I was looking " +\
64                         "for an object called 'HumanSkeleton' in the children " + \
65                         "objects of the human). I won't be able to export the " + \
66                         "human pose to any middleware.")
67
68        if self.skeleton:
69            self.skeleton.create_ik_targets(self.IK_TARGETS)
70            for t, name in self.skeleton.ik_targets:
71                t.parent = self._bpy_object
72
73            # Add an armature sensor. "joint_stateS" to match standard ROS spelling.
74            self.joint_states = ArmaturePose("joint_states")
75            self.skeleton.append(self.joint_states)
76
77
78    def add_interface(self, interface):
79        if interface == "socket":
80            self.joint_states.add_stream("socket")
81            self.joint_states.add_service("socket")
82            self.skeleton.add_service('socket')
83
84        elif interface == "ros":
85
86            self.joint_states.add_stream("ros")
87
88            self.skeleton.add_service("ros")
89            self.skeleton.add_overlay("ros",
90              "morse.middleware.ros.overlays.armatures.ArmatureController")
91
92        elif interface == "pocolibs":
93            self.skeleton.properties(classpath="morse.sensors.human_posture.HumanPosture")
94            self.add_stream(interface)
95
96