Skip to content

Commit 9a4190a

Browse files
committed
FEAT: Constrain the eye movement only a workspace boundary in the video frame. See description
The key improvements are: Eyes only move when face is within the central workspace area Full eye movement range is mapped to workspace boundaries Eyes stay centered when face is outside workspace This creates more natural movement that will integrate well with future neck movement
1 parent 7112511 commit 9a4190a

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

coffee_ws/src/coffee_expressions/coffee_expressions/plaipin_expressive_eyes.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,16 @@ def __init__(self):
4040
# The constraint for the values of the eye movement in the UI
4141
self.declare_parameter('eye_range', 1.0) # Max range for eye movement (-3.0 to 3.0)
4242

43+
# Workspace parameters - defines the active region for eye movement
44+
# Values are percentages of frame dimensions (0.0 to 1.0)
45+
self.declare_parameter('workspace_width', 0.4) # Width of workspace relative to frame width
46+
self.declare_parameter('workspace_height', 0.4) # Height of workspace relative to frame height
47+
4348
self.invert_x = self.get_parameter('invert_x').value
4449
self.invert_y = self.get_parameter('invert_y').value
4550
self.eye_range = self.get_parameter('eye_range').value
51+
self.workspace_width = self.get_parameter('workspace_width').value
52+
self.workspace_height = self.get_parameter('workspace_height').value
4653

4754
# Create custom eye configuration
4855
config = EyeConfig(
@@ -175,32 +182,43 @@ def handle_faces(self, msg):
175182
self.target_face_position[1]
176183
)
177184

178-
# Call go_to_pos only if we have a valid position
179-
if eye_position:
180-
# self.controller.go_to_pos(eye_position)
185+
# Call set_eye_positions only if face is within workspace
186+
if eye_position is not None:
181187
self.eye_controller.set_eye_positions((eye_position[0], eye_position[1]))
182188
self.get_logger().info(f'Moving eyes to position: ({eye_position[0]:.2f}, {eye_position[1]:.2f})')
189+
else:
190+
# Face is outside workspace - keep eyes centered
191+
self.eye_controller.set_eye_positions((0.0, 0.0))
192+
self.get_logger().debug('Face outside workspace - keeping eyes centered')
183193

184194
except Exception as e:
185195
self.get_logger().error(f"Error processing face data: {e}")
186196

187197

188198
def transform_camera_to_eye_coords(self, camera_x, camera_y):
189-
"""Transform camera coordinates to eye controller coordinates (-3.0 to 3.0 range)"""
190-
# Normalize to -1.0 to 1.0
191-
# Note: We invert the coordinates to ensure proper eye direction
192-
# (When face is on right side, eyes should look right)
193-
norm_x = (camera_x - self.frame_width/2) / (self.frame_width/2)
194-
norm_y = (camera_y - self.frame_height/2) / (self.frame_height/2)
199+
"""Transform camera coordinates to eye controller coordinates (-3.0 to 3.0 range)
200+
Only moves eyes when face is within the defined workspace area.
201+
Returns None if face is outside workspace.
202+
"""
203+
# Calculate workspace boundaries
204+
workspace_half_width = (self.workspace_width * self.frame_width) / 2
205+
workspace_half_height = (self.workspace_height * self.frame_height) / 2
206+
frame_center_x = self.frame_width / 2
207+
frame_center_y = self.frame_height / 2
195208

196-
# Add sensitivity multiplier (like in eye_tracking.py)
197-
sensitivity = 1.5 # Higher = more sensitive eye movement
198-
norm_x *= sensitivity
199-
norm_y *= sensitivity
209+
# Check if face is within workspace boundaries
210+
if (abs(camera_x - frame_center_x) > workspace_half_width or
211+
abs(camera_y - frame_center_y) > workspace_half_height):
212+
# Face is outside workspace - return None to indicate no eye movement
213+
return None
214+
215+
# Normalize position within workspace to -1.0 to 1.0
216+
# This maps the workspace edges to maximum eye movement
217+
norm_x = (camera_x - frame_center_x) / workspace_half_width
218+
norm_y = (camera_y - frame_center_y) / workspace_half_height
200219

201220
# Apply inversions if configured
202221
# Note: By default we want norm_x to be positive when face is on right side
203-
# So default should have invert_x=False
204222
if self.invert_x:
205223
norm_x = -norm_x
206224
if self.invert_y:

0 commit comments

Comments
 (0)