Grounded language ist ein interdisziplinäres Problem was ein umfangreiches Fachwissen in sehr unterschiedlichen Disziplinen wie Informatik, Linguistik und Robotersteuerung erfordert. Es ist daher nötig, die Thematik zu vereinfachen anhand eines praktischen Beispiels. Ein Anfang ist eine Landkarte auf der ein Mauscursor bewegt wird. Der nutzer kann die mauf einen belieben Punkt bewegen z.B. auf einen roten Kreis oder ein gelbes Quadrat. Das Computerprogram zeigt für die Mauspostition die [tags] an, z.B. "[kreis] [grün]", oder "[rechteck] [klein]".
zumindest für das MInibeispiel mit der Landkarte auf dem geoemtrische Objekte zu sehen sind, ist damit das symbol grounding problem gelöst.
Ähnlich wie bei einer perspektivischen Darstellung in der Malerei gilt es also die REalität auf ein koordinatensystem abzubilden. Bei grounding problem bestehen die koordinaten aus einer [tag] liste. Der User zeigt auf einen punkt z.B. (100,30) und der Computer bestimmt die Tags für das Objekt an diesem Punkt.
Obwohl die technische Umsetzung leicht ist, kann über grounded language ein erstaunlich leistungsfähiges KI System erstellt werden. Ab dem moment wo der Computer tags ausgeben und parsen kann ist darüber eine Kommunikation möglich. Ein Beispiel:
Angenommen die beschriebene semantische Kamera wurde für ein Jump'bn'Run Videospiel implementiert, das heißt die Software vermag anhand der Tilemap sagen, ob der Mousecursor auf einem Abgrund, einem coin, einem powerup, einem Gegner oder auf einer Plattform steht. Dann kann diese Information in einer Regel referenziert werden, wie "gehe bis zum Abgrund und halte an, dann springe darüber und laufe bis zum Coin". Diese komplexe Befehlsfege referenziert auf erkannte Tags in dem Computerspiel, der parser kann dies auswerten und versteht was der Benutzer möchte. Nicth weil ein hochkomplexer Algorithmus im Hintergrund arbeitet, sondern weil ein mensch maschine interface existiert auf das man verweisen kann.
Der sourcecode und der screenshot zeigen nicht das geometrie problem sondern ein robot in a maze spiel bei dem ein roboter items sammeln muss. Es gibt in der Statuszeile eine semantische Event Erkennung. Der Roboter bewegt sich in der Karte und parallel dazu wird in der Textbox die aktuelle Situaton beschrieben, ein wenig so wie einem frühen Textadventure. Über besagte Statuszeile wird der game state des robtoers definiert und zwar im linguistischen Raum und nicht im geometrisch mathematischen Raum.
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
pygame.font.init()
# --- Configuration Constants ---
GRID_SIZE = 40 # Pixels per cell
GRID_COLS = 20
GRID_ROWS = 12
# Textbox dimensions (40 chars wide, 4 lines high roughly translates to this)
TEXTBOX_HEIGHT = 100
SCREEN_WIDTH = GRID_COLS * GRID_SIZE
SCREEN_HEIGHT = (GRID_ROWS * GRID_SIZE) + TEXTBOX_HEIGHT
# Colors (RGB)
COLOR_STREET = (240, 240, 240)
COLOR_HOUSE = (70, 130, 180)
COLOR_ROBOT = (220, 50, 50)
COLOR_TRASH = (40, 180, 99)
COLOR_TEXTBOX_BG = (30, 30, 30)
COLOR_TEXT = (255, 255, 255)
COLOR_GRID = (210, 210, 210)
# --- Event Log System ---
# The 12 grounded language events:
# 1. "System initialized. Roomba ready."
# 2. "Moved North."
# 3. "Moved South."
# 4. "Moved East."
# 5. "Moved West."
# 6. "Obstacle detected at North."
# 7. "Obstacle detected at South."
# 8. "Obstacle detected at East."
# 9. "Obstacle detected at West."
# 10. "Grid boundary reached."
# 11. "Trash item successfully collected!"
# 12. "Area clear. No trash nearby."
event_logs = ["System initialized. Roomba ready.", "", "", ""]
def log_event(message):
"""Adds a new event to the log, keeping only the last 4 events."""
global event_logs
if event_logs[-1] != message: # Avoid spamming identical consecutive logs
event_logs.append(message)
if len(event_logs) > 4:
event_logs.pop(0)
# --- Map & Environment Setup ---
# 0 = Street (Pathway), 1 = House (Obstacle)
maze = [[0 for _ in range(GRID_COLS)] for _ in range(GRID_ROWS)]
# Generate mock "blocks" of houses to look like a street map
random.seed(42) # Seed for consistent map generation
for r in range(1, GRID_ROWS - 1, 3):
for c in range(1, GRID_COLS - 1, 4):
# Create a 2x2 or 2x3 house block
block_w = random.randint(2, 3)
block_h = 2
for bh in range(block_h):
for bw in range(block_w):
if r + bh < GRID_ROWS - 1 and c + bw < GRID_COLS - 1:
maze[r + bh][c + bw] = 1
# Spawn Trash Items
trash_positions = set()
while len(trash_positions) < 10:
tr = random.randint(0, GRID_ROWS - 1)
tc = random.randint(0, GRID_COLS - 1)
if maze[tr][tc] == 0: # Must be on a street
trash_positions.add((tc, tr))
# Spawn Robot
robot_x, robot_y = 0, 0
while maze[robot_y][robot_x] != 0:
robot_x = random.randint(0, GRID_COLS - 1)
robot_y = random.randint(0, GRID_ROWS - 1)
# --- Simulation Setup ---
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Robot Street Simulator")
clock = pygame.time.Clock()
font = pygame.font.SysFont("Courier", 18) # Monospace font for predictable char width
def check_surroundings(rx, ry):
"""Scans adjacent cells to log nearby obstacles."""
# North
if ry - 1 < 0: pass
elif maze[ry - 1][rx] == 1: log_event("Obstacle detected at North.")
# South
if ry + 1 >= GRID_ROWS: pass
elif maze[ry + 1][rx] == 1: log_event("Obstacle detected at South.")
# West
if rx - 1 < 0: pass
elif maze[ry][rx - 1] == 1: log_event("Obstacle detected at West.")
# East
if rx + 1 >= GRID_COLS: pass
elif maze[ry][rx + 1] == 1: log_event("Obstacle detected at East.")
# Initial scan
check_surroundings(robot_x, robot_y)
# --- Main Loop ---
# --- Main Loop ---
running = True
while running:
for event in pygame.event.get():
# FIX: Changed event.get_type() to event.type
if event.type == pygame.QUIT:
running = False
# FIX: Changed event.get_type() to event.type
elif event.type == pygame.KEYDOWN:
dx, dy = 0, 0
move_dir = ""
if event.key == pygame.K_UP:
dy = -1
move_dir = "North"
elif event.key == pygame.K_DOWN:
dy = 1
move_dir = "South"
elif event.key == pygame.K_LEFT:
dx = -1
move_dir = "West"
elif event.key == pygame.K_RIGHT:
dx = 1
move_dir = "East"
if dx != 0 or dy != 0:
new_x = robot_x + dx
new_y = robot_y + dy
# Check Grid Boundary
if not (0 <= new_x < GRID_COLS and 0 <= new_y < GRID_ROWS):
log_event("Grid boundary reached.")
# Check House Obstacle Collision
elif maze[new_y][new_x] == 1:
log_event(f"Obstacle detected at {move_dir}.")
# Move Valid
else:
robot_x = new_x
robot_y = new_y
log_event(f"Moved {move_dir}.")
# Check Trash Collection
if (robot_x, robot_y) in trash_positions:
trash_positions.remove((robot_x, robot_y))
log_event("Trash item successfully collected!")
# Scan environment post-movement
check_surroundings(robot_x, robot_y)
# Check if all clear
if not trash_positions:
log_event("Area clear. No trash nearby.")
# --- Drawing Environment ---
screen.fill(COLOR_STREET)
# Draw Grid and Houses
for r in range(GRID_ROWS):
for c in range(GRID_COLS):
rect = pygame.Rect(c * GRID_SIZE, r * GRID_SIZE, GRID_SIZE, GRID_SIZE)
if maze[r][c] == 1:
pygame.draw.rect(screen, COLOR_HOUSE, rect)
pygame.draw.rect(screen, COLOR_GRID, rect, 1)
# Draw Trash Items
for (tx, ty) in trash_positions:
trash_rect = pygame.Rect(tx * GRID_SIZE + 10, ty * GRID_SIZE + 10, GRID_SIZE - 20, GRID_SIZE - 20)
pygame.draw.rect(screen, COLOR_TRASH, trash_rect, border_radius=3)
# Draw Robot
robot_rect = pygame.Rect(robot_x * GRID_SIZE + 6, robot_y * GRID_SIZE + 6, GRID_SIZE - 12, GRID_SIZE - 12)
pygame.draw.ellipse(screen, COLOR_ROBOT, robot_rect)
# --- Drawing Grounded Language Textbox ---
# Draw Textbox background container
textbox_rect = pygame.Rect(0, GRID_ROWS * GRID_SIZE, SCREEN_WIDTH, TEXTBOX_HEIGHT)
pygame.draw.rect(screen, COLOR_TEXTBOX_BG, textbox_rect)
pygame.draw.rect(screen, COLOR_TEXT, textbox_rect, 2) # Border
# Render the 4 lines of text
for idx, log in enumerate(event_logs):
# Clip string to 40 characters maximum to respect specification constraints
truncated_log = log[:40]
text_surface = font.render(truncated_log, True, COLOR_TEXT)
screen.blit(text_surface, (15, (GRID_ROWS * GRID_SIZE) + 10 + (idx * 20)))
pygame.display.flip()
clock.tick(30)
pygame.quit()
sys.exit()

No comments:
Post a Comment