14
14
15
15
16
16
17
- class Car :
17
+ class Car () :
18
18
'''
19
19
AVIS Engine Main Car class
20
+
21
+ Attributes
22
+ ----------
23
+
24
+ Public:
25
+ steering_value
26
+ speed_value
27
+ sensor_status
28
+ image_mode
29
+ get_Speed
30
+ data_arr
31
+ data_str
32
+ sock
33
+ image
34
+ sensors
35
+ current_speed
36
+ sensor_angle
20
37
'''
21
- def __init__ (self ) -> None :
22
- # Instance variables for car state
23
- self .steering_value : int = 0
24
- self .speed_value : int = 0
25
- self .sensor_status : int = 1
26
- self .image_mode : int = 1
27
- self .get_Speed : int = 1
28
- self .sensor_angle : int = 30
29
- self .sock : socket .socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
30
- self ._data_format : str = "Speed:{},Steering:{},ImageStatus:{},SensorStatus:{},GetSpeed:{},SensorAngle:{}"
31
- self .data_str : str = self ._data_format .format (
32
- self .speed_value , self .steering_value , self .image_mode , self .sensor_status , self .get_Speed , self .sensor_angle
33
- )
34
- self .image = None
35
- self .sensors = None
36
- self .current_speed = None
37
- self ._is_initialized = False
38
- self ._init_frames_needed = 4 # Number of frames needed for stabilization
39
-
40
- def connect (self , server : str , port : int ) -> bool :
38
+
39
+ #Attributes to kind of replicate a Pub-sub pattern messaging to request data
40
+ steering_value = 0
41
+ speed_value = 0
42
+ sensor_status = 1
43
+ image_mode = 1
44
+ get_Speed = 1
45
+ sensor_angle = 30
46
+
47
+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
48
+
49
+ #Data format for request
50
+ data_arr = [speed_value , steering_value , image_mode , sensor_status , get_Speed , sensor_angle ]
51
+ _data_format = "Speed:{},Steering:{},ImageStatus:{},SensorStatus:{},GetSpeed:{},SensorAngle:{}"
52
+ data_str = _data_format .format (data_arr [0 ], data_arr [1 ], data_arr [2 ], data_arr [3 ], data_arr [4 ], data_arr [5 ])
53
+
54
+ image = None
55
+ sensors = None
56
+ current_speed = None
57
+
58
+ def connect (self ,server ,port ):
41
59
'''
42
60
Connecting to the simulator (server)
43
61
'''
44
62
try :
45
63
self .sock .connect ((server , port ))
46
64
self .sock .settimeout (5.0 )
47
- print (f"connected to { server } { port } " )
48
- # Give simulator time to initialize
49
- time .sleep (3 )
50
- # Request initial data frames for stabilization
51
- for _ in range (self ._init_frames_needed ):
52
- self .getData ()
53
- self ._is_initialized = True
65
+
66
+ print ("connected to " , server , port )
54
67
return True
55
- except Exception as e :
56
- print (f "Failed to connect to { server } { port } : { e } " )
68
+ except :
69
+ print ("Failed to connect to " , server , port )
57
70
return False
58
71
59
- def recvall (self , sock : socket .socket ) -> str :
72
+
73
+ def recvall (self , socket ):
60
74
'''
61
75
Function to receive all the data chunks
62
76
'''
63
77
BUFFER_SIZE = 131072 # Increased buffer size for better performance
64
- data = bytearray ()
78
+ data = bytearray () # Use a bytearray for better performance
79
+
65
80
while True :
66
- part = sock .recv (BUFFER_SIZE )
81
+ part = socket .recv (BUFFER_SIZE )
67
82
data .extend (part )
68
- if utils .KMPSearch (b"<EOF>" , data ) > - 1 :
83
+
84
+ # Use KMP search to find the <EOF>, KMPSearch() returns -1 if the pattern was not found
85
+ # It is 9 times faster than the simple python search
86
+ if utils .KMPSearch (b"<EOF>" , data ) > - 1 : # Convert "<EOF>" to bytes
69
87
break
88
+
70
89
return data .decode ("utf-8" )
71
90
72
- def setSteering (self , steering : int ) -> None :
91
+
92
+ def setSteering (self ,steering ):
73
93
'''
74
94
Setting the steering of the car
95
+
96
+ Parameters
97
+ ----------
98
+ steering : int
99
+ Steering value in degree
75
100
'''
76
101
self .steering_value = steering
77
102
self .image_mode = 0
@@ -80,9 +105,13 @@ def setSteering(self, steering: int) -> None:
80
105
self .sock .sendall (self .data_str .encode ("utf-8" ))
81
106
time .sleep (0.01 )
82
107
83
- def setSpeed (self , speed : int ) -> None :
108
+ def setSpeed (self ,speed ) :
84
109
'''
85
110
Setting the speed of the car
111
+
112
+ Parameters
113
+ ----------
114
+ speed : int
86
115
'''
87
116
self .speed_value = speed
88
117
self .image_mode = 0
@@ -91,49 +120,61 @@ def setSpeed(self, speed: int) -> None:
91
120
self .sock .sendall (self .data_str .encode ("utf-8" ))
92
121
time .sleep (0.01 )
93
122
94
- def setSensorAngle (self , angle : int ) -> None :
123
+ def setSensorAngle (self , angle ) :
95
124
'''
96
125
Setting the angle between each sensor ray
126
+
127
+ Parameters
128
+ ----------
129
+ angle : int
130
+ In degrees
97
131
'''
132
+
98
133
self .image_mode = 0
99
134
self .sensor_status = 0
100
135
self .sensor_angle = angle
101
136
self .updateData ()
102
137
self .sock .sendall (self .data_str .encode ("utf-8" ))
103
-
104
- def getData (self ) -> None :
138
+
139
+ def getData (self ):
105
140
'''
106
141
Requesting for the data from the simulator
107
142
'''
108
143
self .image_mode = 1
109
144
self .sensor_status = 1
110
145
self .updateData ()
111
146
self .sock .sendall (self .data_str .encode ("utf-8" ))
147
+
112
148
receive = self .recvall (self .sock )
149
+
113
150
imageTagCheck = re .search ('<image>(.*?)<\/image>' , receive )
114
151
sensorTagCheck = re .search ('<sensor>(.*?)<\/sensor>' , receive )
115
- speedTagCheck = re .search ('<speed>(.*?)<\/speed>' , receive )
152
+ speedTagCheck = re .search ('<speed>(.*?)<\/speed>' , receive )
153
+
116
154
try :
117
- if imageTagCheck :
155
+ if ( imageTagCheck ) :
118
156
imageData = imageTagCheck .group (1 )
119
157
im_bytes = base64 .b64decode (imageData )
120
- im_arr = np .frombuffer (im_bytes , dtype = np .uint8 )
158
+ im_arr = np .frombuffer (im_bytes , dtype = np .uint8 ) # im_arr is one-dim Numpy array
121
159
imageOpenCV = cv2 .imdecode (im_arr , flags = cv2 .IMREAD_COLOR )
122
160
self .image = imageOpenCV
123
- if sensorTagCheck :
161
+
162
+ if (sensorTagCheck ):
124
163
sensorData = sensorTagCheck .group (1 )
125
164
sensor_arr = re .findall ("\d+" , sensorData )
126
- sensor_int_arr = list (map (int , sensor_arr ))
165
+ sensor_int_arr = list (map (int , sensor_arr ))
127
166
self .sensors = sensor_int_arr
128
167
else :
129
- self .sensors = [1500 , 1500 , 1500 ]
130
- if speedTagCheck :
168
+ self .sensors = [1500 ,1500 ,1500 ]
169
+
170
+ if (speedTagCheck ):
131
171
current_sp = speedTagCheck .group (1 )
132
172
self .current_speed = int (current_sp )
133
173
else :
134
174
self .current_speed = 0
135
- except Exception as e :
136
- print (f"Failed to receive data: { e } " )
175
+ except :
176
+ print ("Failed to receive data" )
177
+
137
178
138
179
def getImage (self ):
139
180
'''
@@ -144,59 +185,36 @@ def getImage(self):
144
185
def getSensors (self ):
145
186
'''
146
187
Returns the sensor data
188
+ A List:
189
+ [Left Sensor: int, Middle Sensor: int, Right Sensor: int]
147
190
'''
148
191
return self .sensors
149
-
192
+
150
193
def getSpeed (self ):
151
194
'''
152
195
Returns the speed of the car
153
196
'''
154
197
return self .current_speed
155
-
156
- def updateData (self ) -> None :
198
+
199
+ def updateData (self ):
157
200
'''
158
201
Updating the request data array and data string
159
202
'''
160
- data = [self .speed_value , self .steering_value , self .image_mode , self .sensor_status , self .get_Speed , self .sensor_angle ]
161
- self .data_str = self ._data_format .format (* data )
162
-
163
- def stop (self ) -> None :
164
- '''
165
- Stopping the car and closing the socket
166
- '''
167
- try :
168
- self .setSpeed (0 )
169
- self .setSteering (0 )
170
- self .sock .sendall ("stop" .encode ("utf-8" ))
171
- self .sock .close ()
172
- print ("Process stopped successfully!" )
173
- except Exception as e :
174
- print (f"Error during stop: { e } " )
175
-
176
- def is_ready (self ) -> bool :
177
- '''
178
- Check if the car is initialized and ready for operation
203
+ data = [self .speed_value ,self .steering_value ,self .image_mode ,self .sensor_status ,self .get_Speed , self .sensor_angle ]
204
+ self .data_str = self ._data_format .format (data [0 ], data [1 ], data [2 ], data [3 ], data [4 ], data [5 ])
179
205
180
- Returns
181
- -------
182
- bool: True if the car is initialized and ready for operation
206
+ def stop (self ):
183
207
'''
184
- return self ._is_initialized
185
-
186
- def __enter__ (self ):
187
- '''Enable use as a context manager.'''
188
- return self
189
-
190
- def __exit__ (self , exc_type , exc_val , exc_tb ):
191
- '''Ensure resources are cleaned up when exiting context.'''
192
- self .stop ()
193
- return False # Do not suppress exceptions
194
-
208
+ Stoping the car and closing the socket
209
+ '''
210
+ self .setSpeed (0 )
211
+ self .setSteering (0 )
212
+ self .sock .sendall ("stop" .encode ("utf-8" ))
213
+ self .sock .close ()
214
+ print ("Process stopped successfully!" )
215
+
195
216
def __del__ (self ):
196
- try :
197
- self .stop ()
198
- except Exception :
199
- pass
200
-
201
-
202
-
217
+ self .stop ()
218
+
219
+
220
+
0 commit comments