joy_remap.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 # Author: furushchev <furushchev@jsk.imi.i.u-tokyo.ac.jp>
4 
5 import ast
6 import operator as op
7 import rospy
8 import traceback
9 from sensor_msgs.msg import Joy
10 
11 
12 class RestrictedEvaluator(object):
13  def __init__(self):
14  self.operators = {
15  ast.Add: op.add,
16  ast.Sub: op.sub,
17  ast.Mult: op.mul,
18  ast.Div: op.truediv,
19  ast.BitXor: op.xor,
20  ast.USub: op.neg,
21  }
22  self.functions = {
23  'abs': lambda x: abs(x),
24  'max': lambda *x: max(*x),
25  'min': lambda *x: min(*x),
26  }
27 
28  def _reval_impl(self, node, variables):
29  if isinstance(node, ast.Num):
30  return node.n
31  elif isinstance(node, ast.BinOp):
32  op = self.operators[type(node.op)]
33  return op(self._reval_impl(node.left, variables),
34  self._reval_impl(node.right, variables))
35  elif isinstance(node, ast.UnaryOp):
36  op = self.operators[type(node.op)]
37  return op(self._reval_impl(node.operand, variables))
38  elif isinstance(node, ast.Call) and node.func.id in self.functions:
39  func = self.functions[node.func.id]
40  args = [self._reval_impl(n, variables) for n in node.args]
41  return func(*args)
42  elif isinstance(node, ast.Name) and node.id in variables:
43  return variables[node.id]
44  elif isinstance(node, ast.Subscript) and node.value.id in variables:
45  var = variables[node.value.id]
46  idx = node.slice.value.n
47  try:
48  return var[idx]
49  except IndexError:
50  raise IndexError("Variable '%s' out of range: %d >= %d" % (node.value.id, idx, len(var)))
51  else:
52  raise TypeError("Unsupported operation: %s" % node)
53 
54  def reval(self, expr, variables):
55  expr = str(expr)
56  if len(expr) > 1000:
57  raise ValueError("The length of an expression must not be more than 1000 characters")
58  try:
59  return self._reval_impl(ast.parse(expr, mode='eval').body, variables)
60  except Exception as e:
61  rospy.logerr(traceback.format_exc())
62  raise e
63 
64 
65 class JoyRemap(object):
66  def __init__(self):
68  self.mappings = self.load_mappings("~mappings")
69  self.warn_remap("joy_out")
70  self.pub = rospy.Publisher(
71  "joy_out", Joy, queue_size=1)
72  self.warn_remap("joy_in")
73  self.sub = rospy.Subscriber(
74  "joy_in", Joy, self.callback,
75  queue_size=rospy.get_param("~queue_size", None))
76 
77  def load_mappings(self, ns):
78  btn_remap = rospy.get_param(ns + "/buttons", [])
79  axes_remap = rospy.get_param(ns + "/axes", [])
80  rospy.loginfo("loaded remapping: %d buttons, %d axes" % (len(btn_remap), len(axes_remap)))
81  return {"buttons": btn_remap, "axes": axes_remap}
82 
83  def warn_remap(self, name):
84  if name == rospy.remap_name(name):
85  rospy.logwarn("topic '%s' is not remapped" % name)
86 
87  def callback(self, in_msg):
88  out_msg = Joy(header=in_msg.header)
89  map_axes = self.mappings["axes"]
90  map_btns = self.mappings["buttons"]
91  out_msg.axes = [0.0] * len(map_axes)
92  out_msg.buttons = [0] * len(map_btns)
93  in_dic = {"axes": in_msg.axes, "buttons": in_msg.buttons}
94  for i, exp in enumerate(map_axes):
95  try:
96  out_msg.axes[i] = self.evaluator.reval(exp, in_dic)
97  except NameError as e:
98  rospy.logerr("You are using vars other than 'buttons' or 'axes': %s" % e)
99  except UnboundLocalError as e:
100  rospy.logerr("Wrong form: %s" % e)
101  except Exception as e:
102  raise e
103 
104  for i, exp in enumerate(map_btns):
105  try:
106  if self.evaluator.reval(exp, in_dic) > 0:
107  out_msg.buttons[i] = 1
108  except NameError as e:
109  rospy.logerr("You are using vars other than 'buttons' or 'axes': %s" % e)
110  except UnboundLocalError as e:
111  rospy.logerr("Wrong form: %s" % e)
112  except Exception as e:
113  raise e
114 
115  self.pub.publish(out_msg)
116 
117 
118 if __name__ == '__main__':
119  rospy.init_node("joy_remap")
120  n = JoyRemap()
121  rospy.spin()
joy_remap.JoyRemap.mappings
mappings
Definition: joy_remap.py:68
joy_remap.RestrictedEvaluator.__init__
def __init__(self)
Definition: joy_remap.py:13
joy_remap.RestrictedEvaluator.functions
functions
Definition: joy_remap.py:22
joy_remap.RestrictedEvaluator._reval_impl
def _reval_impl(self, node, variables)
Definition: joy_remap.py:28
joy_remap.RestrictedEvaluator
Definition: joy_remap.py:12
joy_remap.JoyRemap.warn_remap
def warn_remap(self, name)
Definition: joy_remap.py:83
joy_remap.RestrictedEvaluator.operators
operators
Definition: joy_remap.py:14
joy_remap.JoyRemap.__init__
def __init__(self)
Definition: joy_remap.py:66
joy_remap.JoyRemap.callback
def callback(self, in_msg)
Definition: joy_remap.py:87
joy_remap.JoyRemap.load_mappings
def load_mappings(self, ns)
Definition: joy_remap.py:77
joy_remap.RestrictedEvaluator.reval
def reval(self, expr, variables)
Definition: joy_remap.py:54
joy_remap.JoyRemap.sub
sub
Definition: joy_remap.py:73
joy_remap.JoyRemap
Definition: joy_remap.py:65
joy_remap.JoyRemap.pub
pub
Definition: joy_remap.py:70
joy_remap.JoyRemap.evaluator
evaluator
Definition: joy_remap.py:67


joy
Author(s): Morgan Quigley, Brian Gerkey, Kevin Watts, Blaise Gassend
autogenerated on Thu Dec 5 2024 03:18:09