jointstick_setup.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 import os
3 import yaml
4 import rospy
5 import datetime
6 import threading
7 from sensor_msgs.msg import Joy
8 from controller_manager_msgs.srv import ListControllers
9 
10 # Imports from custom files of this package
11 from helper import *
12 from controllers_info import *
13 
14 try:
15  import msvcrt
16 except ImportError:
17  import sys, termios
18 
19 ui = [None] # mutable hack. Thanks python!
20 
21 # Translate Twist message fields to selection text
23  m = "Choose an axis to move with your current joy binding:\n"
24  m += "0. linear.x\t1. linear.y\t2. linear.z\n"
25  m += "3. angular.x\t4. angular.y\t5. angular.z\n"
26  return m
27 
28 # Translate JointTrajectory message fields to selection text
30  m = "Choose a category to move with your current joy binding:\n"
31  m += "0. position\t1. velocity\n"
32  m += "2. acceleration\t3. effort\n"
33  return m
34 
35 # Translate a joyAction object to a dict for yaml
36 def joyActionsToDict(actions):
37  d = dict()
38  for i, action in enumerate(actions):
39  d[i] = {"button": action.button,
40  "axis": action.axis,
41  "value": action.value,
42  "joint": action.joint,
43  "msg_field": action.msg_field
44  }
45  return d
46 
47 # Translate the list of controllers to a dict for yaml
49  d = dict()
50  for controller in controllers:
51  if controller.joyActions:
52  d[controller.name] = {"type": controller.type,
53  "topic": controller.topic,
54  "actions": joyActionsToDict(controller.joyActions)
55  }
56  return d
57 
58 # Save the list of controllers to a .yaml file
59 def save():
60  print("Saving...")
61  filename = config_file_location+ os.sep+"config_"+datetime.datetime.now().strftime("%d-%m-%Y_%H-%M-%S")+".yaml"
62  with open(filename, "w") as outfile:
63  yaml.dump(controllersToDict(), outfile, default_flow_style=False)
64  print("Success!")
65  print("Saved at {}".format(filename))
66 
67 # Python agnostic user input with accepted answers support
68 def youTalkinToMe(prompt, accepted_ans):
69  while(True):
70  flush()
71  print(prompt)
72  if accepted_ans:
73  print("(Accepted answers: {})".format(accepted_ans))
74  inp = ""
75  try:
76  # Python 2
77  inp = raw_input()
78  except:
79  # Python 3
80  inp = input()
81  if not accepted_ans or inp in accepted_ans:
82  return inp
83 
84 # Python agnostic user input for floats
86  while(True):
87  flush()
88  print(prompt)
89  inp = ""
90  try:
91  # Python 2
92  inp = raw_input()
93  except:
94  # Python 3
95  inp = input()
96  try:
97  return float(inp)
98  except:
99  print("Please provide a number!")
100 
101 # Python agnostic user input to be run in a thread
103  global ui
104  print(prompt)
105  while(read_joy):
106  flush()
107  if saved_buti != -1 or saved_axi != -1:
108  try:
109  # Python 2
110  ui[0] = raw_input()
111  except:
112  # Python 3
113  ui[0] = input()
114 
115 # Translate user joystick input to human readable text
116 # Also, offer the expected behaviour when unpressing buttons/axes
117 # or when pressing new buttons/axes that need to delete old ones
118 def joyInLife(msg):
119  global saved_axi, saved_buti
120  max_ax = max(map(abs, msg.axes))
121  axis_i = -1
122  button_i = -1
123  if min(msg.axes) == -max_ax and max_ax !=0:
124  axis_i = -1 if max_ax == 0 else msg.axes.index(-max_ax)
125  elif max_ax != 0:
126  axis_i = -1 if max_ax == 0 else msg.axes.index(max_ax)
127  if 1 in msg.buttons:
128  button_i = msg.buttons.index(1)
129  combo = None
130  if button_i != -1 and button_i != saved_buti:
131  saved_axi = -1
132  if axis_i != -1 and axis_i != saved_axi:
133  saved_buti = -1
134  saved_buti = button_i if button_i != -1 else saved_buti
135  saved_axi = axis_i if axis_i != -1 else saved_axi
136  if saved_axi >= 0:
137  combo = "[Axis{}]".format(saved_axi)
138  if saved_buti >= 0:
139  if combo is not None:
140  combo += "+[Button{}]".format(saved_buti)
141  else:
142  combo = "[Button{}]".format(saved_buti)
143  return combo
144 
145 # The joystic callback
146 def joyCallback(msg):
147  if read_joy:
148  clear()
149  print("Controls for {}".format(curr_controller.name))
150  print(joyInLife(msg))
151  if saved_axi != -1 or saved_buti != -1:
152  print("Press enter on your keyboard to continue with the current configuration...")
153 
154 # OS agnostic terminal clearance
155 def clear():
156  os.system("cls" if os.name == "nt" else "clear")
157 
158 # OS agnostic terminal flushing
159 def flush():
160  try:
161  while msvcrt.kbhit():
162  msvcrt.getch()
163  except:
164  termios.tcflush(sys.stdin, termios.TCIOFLUSH)
165 
166 # The main setup procedure
168  global read_joy, keepItUp, curr_controller, saved_buti, saved_axi, ui
169  ans = youTalkinToMe("Do you want to see all the discovered controllers?", YES+NO+QUIT)
170  if ans in YES:
171  print(controllers)
172  print("---")
173  elif ans in QUIT:
174  keepItUp = False
175  return
176  print("Initiating joystick configuration...")
177  youTalkinToMe("Press any enter to continue...", [])
178  clear()
179  for controller in controllers:
180  cnt = 0
181  if controller.type in supported_controllers:
182  while(True):
183  ans = ""
184  if cnt == 0:
185  ans = youTalkinToMe("Do you want to assign a joystick command to {}?".format(controller.name), YES+NO+QUIT)
186  else:
187  ans = youTalkinToMe("Do you want to assign another joystick command to {}?".format(controller.name), YES+NO+QUIT)
188  if ans in QUIT:
189  keepItUp = False
190  return
191  elif ans in YES:
192  curr_controller = controller
193  for joint in controller.joints:
194  msg_field = ""
195  if controller.type in ignore_controller_joints:
196  ans = "y"
197  else:
198  ans = youTalkinToMe("[{}] Do you want to assign a joystick command to {}?".format(controller.name, joint), YES+NO+QUIT)
199  if ans in YES:
200  cnt += 1
201  read_joy = True
202  print("Now use your controller to set a new configuration...")
203  t = threading.Thread(target=youTalkinToMeAboutThreads, args=("Don't touch your keyboard now!",))
204  t.deamon = True
205  t.start()
206  while read_joy and keepItUp and not rospy.is_shutdown():
207  if ui[0] is not None and (saved_axi != -1 or saved_buti != -1):
208  read_joy = False
209 
210  if controller.type in twist_controllers:
211  ans = youTalkinToMe(twistToText(), list(twisty_dict.keys()))
212  msg_field = twisty_dict[ans]
213  elif controller.type in joint_traj_controllers:
214  ans = youTalkinToMe(jointTrajToText(), list(jt_dict.keys()))
215  msg_field = jt_dict[ans]
216 
217  val = -1
218  if controller.type not in non_step_controllers:
219  val = youTalkinToMeAboutFloats("Please provide a joint step value:")
220  else:
221  val = youTalkinToMeAboutFloats("Please provide a cmd_vel value:")
222 
223  ans = youTalkinToMe("Do you want to save the current joy binding?", YES+NO+QUIT)
224  if ans in YES:
225  controller.joyActions.append(JoyAction(saved_buti, saved_axi, val, joint, msg_field))
226  print("Saved! (Not on disk yet!)")
227  print("---")
228  elif ans in QUIT:
229  keepItUp = False
230  return
231  ui = [None]
232  saved_buti = -1
233  saved_axi = -1
234  if controller.type in ignore_controller_joints:
235  break
236  elif ans in QUIT:
237  keepItUp = False
238  return
239  elif ans in NO:
240  break
241 
242  while(keepItUp):
243  ans = youTalkinToMe("Do you want to save your configuration?", YES+NO+QUIT)
244  if ans in YES:
245  save()
246  keepItUp = False
247  elif ans in QUIT:
248  keepItUp = False
249  elif ans in NO:
250  ans = youTalkinToMe("Are you sure?", YES+NO+QUIT)
251  if ans in YES or ans in QUIT:
252  keepItUp = False
253 
254 # Initialisations and other boring stuff
255 def main():
256  global config_file_location
257  rospy.init_node("jointstick_setup")
258  config_file_location = rospy.get_param("config_file_location", os.path.expanduser("~"))
259  print("Config file save location was set as: {}".format(config_file_location))
260  rospy.Subscriber("/joy", Joy, joyCallback)
261  controllers_srv = rospy.ServiceProxy("controller_manager/list_controllers", ListControllers)
262 
263  print("Reading available controllers....")
264 
265  rospy.wait_for_service("controller_manager/list_controllers")
266 
267  c = controllers_srv().controller
268 
269  for controller in c:
270  if controller.type != "joint_state_controller/JointStateController":
271  controllers.append(Controller(controller.name, controller.type, [], controller.claimed_resources[0].resources, controller.name+topic_extension[controller.type]))
272 
273  print("Done!")
274 
276 
277  while not rospy.is_shutdown() and keepItUp:
278  rospy.spin()
279  print("Byeee!")
280 
281 main()
def youTalkinToMeAboutFloats(prompt)
def youTalkinToMe(prompt, accepted_ans)
def youTalkinToMeAboutThreads(prompt)
def joyActionsToDict(actions)


jointstick
Author(s): George Stavrinos
autogenerated on Mon Jun 10 2019 13:38:17