Skip to content

Commit ce7e1b0

Browse files
committed
decision components
1 parent cb09e08 commit ce7e1b0

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

src/bitbots_llm_map/LLMMapFreeKickAction.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,38 @@ def __init__(self, blackboard, dsd, parameters=None):
2323

2424
# Logger für ROS 2
2525
self.logger = get_logger("llm_map_freekick")
26+
27+
def perform(self):
28+
self.logger.info("[LLM+MAP] FreeKick Action starting – start Planning...")
29+
30+
# Reading world model
31+
state = {}
32+
wm = self.blackboard.world_model
33+
34+
try:
35+
state["own_position"] = wm.get_current_position()
36+
state["ball_position"] = wm.get_ball_position_xy()
37+
state["ball_seen"] = True # maybe not always true
38+
state["free_kick"] = True
39+
40+
self.logger.info(
41+
f"Reading WorldModel finished → own: {state['own_position']} | ball: {state['ball_position']}"
42+
)
43+
44+
except Exception as e:
45+
self.logger.error(f"Error in World Model!: {e}")
46+
# Using minimal fallback
47+
state = {"own_position": (0.0, 0.0), "ball_position": (2.0, 0.5), "ball_seen": True, "free_kick": True}
48+
self.logger.warn("→ Fallback state was used!")
49+
50+
# LLM creates a problem.pddl
51+
problem_pddl = self.problem_generator.generate(state, task="free_kick")
52+
53+
# Planner finds a solution for the problem
54+
result = self.planner.solve(domain=self.blackboard.llm_map.domain_pddl, problem=problem_pddl, timeout=8)
55+
56+
if result.success:
57+
self.logger.info(f"[LLM+MAP] plan was found! ({len(result.plan)} Schritte, {result.time_taken:.2f}s)")
58+
self.dsd.set_action("ExecuteLLMPlan")
59+
else:
60+
self.logger.warn("[LLM+MAP] Kein Plan gefunden → Fallback")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
; Domain-Header
2+
13
(define (domain bitbots_normal_behavior)
24
(:requirements :strips :typing :durative-actions :fluents :adl)
35
)
6+
7+
(:types robot ball goal position)
8+
9+
(:predicates
10+
(at ?r - robot ?p - position)
11+
()
12+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import os
2+
3+
from langchain_openai import ChatOpenAI
4+
from rclpy.logging import get_logger
5+
6+
7+
class ProblemGenerator:
8+
def __init__(self):
9+
# Open-AI Key
10+
if not os.getenv("OPENAI_API_KEY"):
11+
raise ValueError("❌ OPENAI_API_KEY isn't set!")
12+
13+
self.logger = get_logger()
14+
15+
self.llm = ChatOpenAI(model="gpt-4o", temperature="0.0", max_tokens=700)
16+
17+
self.domain = self._load_domain()
18+
19+
def _load_domain(self):
20+
path = os.path.join(os.path.dirname(__file__), "../pddl/domain.pddl")
21+
if not os.path.exists(path):
22+
raise FileNotFoundError(f"domain.pddl nicht gefunden: {path}")
23+
with open(path, encoding="utf-8") as f:
24+
return f.read()

0 commit comments

Comments
 (0)