[payload] Payload Forward over UDP.

This commit is contained in:
Christophe De Wagter
2016-10-07 11:15:54 +02:00
parent 36230dd12a
commit 3863b2dcd4
7 changed files with 266 additions and 0 deletions
@@ -0,0 +1,13 @@
PAYLOAD
=======
PAYLOAD (downlink) and PAYLOAD_COMMAND (uplink) messages in the pprzlink telemetry act as easy pass-through of information from an autopilot subsystem like a computer vision board to ground station payload control system.
The paparazzi autopilot does not need to understand the data, but just needs to relay it. Payload is typically highly compressed information and only piggy-backs on telemetry when it needs to be transferred over the same long-range low bitrate datalink such as the autopilot telemetry. PAYLOAD is typically used by an external application and needs to be forwarded. ```payload_forward.py``` will forward only the PAYLOAD from IVY to an IP:PORT.
The PAYLOAD sender (typically a paparazzi module) must make sure the telemetry datalink does not get flooded with payload.
Over the years some standards have developed for payload. One is sending jpeg-thumbnails-chunks. A decoder for this 'jpeg100' is added to the forwarding program. For convenience and debugging, the payload_forward program also contains some standard decoders.
Use ```payload.py --help``` to find currently supported options.
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 641 KiB

+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 TUDelft
#
# This file is part of paparazzi.
#
# paparazzi is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# paparazzi is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with paparazzi. If not, see <http://www.gnu.org/licenses/>.
#
import wx
import sys
import argparse
import payload_forward
parser = argparse.ArgumentParser(description='Capture PAYLOAD messages over the IVY bus and forward to a remote application.', epilog='payload.py is part of the paparazzi-uav project.')
parser.add_argument('--ip', '-i', default="127.0.0.1", help='Destination IP ADDRESS (default=127.0.0.1)')
parser.add_argument('--port','-p', type=int, default=32000, help='Destination PORT (default=32000)')
parser.add_argument('--decoder','-d', default='jpeg100', help='Payload decoder. (default=jpeg100)', choices=['none', 'jpeg100'])
settings = parser.parse_args()
print(settings)
class PayloadFrame(wx.App):
def OnInit(self):
self.main = payload_forward.PayloadForwarderFrame(settings)
self.main.Show()
self.SetTopWindow(self.main)
return True
def main():
application = PayloadFrame(0)
application.MainLoop()
if __name__ == '__main__':
main()
@@ -0,0 +1,135 @@
#
# Copyright (C) 2016 TUDelft
#
# This file is part of paparazzi.
#
# paparazzi is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# paparazzi is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with paparazzi. If not, see <http://www.gnu.org/licenses/>.
#
import wx
import sys
import os
import threading
import socket
import array
import jpeg100_decoder
from cStringIO import StringIO
PPRZ_SRC = os.getenv("PAPARAZZI_SRC", os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../..')))
sys.path.append(PPRZ_SRC + "/sw/ext/pprzlink/lib/v1.0/python")
from pprzlink.ivy import IvyMessagesInterface
WIDTH = 300
# Minimal Decoder
class MinimalDecoder:
def __init__(self):
self.data = []
def add_payload(self,bytes):
self.data = bytes
def draw(self,dc,x,y):
dc.DrawText( "Payload: " + str(self.data),x,y)
class PayloadForwarderFrame(wx.Frame):
def message_recv(self, ac_id, msg):
if msg.name == "PAYLOAD":
# convert text to binary
pld = msg.get_field(0).split(",")
b = []
for p in pld:
b.append(int(p))
# forward over UDP
self.data['packets'] = self.data['packets'] + 1
self.data['bytes'] = self.data['bytes'] + len(b)
self.sock.sendto(bytearray(b), (self.settings.ip, self.settings.port))
# send to decoder
self.decoder.add_payload(b)
# graphical update
wx.CallAfter(self.update)
def update(self):
self.Refresh()
def OnSize(self, event):
self.w = event.GetSize()[0]
self.h = event.GetSize()[1]
self.Refresh()
def OnPaint(self, e):
# Paint Area
dc = wx.PaintDC(self)
brush = wx.Brush("white")
dc.SetBackground(brush)
dc.Clear()
# Background
dc.SetBrush(wx.Brush(wx.Colour(0,0,0), wx.TRANSPARENT))
font = wx.Font(11, wx.ROMAN, wx.BOLD, wx.NORMAL)
dc.SetFont(font)
dc.DrawText("UDP: " + self.settings.ip + ":" + str(self.settings.port),2,2)
dc.DrawText("Data: " + str(self.data['packets']) + " packets, " + str(round(float(self.data['bytes'])/1024.0,2)) + "kb)",2,22)
dc.DrawText("Decoder: " + self.settings.decoder ,2,42)
# Payload visual representation
self.decoder.draw(dc, 2, 62)
def __init__(self, _settings):
# Command line arguments
self.settings = _settings
# Statistics
self.data = { 'packets': 0, 'bytes': 0}
# Decoder
if (self.settings.decoder is 'jpeg100'):
self.decoder = jpeg100_decoder.ThumbNailFromPayload()
else:
self.decoder = MinimalDecoder()
self.w = WIDTH
self.h = WIDTH
# Socket
self.sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
# Frame
wx.Frame.__init__(self, id=-1, parent=None, name=u'Payload Forwarding',
size=wx.Size(self.w, self.h), title=u'Payload Forwarding')
ico = wx.Icon(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)))) + "/payload.ico", wx.BITMAP_TYPE_ICO)
self.SetIcon(ico)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# IVY
self.interface = IvyMessagesInterface("PayloadForwarder")
self.interface.subscribe(self.message_recv)
def OnClose(self, event):
self.interface.shutdown()
self.Destroy()