mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-21 20:04:09 +08:00
[payload] Payload Forward over UDP.
This commit is contained in:
@@ -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
BIN
Binary file not shown.
|
After Width: | Height: | Size: 641 KiB |
+46
@@ -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()
|
||||
Reference in New Issue
Block a user