Tag Archives: Streaming

RCP (the new RUDP)

Some months ago I found this awesome blog with research and a usable implementation of rfmon for uni-directional wireless communication. It uses libpcap and a modified firmware for the TP 721N dongle to send encoded video packets and telemetry to the GS. It’s unidirectional and this has some advantages. The biggest advantage for me was that it doesn’t require pairing nor connection handshake. Perfect for a quad!

So I included rfmon in RUDP and renamed the result to RCP (Reliable Comms Protocol…). It’s bidirectional in my case as I need to send control data to the quad as well but the advantages still apply.

Performance is great, I can send 1024×768 video @30 FPS, 2Mbps using around 4-4.5Mbps with very little CPU usage.

The problem I’ve hit is this: the more data I send, the more packets get lost due to interference, etc. Having a fixed retransmit rate – like every packet 3 times – requires a fixed amount of bandwidth but doesn’t scale at all to low-bandwidth situations. So I need a way to use the least amount of bandwidth possible while still ensuring that frames arrive at the other end.
One solution is to add ACK packets to reduce retransmission – which is what RCP does – but this also has an issue. Every confirmation packet keeps the channel busy for a little while – in turn dropping the total bandwidth of the system.
Current solution is to gather many confirmations and send them with low frequency – around MAX_RETRANSMIT_TIME / 2 (currently every 10ms). So fast enough to avoid retransmission, but not as fast as to keep the channel busy unnecessarily. So far this works beautifully.
Code time!

The brain on the UAV uses RCP setup with a RFMON socket:

 

auto s = new util::RCP_RFMON_Socket("mon0", 5);//5 is the end-point ID
m_socket.reset(s);
m_rcp.reset(new util::RCP);

util::RCP::Socket_Handle handle = m_rcp->add_socket(s);
if (handle >= 0)
{
    m_rcp->set_internal_socket_handle(handle);
    m_rcp->set_socket_handle(SETUP_CHANNEL, handle);
    m_rcp->set_socket_handle(PILOT_CHANNEL, handle);
    m_rcp->set_socket_handle(VIDEO_CHANNEL, handle);
    m_rcp->set_socket_handle(TELEMETRY_CHANNEL, handle);
}

 

So – this code adds a socket to the RCP instance and then instructs all channels to go through this socket. Same for the internal data – which represents the ACKs, pings (for RTT estimation) and connection requests.

The reason for this indirection is to allow different sockets for different channels. For example – use RFMON for unidirectional video streaming and another socket over a 433Mhz radio (like this one) for all other comms and ACKs.

In the near future I’ll try this – sending all channels except video through the RFM22B socket, as this should give me better range & penetration compared to 2.4Ghz.

 

Advertisements

Video Latency

Just did some latency tests using RUDP through wifi, 640×480@30fps, 2Mbps.

Both the laptop and the quadcopter are in the same room but they go through a router 3 walls away. Signal strengths are (as reported by iwconfig):

Quad:
Link Quality=70/70  Signal level=-37 dBm

Laptop:
Link Quality=58/70  Signal level=-52 dBm

Ping reports these RTTs:
64 bytes from 192.168.1.110: icmp_seq=1 ttl=64 time=137 ms
64 bytes from 192.168.1.110: icmp_seq=2 ttl=64 time=160 ms
64 bytes from 192.168.1.110: icmp_seq=3 ttl=64 time=85.4 ms
64 bytes from 192.168.1.110: icmp_seq=4 ttl=64 time=108 ms
64 bytes from 192.168.1.110: icmp_seq=5 ttl=64 time=125 ms
64 bytes from 192.168.1.110: icmp_seq=6 ttl=64 time=149 ms
64 bytes from 192.168.1.110: icmp_seq=7 ttl=64 time=73.6 ms
64 bytes from 192.168.1.110: icmp_seq=9 ttl=64 time=119 ms

The quadcopter uses the more sensitive alfa card while the laptop has its own crappy RTL8723be card that has many issues under linux…

I happen to live in a building with a very noisy wifi situation so SNR is not good at all.

Average latency is around 100-160ms with random spikes of 3-400 ms every 10-20 or so seconds.

[Edit – just realized that both the brain and the GS are debug versions…]

To measure I pointed the raspicam at my phone’s stopwatch app and then took photos of the phone and the screen at the same time. Here are some of them:

20141128_212006

 

 

 

 

20141128_212010

 

 

 

 

 

20141128_212011

 

 

 

20141128_212007