1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 from copy import deepcopy
29 from math import fabs
30
31 import rospy
32
33 from std_msgs.msg import (
34 Bool
35 )
36
37 import baxter_dataflow
38
39 from baxter_core_msgs.msg import (
40 HeadPanCommand,
41 HeadState,
42 )
43 from baxter_interface import settings
44
45
47 """
48 Interface class for the head on the Baxter Robot.
49
50 Used to control the head pan angle and to enable/disable the head nod
51 action.
52 """
54 """
55 Constructor.
56 """
57 self._state = dict()
58
59 self._pub_pan = rospy.Publisher(
60 '/robot/head/command_head_pan',
61 HeadPanCommand,
62 queue_size=10)
63
64 self._pub_nod = rospy.Publisher(
65 '/robot/head/command_head_nod',
66 Bool,
67 queue_size=10)
68
69 state_topic = '/robot/head/head_state'
70 self._sub_state = rospy.Subscriber(
71 state_topic,
72 HeadState,
73 self._on_head_state)
74
75 baxter_dataflow.wait_for(
76 lambda: len(self._state) != 0,
77 timeout=5.0,
78 timeout_msg=("Failed to get current head state from %s" %
79 (state_topic,)),
80 )
81
83 self._state['pan'] = msg.pan
84 self._state['panning'] = msg.isPanning
85 self._state['nodding'] = msg.isNodding
86
88 """
89 Get the current pan angle of the head.
90
91 @rtype: float
92 @return: current angle in radians
93 """
94 return self._state['pan']
95
97 """
98 Check if the head is currently nodding.
99
100 @rtype: bool
101 @return: True if the head is currently nodding, False otherwise.
102 """
103 return self._state['nodding']
104
106 """
107 Check if the head is currently panning.
108
109 @rtype: bool
110 @return: True if the head is currently panning, False otherwise.
111 """
112 return self._state['panning']
113
114 - def set_pan(self, angle, speed=100, timeout=10.0):
115 """
116 Pan at the given speed to the desired angle.
117
118 @type angle: float
119 @param angle: Desired pan angle in radians.
120 @type speed: int
121 @param speed: Desired speed to pan at, range is 0-100 [100]
122 @type timeout: float
123 @param timeout: Seconds to wait for the head to pan to the
124 specified angle. If 0, just command once and
125 return. [10]
126 """
127 msg = HeadPanCommand(angle, speed)
128 self._pub_pan.publish(msg)
129
130 if not timeout == 0:
131 baxter_dataflow.wait_for(
132 lambda: (abs(self.pan() - angle) <=
133 settings.HEAD_PAN_ANGLE_TOLERANCE),
134 timeout=timeout,
135 rate=100,
136 timeout_msg="Failed to move head to pan command %f" % angle,
137 body=lambda: self._pub_pan.publish(msg)
138 )
139
141 """
142 Command the head to nod once.
143
144 @type timeout: float
145 @param timeout: Seconds to wait for the head to nod.
146 If 0, just command once and return. [0]
147 """
148 self._pub_nod.publish(True)
149
150 if not timeout == 0:
151
152 baxter_dataflow.wait_for(
153 test=self.nodding,
154 timeout=timeout,
155 rate=100,
156 timeout_msg="Failed to initiate head nod command",
157 body=lambda: self._pub_nod.publish(True)
158 )
159
160
161 baxter_dataflow.wait_for(
162 test=lambda: not self.nodding(),
163 timeout=timeout,
164 rate=100,
165 timeout_msg="Failed to complete head nod command",
166 body=lambda: self._pub_nod.publish(False)
167 )
168