UPDATE 26.11.2019
This blog is depreciated!
UAVcast-Pro has been released. All you need to fly 4G / LTE
**UPDATED 08.02.2016 **
New complete script package available, ready for implementation. Read here for further information.
**UPDATED 13.05.2015 **
Added autoconnection of LTE if loss of signal. See section 3.1
I would like to share the ultimate **RPAS Drone ** setup i ever has experienced / tested. One word, Awesome! In my previous blog article i was explaining usage of Pixhawk in collaboration with RPI for 4G video and telemetry transfer, this requires three separate units ( Pixhawk , TTL to ETH adapter, RPI), the more the worse.
Using RPI2 with Navio+ keeps everything you need in one peace, and at least much more cleaner. I have flown approx 6hrs in total and I`m getting more and more confident with this configuration. I think a 4G telemetry system like this would be much more convenient to use than other regular radios (e.g 433 MHz and so on ).
This article will explain how to configure your RPI2 with the great navigation board from Emlid.com and the usage of 4g cellular network for real time RPAS.
NOTE , All info and usage from this blog is at your own risk. Everything is experimental!
Equipment used:
- Navio+ Emlid.com
- RPI2
- Logitech C920 Web camera
- Logitech F710 Gamepad
- 4G USB dongle
- 4G modem router ( Ground Control station )
- 5v 5A Bec
I would first like to thank all of the staff over at Emlid.com for this great navigation board Navio+ and especially the great support and documentation given at theirs site. Check it out .
**Image Installation **
Install PREEMPT_RT image into RPI2.
Use program such as Image Writer to install image to MicroSd card.
Connect RPI2 using SSH. ( e.g putty, Bitvise Tunnelier or any ssh program you want)
We need to update our source list with the following command.
sudo apt-get update
**Basic RPI2 Settings **
Run raspi-config
Set your desired user settings such as language etc. -
You could try to set overclocking to Pi2 1000MHz, this will increase gStreamer quality drastically, but unfortunately someone (including myself) has some issues running Pi2 overclock with APM software. Guys at Emlid.com are working to get this solved. **Use None/700Mhz to be safe. **
**!Note **: See THIS thread at Emlid.com if any issues like “AK8963: bad DEVICE ID” when overclocking.
RPI power source
We need to attach more power to the RPI2 USB, using a 5v 5A BEC. This will supply our 4G modem with enough power.
All onboard equipment are powered from the same battery source.
**gStreamer-1.0 Installation **
I recently manage to compile gstreamer v1.4. See main discussion thread Here
Version 1.4 are not required for this tutorial, so we just use v1.0 for the sake of convenience.
Type this line to install gstreamer1.0
sudo apt-get install gstreamer1.0
Save attached(in bottom of this article) **gstreamer.sh ** file to RPI or copy paste content bellow.
NOTE! Change the IP to match your GCS ip or dyndns. You may also try with different framerate and bitrate.
Try to find a setting you are satisfied with.
#!/bin/bash
#320x240
#360x288
#640x480
#704x576
WIDTH=640
HEIGHT=480
ip=GCS_IP
v4l2-ctl --set-fmt-video=width=$WIDTH,height=$HEIGHT,pixelformat=1
v4l2-ctl -i 1
gst-launch-1.0 -v \ rtpbin name=rtpbin v4l2src device=/dev/video0 \
! video/x-raw,width=$WIDTH,height=$HEIGHT,framerate=15/1 \
! queue \
! omxh264enc target-bitrate=500000 control-rate=1 \
! "video/x-h264,profile=high" \
! h264parse \
! queue max-size-bytes=10000000 \
! rtph264pay pt=96 config-interval=1 \
! rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 \
! udpsink port=5000 host=$ip ts-offset=0 name=vrtpsink rtpbin.send_rtcp_src_0 \
! udpsink port=5001 host=$ip sync=false async=false name=vrtcpsink udpsrc port=5000 name=vrtpsrc \
! rtpbin.recv_rtcp_sink_0
Remember to set permission to file,
chmod 755 gstreamer.sh
To run gstreamer script, type this;
sudo sh gstreamer.sh
**Client. Windows or unix. **
Get the gstreamer installation package for windows here
Install the package and then navigate to the installation bin directory. e.g gstreamer\1.0\x86\bin
Then open windows command prompt in that directory. left shift + right click. "Open command line here".
Then type this syntax to start gstreamer to listen for any video stream at port 5000.
If your RPI are streaming, you should get a picture right away.
gst-launch-1.0.exe -e -v udpsrc port=5000 ! application/x-rtp, payload=96 !
rtpjitterbuffer ! rtph264depay ! avdec_h264 ! fpsdisplaysink sync=false text-overlay=false
VLC If you dont have the VLC installed, you can get it here
Save the attached(In the Bottom of this article) vlc.sdp and run it.
**UQMI 4G integration **
UQMI (Supports 4G LTE) Read discussion thread here
Tested and working on RPI 2.
Install required dependencies:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install usb-modeswitch
sudo apt-get install cmake
sudo apt-get install dh-autoreconf
sudo apt-get install dnsutils
DIR /home/pi
*** installing json-c ***
wget https://s3.amazonaws.com/json-c_releases/releases/json-c-0.12.tar.gz
sudo tar -xvf json-c-0.12.tar.gz
cd json-c-0.12
sed -i s/-Werror// Makefile.in && ./configure --prefix=/usr --disable-static && make -j1
su
make install
cd ..
*** Installing libubox ****
git clone https://github.com/UAVmatrix/libubox.git libubox
cd libubox
cmake CMakeLists.txt -DBUILD_LUA=OFF
make
sudo make install
mkdir -p /usr/include/libubox
cp *.h /usr/include/libubox
cp libubox.so /usr/lib
cp libblobmsg_json.so /usr/lib
ldconfig
Then git, compile and install **uqmi **
cd /home/pi
sudo git clone git://nbd.name/uqmi.git
cd uqmi
sudo cmake CMakeLists.txt
sudo make install
3.1 Autoconnection of LTE if loss of signal. ( UPDATE 13.05.2015 )
This section will explain autoconnection of LTE 4G if loss of signal. We need to create crontab job that checks every 15sec if RPI is online, and if not reconnect. We also needs to change the way APM streams UDP packets. Normally we just type UDP:GCS_IP:port, but this wont work after wwan0 ( LTE USB Modem) is re-iniziated. we need to stream our packets to localhost and then use udp_redirect script to forward packets to GCS.
First we are going to create "checkifonline" script.
sudo vi checkifonline.sh
Then copy and paste code bellow.
This script will check if our RPI is online and if not, re-connect our LTE modem
Change the green fields to match your setting.
#!/bin/bash
#Create lock file
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "This script is already running"
exit
fi
# make sure the lockfile is removed when we exit and then claim it
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
#let`s ping google.
if ! wget -q --tries=10 --timeout=20 --spider http://google.com
then
sleep 1
#let`s ping google again to doublecheck that RPI is offline.
if ! wget -q --tries=10 --timeout=20 --spider http://google.com
then
sudo killall -9 uqmi
sudo killall -9 dhclient
sudo uqmi -d /dev/cdc-wdm0 --set-device-operating-mode shutting_down
sleep 30
sudo uqmi -d /dev/cdc-wdm0 --stop-network 4294967295 --autoconnect
sleep 2
sudo uqmi -d /dev/cdc-wdm0 --network-register
sleep 2
sudo uqmi -s -d /dev/cdc-wdm0 --start-network YOUR_APN --keep-client-id wds --autoconnect &
echo "Restartet Modem"
sleep 8
sudo dhclient -v wwan0
sleep 5
else
echo "RPI Online"
fi
else
echo "RPI Online"
fi
#remove LockFile
rm -f ${LOCKFILE}
Remember to set permission
sudo chmod 755 checkifonline.sh
Let`s add this script to crontab
sudo crontab -e
add these line to the bottom of the file
* * * * * /home/pi/./checkifonline.sh &
* * * * * sleep 15; /home/pi/./checkifonline.sh &
* * * * * sleep 30; /home/pi/./checkifonline.sh &
* * * * * sleep 45; /home/pi/./checkifonline.sh &
This will run our checkifonline script every 15sec.
Next we need to create udp_redirect program.
Make another script
sudo vi udp_redirect.c
Copy paste the code bellow.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[]) {
if (argc!=3 && argc!=5) {
printf("Usage: %s our-ip our-port send-to-ip send-to-port\n",argv[0]);
printf("Usage: %s our-ip our-port # echo mode\n",argv[0]);
exit(1);
}
int os=socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
struct sockaddr_in a;
a.sin_family=AF_INET;
a.sin_addr.s_addr=inet_addr(argv[1]); a.sin_port=htons(atoi(argv[2]));
if(bind(os,(struct sockaddr *)&a,sizeof(a)) == -1) {
printf("Can't bind our address (%s:%s)\n", argv[1], argv[2]);
exit(1); }
if(argc==5) { a.sin_addr.s_addr=inet_addr(argv[3]); a.sin_port=htons(atoi(argv[4])); }
struct sockaddr_in sa;
struct sockaddr_in da; da.sin_addr.s_addr=0;
while(1) {
char buf[65535];
int sn=sizeof(sa);
int n=recvfrom(os,buf,sizeof(buf),0,(struct sockaddr *)&sa,&sn);
if(n<=0) continue;
if(argc==3) { sendto(os,buf,n,0,(struct sockaddr *)&sa,sn);
} else if(sa.sin_addr.s_addr==a.sin_addr.s_addr && sa.sin_port==a.sin_port) {
if(da.sin_addr.s_addr) sendto(os,buf,n,0,(struct sockaddr *)&da,sizeof(da));
} else {
sendto(os,buf,n,0,(struct sockaddr *)&a,sizeof(a));
da=sa;
}
}
}
Set permission to file
sudo chmod 755 udp_redirect.c
Then we compile the file we just created.
sudo gcc -o udp_redirect udp_redirect.c
Now you should have a file named udp_redirect in /home/pi
Finally we are going to make udp-send.sh script. This scripft will find GCS ip address and forward UDP trafic from 127.0.0.1( localhost) to your GCS.
sudo vi udp-send.sh
Copy paste the code bellow
#!/bin/bash
ip=`dig +short YOUR_GCS_DNS`
echo $ip /home/pi/udp_redirect 0.0.0.0 14550 $ip 14550 &
**Note! ** - Remeber to change the APM start line in ArduPilot.sh as described in earlier.
From:
sudo ArduPlane -A udp:$ip:14550
To
sudo ArduPlane -A udp:127.0.0.1:14550
APM installation.
All documentation is provided at Emlid.com , i would recommend to see theirs instructions. After successfully installed APM, make another script which just fires ArduPilot software.
sudo vi Ardupilot.sh
Copy paste code bellow. Change code to mach you airframe and port !NOTE, If you are going to use Autoconnect features as described in section 3.1, you need to change the APM start line to
sudo ArduPlane -A udp:127.0.0.1:14550
#!/bin/bash
ip=`dig +short YOUR_DynDns_ADRESS`
sudo ArduPlane -A udp:$ip:14550
Set permission to file
sudo chmod 755 ArduPilot.sh
Now test that ArduPilot is working properly.
sudo sh ArduPilot.sh
RPI startup and usage of installed code.
Now you should have two files located in /home/pi ( gstreamer.sh, ArduPilot.sh)
I have made a startup script which calls all the necessary programs in correct order.
( Also see attched runCode.sh in the bottom)
sudo vi runCode.sh
Copy paste code bellow. Change the yellow fields to mach yours. You will need to contact your operator to get correct APN name.
Telenor, Norway using; internet.public
#!/bin/bash
function CheckOnline {
SERVICE='uqmi'
if ps ax | grep -v grep | grep $SERVICE > /dev/null
then
echo "$SERVICE service running, everything is fine"
wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
echo "Online, starting APM"
ArduPilot
sleep 1
else
echo "4G Offline"
fi
else
echo "$SERVICE is not running"
echo "Check if RPI is online anyway"
wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
echo "RPI is Online, starting APM"
ArduPilot
sleep 1
else
echo "RPI Offline"
uqmi
fi
fi
}
function gstreamer {
pidof gst-launch-1.0 >/dev/null
if [[ $? -ne 0 ]] ; then
sudo sh /home/pi/gstreamer.sh &
sleep 5
pidof gst-launch-1.0 >/dev/null
if [[ $? -eq 0 ]] ; then
echo "gStremer Started"
else
echo 'Could`t start gStreamer'
fi
else
echo "gStremer already running"
fi
}
function uqmi {
sudo uqmi -d /dev/cdc-wdm0 --stop-network 4294967295 --autoconnect
sleep 2
if ! sudo uqmi -s -d /dev/cdc-wdm0 --get-data-status | grep '"connected"' > /dev/null; then
sudo uqmi -d /dev/cdc-wdm0 --stop-network 4294967295 --autoconnect
sleep 2
sudo uqmi -d /dev/cdc-wdm0 --network-register
echo network register
sleep 3
echo Connecting 4G
sudo uqmi -s -d /dev/cdc-wdm0 --start-network YOUR_APN_NAME --keep-client-id wds --autoconnect &
sleep 15
if ! sudo uqmi -s -d /dev/cdc-wdm0 --get-data-status | grep '"connected"' > /dev/null; then
echo "Not Connected!"
else
echo "Connected"
sudo dhclient -v wwan0
sleep 3
CheckOnline
fi
else
echo "Already connected to internet."
echo "Check if gStreamer or APM is running, if not we start them."
CheckOnline
fi
}
function ArduPilot {
pidof ArduPlane >/dev/null
if [[ $? -ne 0 ]] ; then
nohup sudo sh /home/pi/ArduPilot.sh > /dev/null 2>&1 &
sleep 5
pidof ArduPlane >/dev/null
if [[ $? -eq 0 ]] ; then
echo "APM started"
gstreamer
else
echo 'could`t start ArduPilot'
fi
else
echo "APM already running"
echo "Starting gStreamer"
gstreamer
fi
}
sleep 25
CheckOnline
Set Permission
chmod 755 runCode.sh
This script is not the most glorious one ( made in a hurry) but it should give you an idea on how to set everything up.
You are free to make a more robust version with further functionalities.
**Add runCode.sh to run a startup **
we need to add runCode.sh to /etc/rc.local
sudo vi /etc/rc.local
add this line to the bottom before exit 0
sudo /home/pi/./runCode.sh &
Reboot RPI and verify that 4G, APM code, gStreamer is running. At this stage you should be able to connect 4G cellular network and stream telemetry from Navio to Mission planner and simultaneously have video stream provided by gstreamer to your GCS.
Now you can connect your gamepad and select Joystick tab in mission planner. Set desired function to each of the buttons and joysticks. This is how i have configured my Gamepad.
**Failsafe **
Few thing to remember before flight. My failsafe function is set as bellow;
GCS failsafe in Mission planner.
When flying while using telemetry on the GCS, the autopilot can be programmed to trigger into failsafe mode if it loses telemetry. In the event that the autopilot stops receiving MAVlink (telemetry protocol) heartbeat messages for more than 20 sec, the GCS failsafe (FS_GCS_ENABL, 0=Disabled, 1=Enabled) will trigger the autopilot to go into long failsafe and change the flight mode to RTL
Set Long failsafe in mission planner.
The action to take on a long (20 second) failsafe event in AUTO, GUIDED or LOITER modes. A long failsafe event in stabilization modes will always cause an RTL (ReturnToLaunch). In AUTO modes you can choose whether it will RTL or continue with the mission. If FS_LONG_ACTN is 0 then it will continue with the mission, if it is 1 then it will enter RTL mode. Note that if FS_SHORT_ACTN is 1, then the aircraft will enter CIRCLE mode after 1.5 seconds of failsafe, and will always enter RTL after 20 seconds of failsafe, regardless of the FS_LONG_ACTN setting.
Read all about failsafe from Ardupilot
https://youtu.be/5f0Kz7wUwzA
https://youtu.be/EBhvOVh2hNA
https://youtu.be/qY4sAh3ZrGE
**Happy and SAFE Flying! **