1- import base64
2- import re
31import json
42import cv2
3+ import base64
54import threading
5+ import time
66import numpy as np
7- import matplotlib .pyplot as plt
8-
9- from gui_interfaces .general .measuring_threading_gui import MeasuringThreadingGUI
7+ import math
108from map import Map
11- from HAL import getPose3d , getLiftState
9+ from gui_interfaces .general .measuring_threading_gui_harmonic import (
10+ MeasuringThreadingGUI ,
11+ )
1212from console_interfaces .general .console import start_console
13-
14- # Matrix colors
15- red = [0 , 0 , 255 ]
16- orange = [0 , 165 , 255 ]
17- yellow = [0 , 255 , 255 ]
18- green = [0 , 255 , 0 ]
19- blue = [255 , 0 , 0 ]
20- indigo = [130 , 0 , 75 ]
21- violet = [211 , 0 , 148 ]
22-
23-
13+ from HAL import getPose3d , getOdom
2414class WebGUI (MeasuringThreadingGUI ):
25- def __init__ (self , host = "ws://127.0.0.1:2303" ):
15+ def __init__ (self , host = "ws://127.0.0.1:2303" , freq = 30.0 ):
2616 super ().__init__ (host )
27-
28- self .array_lock = threading .Lock ()
29- self .array = None
30-
31- self .image_to_be_shown = None
32- self .image_to_be_shown_updated = False
33- self .image_show_lock = threading .Lock ()
34-
17+ self .user_map = None
18+ self .image_lock = threading .Lock ()
19+ self .map = Map (getPose3d , getOdom )
3520 # Payload vars
36- self .payload = {"map" : "" , "array" : "" , "liftState" : "" }
37- self .init_coords = (171 , 63 )
38- self .start_coords = (201 , 85.5 )
39- self .map = Map (getPose3d )
40-
21+ self .payload = {"user_map" : "" , "real_pose" : "" }
4122 self .start ()
42-
43- # Prepares and sends a map to the websocket server
23+ # Prepares and send image to the websocket server
4424 def update_gui (self ):
45- self .payload ["array" ] = self .array
46- self .payload ["liftState" ] = getLiftState ()
47-
48- # Payload Map Message
4925 pos_message = self .map .getRobotCoordinates ()
50- ang_message = self .map .getRobotAngle ()
51- pos_message = str (pos_message + ang_message )
52- self .payload ["map" ] = pos_message
53-
54- payload = self .payloadImage ()
55- self .payload ["image" ] = json .dumps (payload )
56-
26+ pos_message = str (pos_message )
27+ self .payload ["real_pose" ] = pos_message
28+ if np .any (self .user_map ):
29+ _ , encoded_image = cv2 .imencode (".JPEG" , self .user_map )
30+ b64 = base64 .b64encode (encoded_image ).decode ("utf-8" )
31+ shape = self .user_map .shape
32+ else :
33+ b64 = None
34+ shape = 0
35+ payload_img = {
36+ "user_map" : b64 ,
37+ "shape" : shape ,
38+ }
39+ self .payload ["user_map" ] = json .dumps (payload_img )
5740 message = json .dumps (self .payload )
5841 self .send_to_client (message )
59-
60- # Process the array(ideal path) to be sent to websocket
61-
62- # Function to prepare image payload
63- # Encodes the image as a JSON string and sends through the WS
64- def payloadImage (self ):
65- with self .image_show_lock :
66- image_to_be_shown_updated = self .image_to_be_shown_updated
67- image_to_be_shown = self .image_to_be_shown
68-
69- image = image_to_be_shown
70- payload = {"image" : "" , "shape" : "" }
71-
72- if not image_to_be_shown_updated :
73- return payload
74-
75- shape = image .shape
76- frame = cv2 .imencode (".JPEG" , image )[1 ]
77- encoded_image = base64 .b64encode (frame )
78-
79- payload ["image" ] = encoded_image .decode ("utf-8" )
80- payload ["shape" ] = shape
81-
82- with self .image_show_lock :
83- self .image_to_be_shown_updated = False
84-
85- return payload
86-
87- def process_colors (self , image ):
88- colored_image = np .zeros ((image .shape [0 ], image .shape [1 ], 3 ), dtype = np .uint8 )
89-
90- # Grayscale for values < 128
91- mask = image < 128
92- colored_image [mask ] = image [mask ][:, None ] * 2
93-
94- # Color lookup table
95- color_table = {
96- 128 : red ,
97- 129 : orange ,
98- 130 : yellow ,
99- 131 : green ,
100- 132 : blue ,
101- 133 : indigo ,
102- 134 : violet ,
103- }
104-
105- for value , color in color_table .items ():
106- mask = image == value
107- colored_image [mask ] = color
108-
109- return colored_image
110-
111- # load the image data
112- def showNumpy (self , image ):
113- with self .image_show_lock :
114- self .image_to_be_shown = self .process_colors (image )
115- self .image_to_be_shown_updated = True
116-
117- def showPath (self , array ):
118- array_scaled = []
119- for wp in array :
120- array_scaled .append ([wp [0 ] * 0.72 , wp [1 ] * 0.545 ])
121-
122- print ("Path array: " + str (array_scaled ))
123- self .array_lock .acquire ()
124-
125- strArray = "" .join (str (e ) for e in array_scaled )
126- print ("strArray: " + str (strArray ))
127-
128- # Remove unnecesary spaces in the array to avoid JSON syntax error in javascript
129- strArray = re .sub (r"\[[ ]+" , "[" , strArray )
130- strArray = re .sub (r"[ ]+" , ", " , strArray )
131- strArray = re .sub (r",[ ]+]" , "]" , strArray )
132- strArray = re .sub (r",," , "," , strArray )
133- strArray = re .sub (r"]\[" , "],[" , strArray )
134- strArray = "[" + strArray + "]"
135- print ("strArray2: " + str (strArray ))
136-
137- self .array = strArray
138- self .array_lock .release ()
139-
140- def getMap (self , url ):
141- return plt .imread (url )
142-
143-
42+ # Function to set the next image to be sent
43+ def setUserMap (self , image ):
44+ if image .shape [0 ] != 970 or image .shape [1 ] != 1500 :
45+ raise ValueError (
46+ "map passed has the wrong dimensions, it has to be 970 pixels high and 1500 pixels wide"
47+ )
48+ processed_image = np .stack ((image ,) * 3 , axis = - 1 )
49+ with self .image_lock :
50+ self .user_map = processed_image
51+ def poseToMap (self , x_prime , y_prime , yaw_prime ):
52+ y = - 23.58 * (- 20.36 - x_prime )
53+ x = - 23.53 * (- 31.95 - y_prime )
54+ yaw = yaw_prime - math .pi / 2
55+ return [round (x ), round (y ), yaw ]
14456host = "ws://127.0.0.1:2303"
14557gui = WebGUI (host )
146-
14758# Redirect the console
14859start_console ()
149-
150-
151- def showPath (array ):
152- return gui .showPath (array )
153-
154-
155- def showNumpy (image ):
156- gui .showNumpy (image )
157-
158-
159- def getMap (url ):
160- return gui .getMap (url )
60+ # Expose the user functions
61+ def setUserMap (image ):
62+ gui .setUserMap (image )
63+ def poseToMap (x_prime , y_prime , yaw_prime ):
64+ return gui .poseToMap (x_prime , y_prime , yaw_prime )
0 commit comments