server.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # coding:utf-8
3 # The MIT License (MIT)
4 #
5 # Copyright (c) 2018 Bluewhale Robot
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in all
15 # copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24 #
25 # Author: Xie fusheng
26 # Randoms
27 
28 
29 
30 
31 import commands
32 import math
33 import os
34 import signal
35 import struct
36 import subprocess
37 import sys
38 import threading
39 import time
40 from socket import (AF_INET, SO_BROADCAST, SOCK_DGRAM, SOL_SOCKET, socket,
41  timeout)
42 
43 import numpy as np
44 import psutil
45 import rospy
46 import tf
47 from geometry_msgs.msg import Pose, Pose2D, Twist
48 from nav_msgs.msg import Odometry
49 from sensor_msgs.msg import Image
50 from std_msgs.msg import Bool, Float64, Int16, String, UInt32
51 from tf.transformations import euler_from_quaternion, quaternion_from_euler
52 from xiaoqiang_msgs.msg import Status
53 
54 HOST = '' # should not be 127.0.0.1 or localhost
55 USER_SOCKET_PORT = 20001 # 局域网udp命令监听端口
56 USER_SOCKET_REMOTE = None
57 USER_SERVER_SOCKET = None
58 BUFSIZE = 1024
59 
60 PACKAGE_HEADER = [205, 235, 215]
61 DATA_CACHE = []
62 
63 CMD_PUB = None
64 MAP_SAVE_PUB = None
65 
66 MAX_VEL = 0.8
67 MAX_THETA = 3.6
68 STATUS = Status()
69 STATUS.brightness = 0.0
70 STATUS.image_status = False
71 STATUS.odom_status = False
72 STATUS.orb_start_status = False
73 STATUS.orb_init_status = False
74 STATUS.power = 0.0
75 STATUS.orb_scale_status = False
76 POWER_LOW = 10.0
77 
78 STATUS_LOCK = threading.Lock()
79 
80 DATA_CACHE = []
81 CURRENT_POSE = Pose()
82 SEND_DATA = bytearray([205, 235, 215, 24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
84 SPEED_CMD = Twist()
85 
86 MAP_THREAD = None
87 NAV_THREAD = None
88 CONTROL_FLAG = False
89 
90 SCALE_ORB_THREAD = None
91 GLOBAL_MOVE_PUB = None
92 EVEVATOR_PUB = None
93 
94 TILT_PUB = None
95 MAV_LAST_TIME = None
96 
97 
98 def unpack_req(req):
99  global DATA_CACHE
100  res = []
101  package_list = split_req(req)
102  # process the first package
103  completeData = DATA_CACHE + package_list[0]
104  package_list.remove(package_list[0])
105  package_list = split_req(completeData) + package_list
106 
107  for count in range(0, len(package_list)):
108  if len(package_list[count]) != 0 and len(package_list[count]) == package_list[count][0] + 1:
109  res.append(package_list[count][1:])
110  last_one = package_list[-1:][0] # the last one
111  if len(last_one) == 0 or len(last_one) != last_one[0] + 1:
112  DATA_CACHE = last_one
113  return res
114 
115 
117  if len(req) < 3:
118  return -1
119  for count in range(0, len(req) - 2):
120  if req[count] == PACKAGE_HEADER[0] and req[count + 1] == PACKAGE_HEADER[1] and req[count + 2] == PACKAGE_HEADER[2]:
121  return count
122  return -1
123 
124 
125 def split_req(req):
126  res = []
127  start_index = 0
128  new_index = 0
129  while True:
130  new_index = find_package_header(req[start_index:])
131  if new_index == -1:
132  break
133  res.append(req[start_index: start_index + new_index])
134  start_index = new_index + 3 + start_index
135  res.append(req[start_index:])
136  return res
137 
138 
139 def parse_data(cmds):
140  global CONTROL_FLAG
141  res = None
142  for count in range(0, len(cmds)):
143  if len(cmds[count]) > 0:
144  CONTROL_FLAG = True
145  # 判断是否为关机命令
146  if len(cmds[count]) == 2:
147  global_move_flag = Bool()
148  global_move_flag.data = True
149 
150  if cmds[count][0] == 0xaa and cmds[count][1] == 0x44:
151  rospy.loginfo("system poweroff")
152  commands.getstatusoutput(
153  '/sbin/shutdown -h now')
154 
155  if cmds[count][0] == ord('f'):
156  rospy.loginfo("forward")
157  GLOBAL_MOVE_PUB.publish(global_move_flag)
158  SPEED_CMD.linear.x = MAX_VEL*cmds[count][1]/100.0
159  CMD_PUB.publish(SPEED_CMD)
160  elif cmds[count][0] == ord('b'):
161  rospy.loginfo("back")
162  GLOBAL_MOVE_PUB.publish(global_move_flag)
163  SPEED_CMD.linear.x = -MAX_VEL*cmds[count][1]/100.0
164  CMD_PUB.publish(SPEED_CMD)
165  elif cmds[count][0] == ord('c'):
166  rospy.loginfo("circleleft")
167  GLOBAL_MOVE_PUB.publish(global_move_flag)
168  SPEED_CMD.angular.z = MAX_THETA*cmds[count][1]/100.0/2.8
169  CMD_PUB.publish(SPEED_CMD)
170  elif cmds[count][0] == ord('d'):
171  rospy.loginfo("circleright")
172  GLOBAL_MOVE_PUB.publish(global_move_flag)
173  SPEED_CMD.angular.z = -MAX_THETA*cmds[count][1]/100.0/2.8
174  CMD_PUB.publish(SPEED_CMD)
175  elif cmds[count][0] == ord('s'):
176  rospy.loginfo("stop")
177  SPEED_CMD.linear.x = 0
178  SPEED_CMD.angular.z = 0
179  CMD_PUB.publish(SPEED_CMD)
180  return res
181 
182 
183 class UserServer(threading.Thread):
184  # 接收udp命令的socket
185  def __init__(self):
186  global USER_SERVER_SOCKET
187  super(UserServer, self).__init__()
188  self._stop = threading.Event()
189  USER_SERVER_SOCKET = socket(AF_INET, SOCK_DGRAM)
190  USER_SERVER_SOCKET.bind((HOST, USER_SOCKET_PORT))
191 
192  def stop(self):
193  if USER_SERVER_SOCKET != None:
194  USER_SERVER_SOCKET.close()
195  self._stop.set()
196 
197  def stopped(self):
198  return self._stop.isSet()
199 
200  def run(self):
201  global USER_SOCKET_REMOTE
202  USER_SERVER_SOCKET.settimeout(2) # 设置udp 2秒超时 等待
203  while not self.stopped() and not rospy.is_shutdown():
204  try:
205  data, USER_SOCKET_REMOTE = USER_SERVER_SOCKET.recvfrom(BUFSIZE)
206  except timeout:
207  continue
208  if not data:
209  break
210  dataList = []
211  for c in data:
212  dataList.append(ord(c))
213  parse_data(unpack_req(dataList)) # 处理命令数据
214  self.stop()
215 
216 
217 def get_power(power):
218  STATUS_LOCK.acquire()
219  STATUS.power = power.data
220  STATUS_LOCK.release()
221 
222 
223 def get_image(image):
224  STATUS_LOCK.acquire()
225  if image != None:
226  STATUS.image_status = True
227  else:
228  STATUS.image_status = False
229  STATUS_LOCK.release()
230 
231 
232 def get_odom(odom):
233  global CURRENT_POSE
234  STATUS_LOCK.acquire()
235  if odom != None:
236  STATUS.odom_status = True
237  CURRENT_POSE = odom.pose.pose # 更新坐标
238 
239  else:
240  STATUS.odom_status = False
241  STATUS_LOCK.release()
242 
243 
244 def get_orb_start_status(orb_frame):
245  STATUS_LOCK.acquire()
246  if orb_frame != None:
247  STATUS.orb_start_status = True
248  else:
249  STATUS.orb_start_status = False
250  STATUS_LOCK.release()
251 
252 
253 def get_orb_tracking_flag(camera_pose):
254  STATUS_LOCK.acquire()
255  if camera_pose != None:
256  STATUS.orb_init_status = True
257  else:
258  STATUS.orb_init_status = False
259  STATUS_LOCK.release()
260 
261 
262 def get_global_move_flag(move_enable):
263  if not move_enable.data:
264  # 关闭视觉导航
265  if not NAV_THREAD.stopped():
266  NAV_THREAD.stop()
267 
268 
269 def broadcast():
270  global CMD_PUB, GLOBAL_MOVE_PUB, MAV_LAST_TIME
271  rospy.init_node("broadcast", anonymous=True)
272  MAV_LAST_TIME = rospy.Time.now()
273  rospy.Subscriber("/xiaoqiang_driver/power", Float64, get_power)
274  rospy.Subscriber("/usb_cam/image_raw", Image, get_image)
275  rospy.Subscriber("/xiaoqiang_driver/odom", Odometry, get_odom)
276  rospy.Subscriber("/orb_slam/camera", rospy.msg.AnyMsg, get_orb_tracking_flag)
277  rospy.Subscriber("/orb_slam/frame", Image, get_orb_start_status)
278  rospy.Subscriber("/xiaoqiang_driver/global_move_flag",
279  Bool, get_global_move_flag)
280  GLOBAL_MOVE_PUB = rospy.Publisher("/xiaoqiang_driver/global_move_flag", Bool, queue_size=1)
281  CMD_PUB = rospy.Publisher('/xiaoqiang_driver/cmd_vel', Twist, queue_size=0)
282 
283 
284 if __name__ == "__main__":
285  broadcast()
286  rate = rospy.Rate(10)
287  # 配置udp广播
288  MYPORT = 22001 # 广播端口
289  s = socket(AF_INET, SOCK_DGRAM)
290  s.bind(('', 0))
291  s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
292  # 开启udp接收监听线程
293  user_server_thread = UserServer()
294  user_server_thread.start()
295  i = 10
296  ii = 40
297  cmd4 = "aplay /home/xiaoqiang/Desktop/d.wav"
298  while not rospy.is_shutdown():
299  # #每2秒提示一下
300  # if ii==10:
301  # subprocess.Popen(cmd4,shell=True)
302 
303  # if not control_flag and ii>32 and ii<37:
304  # speed_cmd.linear.x = 0
305  # speed_cmd.angular.z = 0
306  # cmd_pub.publish(speed_cmd)
307  # 每4秒心跳维护一次
308  if ii == 40:
309  ii = 0
310  CONTROL_FLAG = False
311  ii += 1
312  # 持续反馈状态
313  if USER_SOCKET_REMOTE != None and USER_SERVER_SOCKET != None:
314 
315  SEND_DATA[4:8] = map(ord, struct.pack('f', 0.0))
316  SEND_DATA[8:12] = map(ord, struct.pack('f', 0.0))
317  SEND_DATA[12:16] = map(ord, struct.pack('f', 0.0))
318  SEND_DATA[16:20] = map(ord, struct.pack('f', STATUS.power))
319  SEND_DATA[24:28] = map(ord, struct.pack('f', 0.0))
320  if STATUS.odom_status:
321  statu0 = 0x01 # 混合里程计
322  else:
323  statu0 = 0x00
324  if STATUS.image_status:
325  statu1 = 0x02 # 视觉摄像头
326  else:
327  statu1 = 0x00
328  if STATUS.orb_start_status:
329  statu2 = 0x04 # 视觉系统状态
330  else:
331  statu2 = 0x00
332  if STATUS.orb_init_status:
333  statu3 = 0x08 # 视觉系统状态
334  else:
335  statu3 = 0x00
336  SEND_DATA[20] = statu0 + statu1 + statu2 + statu3
337  try:
338  USER_SERVER_SOCKET.sendto(bytes(SEND_DATA), USER_SOCKET_REMOTE)
339  except:
340  print "remote disconnect !\n"
341 
342  # 每秒广播一次
343  if i == 10:
344  i = 0
345  data = "xq"
346  # 发送广播包
347  try:
348  s.sendto(data, ('<broadcast>', MYPORT))
349  except:
350  continue
351  # clear data
352  STATUS.power = 0.0
353  STATUS.orb_init_status = False
354  STATUS.orb_start_status = False
355  STATUS.image_status = False
356  STATUS.odom_status = False
357  i += 1
358  rate.sleep()
359  user_server_thread.stop()
def find_package_header(req)
Definition: server.py:116
def get_global_move_flag(move_enable)
Definition: server.py:262
def get_odom(odom)
Definition: server.py:232
def __init__(self)
Definition: server.py:185
def get_power(power)
Definition: server.py:217
def stop(self)
Definition: server.py:192
def get_orb_start_status(orb_frame)
Definition: server.py:244
def split_req(req)
Definition: server.py:125
def get_orb_tracking_flag(camera_pose)
Definition: server.py:253
def get_image(image)
Definition: server.py:223
def stopped(self)
Definition: server.py:197
def run(self)
Definition: server.py:200
def broadcast()
Definition: server.py:269
def parse_data(cmds)
Definition: server.py:139
def unpack_req(req)
Definition: server.py:98


xiaoqiang_server
Author(s):
autogenerated on Mon Jun 10 2019 15:53:41