Skip to content

Commit ec8ff0c

Browse files
committed
update mission planning
1 parent 3986913 commit ec8ff0c

11 files changed

Lines changed: 541 additions & 270 deletions

File tree

GEMstack/knowledge/defaults/computation_graph.yaml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,15 @@ components:
4040
inputs: all
4141
- mission_execution:
4242
outputs: mission
43+
- mission_planning:
44+
inputs: all
45+
outputs: mission
4346
- route_planning:
44-
inputs: [vehicle, roadgraph, mission]
47+
inputs: all
4548
outputs: route
4649
- driving_logic:
4750
inputs:
4851
outputs: intent
49-
- parking_component: # one way
50-
inputs: all
51-
outputs: mission_plan
52-
- summon_component: # one way
53-
inputs: all
54-
outputs: route
55-
- summoning_mission_planning:
56-
inputs: all
57-
outputs: mission_plan
58-
- route_planning_component: # one way
59-
inputs: all
60-
outputs: route
6152
- motion_planning:
6253
inputs: all
6354
outputs: trajectory
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
from typing import List, Union
2+
from klampt.vis import scene
3+
from ..component import Component
4+
from ...utils import serialization
5+
from ...state import Route, ObjectFrameEnum, AllState, VehicleState, Roadgraph, MissionObjective, MissionEnum, ObjectPose
6+
import numpy as np
7+
import requests
8+
import json
9+
import time
10+
11+
12+
def check_distance(goal_pose: Union[ObjectPose, list], current_pose : ObjectPose):
13+
if isinstance(goal_pose, ObjectPose):
14+
goal = np.array([goal_pose.x, goal_pose.y])
15+
else:
16+
goal = np.array([goal_pose[0], goal_pose[1]])
17+
current = np.array([current_pose.x, current_pose.y])
18+
return np.linalg.norm(goal - current)
19+
20+
21+
class StateMachine:
22+
def __init__(self, state_list : List = None):
23+
self.state_list = state_list
24+
self.state_index = 0
25+
self.initial_state = self.state_list[0]
26+
self.current_state = self.state_list[self.state_index]
27+
28+
def next_state(self):
29+
if self.state_index < len(self.state_list) - 1:
30+
self.state_index += 1
31+
return self.state_list[self.state_index]
32+
else:
33+
self.state_index = 0
34+
return self.state_list[0]
35+
36+
37+
class SummoningMissionPlanner(Component):
38+
def __init__(self, use_webapp, goal, state_machine):
39+
self.state_machine = StateMachine([eval(s) for s in state_machine])
40+
self.goal_location = goal['location']
41+
self.goal_frame = goal['frame']
42+
self.new_goal = False
43+
self.goal_pose = None
44+
self.start_pose = None
45+
self.start_time = time.time()
46+
47+
self.flag_use_webapp = use_webapp
48+
49+
if self.flag_use_webapp:
50+
# Initialize the state in the server
51+
url = "http://localhost:8000/api/status"
52+
data = {
53+
"status": "IDLE"
54+
}
55+
response = requests.post(url=url, json=data)
56+
if response.status_code == 200:
57+
print("Status updated successfully")
58+
else:
59+
print("Failed to update status:", response.status_code)
60+
url = "http://localhost:8000/api/summon"
61+
data = {
62+
"lat": 0,
63+
"lon": 0
64+
}
65+
response = requests.post(url=url, json=data)
66+
if response.status_code == 200:
67+
print("Initialize goal location successfully")
68+
else:
69+
print("Failed to initialize goal location:", response.status_code)
70+
71+
def state_inputs(self):
72+
return ['all']
73+
74+
def state_outputs(self) -> List[str]:
75+
return ['mission']
76+
77+
def rate(self):
78+
return 1.0
79+
80+
def update(self, state: AllState):
81+
vehicle = state.vehicle
82+
mission = state.mission
83+
route = state.route
84+
85+
if self.flag_use_webapp:
86+
goal_location = None
87+
goal_frame = None
88+
url = "http://localhost:8000/api/summon"
89+
response = requests.get(url)
90+
print("GET:", response)
91+
if response.status_code == 200:
92+
data = response.json()
93+
if data['lat'] == 0 and data['lon'] == 0: # TODO: lat and lon equal to 0 is meaningful, should change
94+
print("No goal location received")
95+
goal_location = None
96+
goal_frame = None
97+
else:
98+
goal_location = [data['lat'] , data['lon']]
99+
goal_frame = 'global'
100+
print("Goal location:", goal_location)
101+
print("Goal frame:", goal_frame)
102+
103+
if self.goal_location == goal_location:
104+
self.new_goal = False
105+
else:
106+
self.new_goal = True
107+
self.goal_location = goal_location
108+
self.goal_frame = goal_frame
109+
else:
110+
self.new_goal = True
111+
goal_location = self.goal_location
112+
goal_frame = self.goal_frame
113+
114+
if goal_frame == 'global':
115+
self.goal_pose = ObjectPose(t=time.time(), x=goal_location[0], y=goal_location[1],
116+
frame=ObjectFrameEnum.GLOBAL)
117+
elif goal_frame == 'cartesian':
118+
self.goal_pose = ObjectPose(t=time.time(), x=goal_location[0], y=goal_location[1],
119+
frame=ObjectFrameEnum.ABSOLUTE_CARTESIAN)
120+
elif goal_frame == 'start':
121+
self.goal_pose = ObjectPose(t=time.time() - self.start_time, x=goal_location[0], y=goal_location[1],
122+
frame=ObjectFrameEnum.START)
123+
elif goal_frame is None:
124+
pass
125+
else:
126+
raise ValueError("Invalid frame argument")
127+
128+
if self.goal_pose:
129+
self.goal_pose = self.goal_pose.to_frame(ObjectFrameEnum.START, start_pose_abs=state.start_vehicle_pose)
130+
131+
# Initiate state
132+
if mission is None:
133+
mission = MissionObjective()
134+
mission.type = self.state_machine.initial_state
135+
136+
# Receive goal location from the server and start driving
137+
elif mission.type == MissionEnum.IDLE:
138+
if self.new_goal:
139+
mission.goal_pose = self.goal_pose
140+
mission.type = self.state_machine.next_state()
141+
print("============== Next state:", mission.type)
142+
143+
# Reach the end of the route, begin to search for parking
144+
elif mission.type == MissionEnum.SUMMONING_DRIVE:
145+
mission.goal_pose = self.goal_pose
146+
if route:
147+
_, closest_index = route.closest_point([vehicle.pose.x, vehicle.pose.y], edges=False)
148+
if closest_index == len(route.points) - 1 or check_distance(mission.goal_pose, vehicle.pose) < 1:
149+
mission.type = self.state_machine.next_state()
150+
print("============== Next state:", mission.type)
151+
152+
# Finish parking, back to idle and wait for the next goal location
153+
elif mission.type == MissionEnum.PARALLEL_PARKING:
154+
if route:
155+
_, closest_index = route.closest_point([vehicle.pose.x, vehicle.pose.y], edges=False)
156+
if closest_index == len(route.points) - 1 or check_distance(route.points[-1], vehicle.pose) < 0.1:
157+
mission.type = self.state_machine.next_state()
158+
self.goal_pose = None
159+
mission.goal_pose = self.goal_pose
160+
print("============== Next state:", mission.type)
161+
162+
else:
163+
raise ValueError("Invalid mission type")
164+
165+
166+
if self.flag_use_webapp:
167+
url = "http://localhost:8000/api/status"
168+
data = {
169+
"status": mission.type.name
170+
}
171+
print("POST:", data)
172+
response = requests.post(url=url, json=data)
173+
if response.status_code == 200:
174+
print("Status updated successfully")
175+
else:
176+
print("Failed to update status:", response.status_code)
177+
178+
return mission

0 commit comments

Comments
 (0)