Skip to content

Robot.py #663

@alzaky

Description

@alzaky

import tkinter as tk
import threading
import time
import random
import speech_recognition as sr
from tkinter import ttk

----- Settings -----

OWNER_NAME = "owner"
CONFIRM_TIMEOUT = 5

Enhanced commands with multiple language support

ACTION_MAP = {
"wave": {
"action": "Wave Hand",
"keywords": {
"en": ["wave", "hello", "hi", "greet"],
"ar": ["اهتز", "مرحباً", "لوح", "سلم"]
}
},
"forward": {
"action": "Move Forward",
"keywords": {
"en": ["forward", "front", "ahead", "advance", "go"],
"ar": ["امام", "تقديم", "انطلق", "اسرع"]
}
},
"backward": {
"action": "Move Backward",
"keywords": {
"en": ["backward", "back", "behind", "retreat"],
"ar": ["خلف", "تراجع", "ارجع", "الى وراء"]
}
},
"left": {
"action": "Turn Left",
"keywords": {
"en": ["left", "turn left", "go left"],
"ar": ["يسار", "اتجه يسار", "شمال", "يسارا"]
}
},
"right": {
"action": "Turn Right",
"keywords": {
"en": ["right", "turn right", "go right"],
"ar": ["يمين", "اتجه يمين", "يمينا"]
}
},
"reset": {
"action": "Reset Position",
"keywords": {
"en": ["reset", "home", "center", "stop"],
"ar": ["استعادة", "مركز", "اعد", "توقف"]
}
}
}

ACTIONS = list(ACTION_MAP.keys())
pending = {}
_next_id = 0
lock = threading.Lock()
current_language = "en" # Default language

----- Control Functions -----

def next_id():
global _next_id
with lock:
_next_id += 1
return _next_id

def find_matching_command(text, lang="en"):
"""Find matching command in text with language support"""
text = text.lower().strip()

for cmd_id, cmd_info in ACTION_MAP.items(): # Check keywords in the specified language if lang in cmd_info["keywords"]: for keyword in cmd_info["keywords"][lang]: if keyword.lower() in text: return cmd_id, cmd_info["action"] return None, None 

def receive_command(from_name, text, confidence=0.8):
"""Receive command with multi-language support"""
# Try current language first
cmd_id, action = find_matching_command(text, current_language)

# If not found, try other languages if not action: for lang in ["en", "ar"]: if lang != current_language: cmd_id, action = find_matching_command(text, lang) if action: break if not action: app.log_event(f"[WARN] Cannot recognize command: {text}") return if from_name == OWNER_NAME and confidence >= 0.55: app.log_event(f"[AUTH] Owner verified → Executing {action}") execute_action(action) return cid = next_id() pending[cid] = {"from": from_name, "action": action, "ts": time.time()} app.update_pending() app.log_event(f"[PENDING-{cid}] {from_name}: {action}. Awaiting confirmation") 

def wait_timeout(cid):
start = time.time()
while time.time() - start < CONFIRM_TIMEOUT:
time.sleep(0.2)
if cid not in pending:
return
if cid in pending:
info = pending.pop(cid)
app.update_pending()
app.log_event(f"[TIMEOUT] Command {cid} ignored (from {info['from']})")

def confirm_cmd(cid):
if cid in pending:
info = pending.pop(cid)
app.update_pending()
app.log_event(f"[CONFIRMED] Approved {cid} → Executing {info['action']}")
execute_action(info['action'])
else:
app.log_event(f"[CONFIRM] No pending command with id {cid}")

def execute_action(action):
app.log_event(f"[EXECUTE] {action}")
app.perform_action(action)
time.sleep(0.5)
app.log_event(f"[DONE] {action}")

def switch_language(lang):
"""Switch voice recognition language"""
global current_language
current_language = lang
app.log_event(f"[LANGUAGE] Switched to {lang.upper()} voice recognition")
app.update_language_display()

----- Enhanced Voice Recognition -----

def listen_microphone():
r = sr.Recognizer()

try: with sr.Microphone() as source: r.adjust_for_ambient_noise(source, duration=1) app.log_event("[INFO] Ready to listen... Adjusted for ambient noise") except: app.log_event("[WARN] Cannot access microphone") return while True: try: app.log_event(f"[LISTENING] Listening for {current_language.upper()} commands...") with sr.Microphone() as source: r.pause_threshold = 1.0 r.energy_threshold = 300 audio = r.listen(source, timeout=5, phrase_time_limit=3) # Try recognition with current language if current_language == "ar": text = r.recognize_google(audio, language="ar-AR") else: text = r.recognize_google(audio, language="en-US") app.log_event(f"[VOICE] Recognized: '{text}'") if text.strip(): receive_command(OWNER_NAME, text, confidence=0.8) except sr.WaitTimeoutError: continue except sr.UnknownValueError: app.log_event("[ERROR] Could not understand audio") except sr.RequestError as e: app.log_event(f"[ERROR] Recognition service error: {e}") except Exception as e: app.log_event(f"[ERROR] {e}") time.sleep(0.5) 

----- Event Simulation -----

def simulate_events():
while True:
time.sleep(random.uniform(5, 8))
who = random.choice(["Alice", "Bob", "Charlie"])
phrase = random.choice(ACTIONS)
conf = 0.55
app.log_event(f"[EVENT] {who} → '{phrase}' (conf={conf:.2f})")
receive_command(who, phrase, conf)

----- Enhanced GUI -----

class RobotApp:
def init(self, master):
self.master = master
master.title("AI Robot Simulator - Multi Language")
master.geometry("850x650")

 # Font settings self.title_font = ("Arial", 16, "bold") self.normal_font = ("Arial", 11) self.small_font = ("Arial", 10) # Title Frame title_frame = tk.Frame(master, bg="#2C3E50") title_frame.pack(fill="x", padx=10, pady=5) tk.Label(title_frame, text="AI Robot Simulator - Voice Controlled", font=self.title_font, fg="white", bg="#2C3E50").pack(pady=10) # Language Selection Frame lang_frame = tk.Frame(master) lang_frame.pack(fill="x", padx=10, pady=5) tk.Label(lang_frame, text="Voice Language:", font=self.normal_font).pack(side="left") self.lang_var = tk.StringVar(value="en") tk.Radiobutton(lang_frame, text="English", variable=self.lang_var, value="en", command=lambda: switch_language("en"), font=self.small_font).pack(side="left", padx=10) tk.Radiobutton(lang_frame, text="Arabic", variable=self.lang_var, value="ar", command=lambda: switch_language("ar"), font=self.small_font).pack(side="left", padx=10) # Commands Frame commands_frame = tk.Frame(master, relief="solid", bd=1, padx=10, pady=10) commands_frame.pack(fill="x", padx=10, pady=5) tk.Label(commands_frame, text="Supported Voice Commands:", font=self.normal_font, justify="left").pack(anchor="w") self.commands_display = tk.Text(commands_frame, height=6, wrap="word", font=("Arial", 9)) self.commands_display.pack(fill="x", pady=5) # Robot Canvas self.canvas = tk.Canvas(master, width=500, height=300, bg="white", highlightthickness=1, highlightbackground="#CCCCCC") self.canvas.pack(pady=10) # Manual Control Buttons button_frame = tk.Frame(master) button_frame.pack(pady=10) # Row 1 button_frame1 = tk.Frame(button_frame) button_frame1.pack() buttons1 = [ ("Move Forward", "forward"), ("Move Backward", "backward"), ("Reset Position", "reset") ] for text, action in buttons1: btn = tk.Button(button_frame1, text=text, command=lambda a=action: receive_command(OWNER_NAME, a, 1.0), font=self.small_font, width=15, height=2, bg="#27AE60", fg="white") btn.pack(side="left", padx=5) # Row 2 button_frame2 = tk.Frame(button_frame) button_frame2.pack(pady=5) buttons2 = [ ("Turn Left", "left"), ("Turn Right", "right"), ("Wave Hand", "wave") ] for text, action in buttons2: btn = tk.Button(button_frame2, text=text, command=lambda a=action: receive_command(OWNER_NAME, a, 1.0), font=self.small_font, width=15, height=2, bg="#2980B9", fg="white") btn.pack(side="left", padx=5) # Event Log Frame log_frame = tk.Frame(master) log_frame.pack(fill="both", expand=True, padx=10, pady=5) tk.Label(log_frame, text="Event Log:", font=self.normal_font, justify="left").pack(anchor="w") # Text area with scrollbar text_frame = tk.Frame(log_frame) text_frame.pack(fill="both", expand=True) self.log = tk.Text(text_frame, height=8, wrap="word", font=("Consolas", 9)) scrollbar = tk.Scrollbar(text_frame, command=self.log.yview) self.log.config(yscrollcommand=scrollbar.set) self.log.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") # Pending Commands Frame pending_frame = tk.Frame(master) pending_frame.pack(fill="x", padx=10, pady=5) tk.Label(pending_frame, text="Pending Commands:", font=self.normal_font, justify="left").pack(anchor="w") self.pending_box = tk.Listbox(pending_frame, height=3, font=self.small_font) self.pending_box.pack(fill="x") # Confirm button confirm_btn = tk.Button(pending_frame, text="Confirm Last Command", command=self.confirm_last, font=self.small_font, bg="#E67E22", fg="white", width=20) confirm_btn.pack(pady=5) self.draw_robot() self.update_sensors() self.update_language_display() def confirm_last(self): if pending: last_cid = list(pending.keys())[-1] confirm_cmd(last_cid) def log_event(self, text): timestamp = time.strftime("%H:%M:%S") formatted_text = f"[{timestamp}] {text}" self.log.insert("end", formatted_text + "\n") self.log.see("end") self.master.update() def update_pending(self): self.pending_box.delete(0, "end") for cid, info in pending.items(): display_text = f"{cid}: {info['from']} → {info['action']}" self.pending_box.insert("end", display_text) def update_language_display(self): """Update the commands display based on current language""" self.commands_display.delete(1.0, "end") lang_name = "English" if current_language == "en" else "Arabic" self.commands_display.insert("end", f"Current Language: {lang_name}\n\n") for cmd_id, cmd_info in ACTION_MAP.items(): if current_language in cmd_info["keywords"]: keywords = ", ".join(cmd_info["keywords"][current_language]) self.commands_display.insert("end", f"• {cmd_info['action']}: {keywords}\n") self.commands_display.config(state="disabled") def draw_robot(self): self.canvas.delete("all") # Robot body self.canvas.create_rectangle(220, 150, 280, 250, fill="#B0BEC5", outline="#37474F", width=2) # Head self.canvas.create_oval(220, 100, 280, 150, fill="#FFEB3B", outline="#37474F", width=2) # Eyes self.canvas.create_oval(235, 115, 245, 125, fill="black") self.canvas.create_oval(255, 115, 265, 125, fill="black") # Arms self.left_arm = self.canvas.create_line(220, 160, 180, 200, width=6, fill="#5D4037") self.right_arm = self.canvas.create_line(280, 160, 320, 200, width=6, fill="#5D4037") # Wheels self.left_wheel = self.canvas.create_oval(210, 250, 230, 270, fill="#212121") self.right_wheel = self.canvas.create_oval(270, 250, 290, 270, fill="#212121") # Sensors self.temp_sensor = self.canvas.create_rectangle(20, 20, 90, 40, fill="#F44336") self.humidity_sensor = self.canvas.create_rectangle(100, 20, 170, 40, fill="#2196F3") # Sensor labels self.canvas.create_text(55, 30, text="Temp", fill="white", font=("Arial", 9, "bold")) self.canvas.create_text(135, 30, text="Humidity", fill="white", font=("Arial", 9, "bold")) def perform_action(self, action): if action == "Wave Hand": for i in range(3): self.canvas.coords(self.right_arm, 280, 160, 340, 140) self.master.update() time.sleep(0.3) self.canvas.coords(self.right_arm, 280, 160, 320, 200) self.master.update() time.sleep(0.3) elif action == "Move Forward": self.canvas.move("all", 0, -20) self.master.update() elif action == "Move Backward": self.canvas.move("all", 0, 20) self.master.update() elif action == "Turn Left": self.canvas.move(self.left_wheel, -15, 0) self.canvas.move(self.right_wheel, -5, 0) self.master.update() elif action == "Turn Right": self.canvas.move(self.left_wheel, 5, 0) self.canvas.move(self.right_wheel, 15, 0) self.master.update() elif action == "Reset Position": self.canvas.delete("all") self.draw_robot() self.master.update() def update_sensors(self): temp = random.randint(20, 35) humidity = random.randint(30, 80) # Update sensor colors temp_color = f"#ff{max(0, 255-temp*7):02x}00" hum_color = f"#0000{min(255, humidity*3):02x}" self.canvas.itemconfig(self.temp_sensor, fill=temp_color) self.canvas.itemconfig(self.humidity_sensor, fill=hum_color) # Update sensor readings self.canvas.delete("sensor_readings") self.canvas.create_text(55, 30, text=f"{temp}°C", fill="white", font=("Arial", 8, "bold"), tags="sensor_readings") self.canvas.create_text(135, 30, text=f"{humidity}%", fill="white", font=("Arial", 8, "bold"), tags="sensor_readings") self.master.after(3000, self.update_sensors) 

----- Application Startup -----

if name == "main":
root = tk.Tk()
app = RobotApp(root)

# Start background threads threading.Thread(target=simulate_events, daemon=True).start() threading.Thread(target=listen_microphone, daemon=True).start() app.log_event("✅ Application ready") app.log_event("🎤 Voice commands activated") app.log_event("🔊 You can speak commands in English or Arabic") app.log_event("🌐 Use the radio buttons to switch voice recognition language") root.mainloop() 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions