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