8 import _thread
as thread
13 from datetime
import datetime, timedelta
20 from std_msgs.msg
import String
21 from std_msgs.msg
import Float64
22 from geometry_msgs.msg
import Point
23 from geometry_msgs.msg
import Quaternion
24 from amr_interop_msgs.msg
import Location
25 from amr_interop_msgs.msg
import Velocity
26 from amr_interop_msgs.msg
import ErrorCodes
27 from amr_interop_msgs.msg
import PredictedLocation
28 from amr_interop_msgs.msg
import PredictedLocations
32 rospy.loginfo(message)
37 def on_close(ws, close_status_code, close_msg):
38 rospy.loginfo(
"### closed ###")
42 identity[
"timestamp"] = datetime.now(pytz.utc).strftime(
"%Y-%m-%dT%H:%M:%S%z")
43 ws.send(json.dumps(identity))
47 status[
"timestamp"] = datetime.now(pytz.utc).strftime(
"%Y-%m-%dT%H:%M:%S%z")
48 ws.send(json.dumps(status))
52 thread.start_new_thread(run, ())
55 identity[
"uuid"] = msg.data
56 status[
"uuid"] = msg.data
59 identity[
"manufacturerName"] = msg.data
62 identity[
"robotModel"] = msg.data
65 identity[
"robotSerialNumber"] = msg.data
68 if "baseRobotEnvelope" not in identity:
69 identity[
"baseRobotEnvelope"] = {}
71 identity[
"baseRobotEnvelope"][
"x"] = msg.x
72 identity[
"baseRobotEnvelope"][
"y"] = msg.y
73 if not math.isnan(msg.z):
74 identity[
"baseRobotEnvelope"][
"z"] = msg.z
77 identity[
"maxSpeed"] = msg.data
80 identity[
"maxRunTime"] = msg.data
83 identity[
"emergencyContactInformation"] = msg.data
86 identity[
"chargerType"] = msg.data
89 identity[
"supportVendorName"] = msg.data
92 identity[
"supportVendorContactInformation"] = msg.data
95 identity[
"productDocumentation"] = msg.data
98 identity[
"thumbnailImage"] = msg.data
101 identity[
"cargoType"] = msg.data
104 if "cargoMaxVolume" not in identity:
105 identity[
"cargoMaxVolume"] = {}
107 identity[
"cargoMaxVolume"][
"x"] = msg.x
108 identity[
"cargoMaxVolume"][
"y"] = msg.y
109 if not math.isnan(msg.z):
110 identity[
"cargoMaxVolume"][
"z"] = msg.z
113 identity[
"cargoMaxWeight"] = msg.data
116 status[
"operationalState"] = msg.data
119 if "location" not in identity:
120 status[
"location"] = {}
122 status[
"location"][
"x"] = msg.x
123 status[
"location"][
"y"] = msg.y
124 if math.isnan(msg.z):
125 status[
"location"].pop(
"z",
None)
127 status[
"location"][
"z"] = msg.z
128 status[
"location"][
"angle"] = {}
129 status[
"location"][
"angle"][
"x"] = msg.angle.x
130 status[
"location"][
"angle"][
"y"] = msg.angle.y
131 status[
"location"][
"angle"][
"z"] = msg.angle.z
132 status[
"location"][
"angle"][
"w"] = msg.angle.w
134 status[
"location"][
"planarDatum"] = msg.planar_datum
137 if "velocity" not in identity:
138 status[
"velocity"] = {}
140 status[
"velocity"][
"linear"] = msg.linear
142 if math.isnan(msg.angular.x)
or \
143 math.isnan(msg.angular.y)
or \
144 math.isnan(msg.angular.z)
or \
145 math.isnan(msg.angular.w):
146 status[
"velocity"].pop(
"angular",
None)
148 status[
"velocity"][
"angular"] = {}
149 status[
"velocity"][
"angular"][
"x"] = msg.angular.x
150 status[
"velocity"][
"angular"][
"y"] = msg.angular.y
151 status[
"velocity"][
"angular"][
"z"] = msg.angular.z
152 status[
"velocity"][
"angular"][
"w"] = msg.angular.w
155 status[
"batteryPercentage"] = msg.data
158 status[
"remainingRunTime"] = msg.data
161 status[
"loadPercentageStillAvailable"] = msg.data
164 if len(msg.data) > 0:
165 status[
"errorCodes"] = msg.data
168 if len(msg.data) > 0:
171 for i
in range(len(msg.data)):
173 path[
"timestamp"] = msg.data[i].timestamp
174 path[
"x"] = msg.data[i].x
175 path[
"y"] = msg.data[i].y
176 if not math.isnan(msg.data[i].z):
177 path[
"z"] = msg.data[i].z
179 path[
"angle"][
"x"] = msg.data[i].angle.x
180 path[
"angle"][
"y"] = msg.data[i].angle.y
181 path[
"angle"][
"z"] = msg.data[i].angle.z
182 path[
"angle"][
"w"] = msg.data[i].angle.w
183 path[
"planarDatumUUID"] = msg.data[i].planar_datum_uuid
185 status[
"path"].append(path)
188 if len(msg.data) > 0:
189 status[
"destinations"] = []
191 for i
in range(len(msg.data)):
193 path[
"timestamp"] = msg.data[i].timestamp
194 path[
"x"] = msg.data[i].x
195 path[
"y"] = msg.data[i].y
196 if not math.isnan(msg.data[i].z):
197 path[
"z"] = msg.data[i].z
199 path[
"angle"][
"x"] = msg.data[i].angle.x
200 path[
"angle"][
"y"] = msg.data[i].angle.y
201 path[
"angle"][
"z"] = msg.data[i].angle.z
202 path[
"angle"][
"w"] = msg.data[i].angle.w
203 path[
"planarDatumUUID"] = msg.data[i].planar_datum_uuid
205 status[
"destinations"].append(path)
207 if __name__ ==
"__main__":
208 rospy.init_node(
"amr_interop_bridge")
210 url = rospy.get_param(
"~url",
"ws://localhost/")
215 rospy.Subscriber(
"uuid", String, uuid_callback)
216 rospy.Subscriber(
"manufacture_name", String, manufacture_name_callback)
217 rospy.Subscriber(
"robot_model", String, robot_model_callback)
218 rospy.Subscriber(
"robot_serial_number", String, robot_serial_number_callback)
219 rospy.Subscriber(
"base_robot_envelope", Point, base_robot_envelope_callback)
220 rospy.Subscriber(
"max_speed", Float64, max_speed_callback)
221 rospy.Subscriber(
"max_run_time", Float64, max_run_time_callback)
222 rospy.Subscriber(
"emergency_contact_information", String, emergency_contact_information_callback)
223 rospy.Subscriber(
"charger_type", String, charger_type_callback)
224 rospy.Subscriber(
"support_vendor_name", String, support_vendor_name_callback)
225 rospy.Subscriber(
"support_vendor_contact_information", String, support_vendor_contact_information_callback)
226 rospy.Subscriber(
"product_documentation", String, product_documentation_callback)
227 rospy.Subscriber(
"thumbnail_image", String, thumbnail_image_callback)
228 rospy.Subscriber(
"cargo_type", String, cargo_type_callback)
229 rospy.Subscriber(
"cargo_max_volume", Point, cargo_max_volume_callback)
230 rospy.Subscriber(
"cargo_max_weight", String, cargo_max_weight_callback)
232 rospy.Subscriber(
"operational_state", String, operational_state_callback)
233 rospy.Subscriber(
"location", Location, location_callback)
234 rospy.Subscriber(
"velocity", Velocity, velocity_callback)
235 rospy.Subscriber(
"battery_percentage", Float64, battery_percentage_callback)
236 rospy.Subscriber(
"remaining_run_time", Float64, remaining_run_time_callback)
237 rospy.Subscriber(
"load_percentage_still_avaiable", Float64, load_percentage_still_avaiable_callback)
238 rospy.Subscriber(
"error_codes", ErrorCodes, error_codes_callback)
239 rospy.Subscriber(
"path", PredictedLocations, path_callback)
240 rospy.Subscriber(
"destinations", PredictedLocations, destinations_callback)
244 ws = websocket.WebSocketApp(url,
246 on_message=on_message,