def convertKPsToMetres(self, kps_bearingrange):
     # because the localmaxima node uses x and y to store bearing range,
     # which is somewhat wrong, but nevermind:
     # Also here we discard keypoints that are a long way away (> Max_Range)
     Max_Range = self.options.Max_Range
     r = []
     for kp in kps_bearingrange:
         bearing = kp.pt.x
         range = kp.pt.y
         if range > Max_Range:
             continue
         t = msg.KeyPoint(
             msg.floatXY(-range * math.sin(bearing),
                         range * math.cos(bearing)), kp.size, kp.angle,
             kp.response, kp.octave, kp.class_id)
         r.append(t)
     return r
p_MotorMap << pp.Group(l \
    + p_int + c \
    + p_int + c \
    + p_int + c \
    + p_int \
    + r)
p_MotorMap.setParseAction(lambda x: messaging.MotorMap(*x[0]))
p_KeyPoint << pp.Group(l \
    + p_floatXY + c \
    + p_float + c \
    + p_float + c \
    + p_float + c \
    + p_float + c \
    + p_float \
    + r)
p_KeyPoint.setParseAction(lambda x: messaging.KeyPoint(*x[0]))
p_ScriptResponse << pp.Group(l \
    + p_str + c \
    + p_DebugType + c \
    + p_str + c \
    + p_int \
    + r)
p_ScriptResponse.setParseAction(lambda x: messaging.ScriptResponse(*x[0]))
p_ScriptExecRequest << pp.Group(l \
    + p_str + c \
    + p_float + c \
    + p_str + c \
    + p_int \
    + r)
p_ScriptExecRequest.setParseAction(lambda x: messaging.ScriptExecRequest(*x[0]))