Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions core/physical/domains/cooking_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import re

class CookingEngine:
def __init__(self):
# Built-in step templates
self.templates = ["pasta", "stir-fry", "baking", "salad", "omelette"]
self.threshold_temp_f= 400
self.threshold_temp_c= 200




def analyze(self, detections: list, ocr_text: str, hand_results: list):
"""
Analyzes cooking tasks based on object detections, recipe OCR, and hand positions.
"""
detected_items= set(detections)
current_step = 'Unknown step'
criticality_level= 'normal'
criticality_message= ' '


text_lower= ocr_text.lower()


if {'knife', 'cutting board'}.issubset(detected_items):
current_step = 'PREP: Cutting ingredients'

# PASTA
elif {'uncooked pasta','pot', 'stove'}.issubset(detected_items):
current_step= 'PASTA: Adding pasta to water'
elif {'pot', 'stove'}.issubset(detected_items):
current_step= 'PASTA: Boiling water'
elif {'strainer','sink', 'pot'}.issubset(detected_items):
current_step= 'PASTA: Draining water'
elif {'saucepan','ladle', 'stove'}.issubset(detected_items):
current_step= 'PASTA: Simmering and preparing the sauce'
elif {'saucepan','pasta', 'tongs'}.issubset(detected_items):
current_step= 'PASTA: Combining pasta with sauce'

#STIR-FRY
elif {'pan','spatula', 'stove'}.issubset(detected_items):
current_step= 'STIR-FRY: Frying of protiens and vegetables'
elif {'pan','oil'}.issubset(detected_items):
current_step= 'STIR-FRY: Sauteing in garlic and oil'
elif {'sauce','pan'}.issubset(detected_items):
current_step= 'STIR-FRY: Adding sauce for thickening'

#SALAD
elif {'dressing','mixing bowl'}.issubset(detected_items):
current_step= 'SALAD: Emulsifying dressing'
elif {'tongs','mixing bowl'}.issubset(detected_items):
current_step= 'SALAD: Tossing ingredients and dressing'



elif {'whisk','mixing bowl'}.issubset(detected_items):
if 'egg' in text_lower or 'omelette' in text_lower:
current_step= 'OMELETTE: Whisking eggs and seasoning'
else:
current_step= 'BAKING: Mixing dough'


#BAKING

elif {'baking tray','parchment paper'}.issubset(detected_items):
current_step= 'BAKING: Greasing and preparing the baking pan'
elif {'baking tray','oven'}.issubset(detected_items):
current_step= 'BAKING: Baking inside oven'

#OMELETTE

elif {'pan','spatula', 'stove'}.issubset(detected_items):
current_step= 'OMELETTE: Flipping and folding the omelette'
elif {'pan','stove'}.issubset(detected_items):
current_step= 'OMELETTE: Puring eggs into hot pan'

detected_temp = 0.0
temp_match= re.findall(r'(\d+)\s*Β°?[FfCc]', ocr_text)
for match in temp_match:
detected_temp= float(match)


if 'F' in ocr_text.upper() and detected_temp> self.threshold_temp_f:
criticality_level= 'CRITICAL'
criticality_message= f'High temperature detected({detected_temp} Β°F)'
if 'C' in ocr_text.upper() and detected_temp> self.threshold_temp_c:
criticality_level= 'CRITICAL'
criticality_message= f'High temperature detected({detected_temp} Β°C)'

return {
'current_step': current_step,
'criticality_level' : criticality_level,
'criticality_message': criticality_message
}



19 changes: 19 additions & 0 deletions core/physical/physical_pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from core.physical.domains.cooking_engine import CookingEngine


class PhysicalPipeline:
def __init__(self):

self.cooking_engine = CookingEngine()

def process(self, task_type, detections, ocr_text, hand_results=[]):

if task_type == "cooking":
return self.cooking_engine.analyze(detections, ocr_text, hand_results)


return {
'current_step': 'Unknown pipeline task',
'criticality_level': 'normal',
'criticality_message': ''
}
4 changes: 3 additions & 1 deletion core/physical/task_recognizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class Detection(Protocol):
class TaskRecognizer:
"""Recognize physical task categories from camera-frame signals."""

COOKING_OBJECTS = {"knife", "bowl", "stove", "pot", "pan"}
COOKING_OBJECTS = {"knife", "bowl", "stove", "pot", "pan",
"mixing bowl", "whisk", "baking tray", "oven",
"saucepan", "spatula", "tongs", "cutting board", "strainer"}
HARDWARE_REPAIR_OBJECTS = {"screwdriver", "wrench", "circuit_board", "wire"}
FORM_KEYWORDS = ("name:", "date:", "signature", "___")

Expand Down
Binary file modified tests/__pycache__/__init__.cpython-314.pyc
Binary file not shown.
63 changes: 63 additions & 0 deletions tests/unit/test_cooking_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import unittest
from core.physical.domains.cooking_engine import CookingEngine

class TestCookingEngine(unittest.TestCase):
def setUp(self):
self.engine= CookingEngine()


def test_prep_cutting_test(self):

detections= ['knife', 'cutting board', 'tomato']
ocr_text= "Slice the tomatoes"

result= self.engine.analyze( detections, ocr_text, [])
self.assertEqual(result['current_step'], 'PREP: Cutting ingredients')
self.assertEqual(result['criticality_level'], 'normal')

def test_pasta_sequence(self):

detections = ["uncooked pasta", "pot", "stove"]
ocr_text = "Add the pasta to boiling water."

result = self.engine.analyze(detections, ocr_text, [])

self.assertEqual(result['current_step'], 'PASTA: Adding pasta to water')

def test_mixing_bowl_tie_breaker_baking(self):
detections = ["whisk", "mixing bowl", "flour"]
ocr_text = "Mix the flour and sugar together."

result = self.engine.analyze(detections, ocr_text, [])

self.assertEqual(result['current_step'], 'BAKING: Mixing dough')

def test_mixing_bowl_tie_breaker_omelette(self):
detections = ["whisk", "mixing bowl"]
ocr_text = "Whisk 3 large EGGS thoroughly." # Capitalized to test case-insensitivity

result = self.engine.analyze(detections, ocr_text, [])

self.assertEqual(result['current_step'], 'OMELETTE: Whisking eggs and seasoning')

def test_critical_temperature_alert_fahrenheit(self):
detections = ["baking tray", "oven"]
ocr_text = "Preheat oven to 425Β°F."

result = self.engine.analyze(detections, ocr_text, [])

self.assertEqual(result['criticality_level'], 'CRITICAL')
self.assertIn('High temperature detected', result['criticality_message'])

def test_safe_temperature_celsius(self):
detections = ["pan", "stove"]
ocr_text = "Keep oil simmered at 150Β°C."

result = self.engine.analyze(detections, ocr_text, [])

self.assertEqual(result['criticality_level'], 'normal')

if __name__ == '__main__':
unittest.main()