Here they are: Init.d scripts for broadcasting if you setup your RPi as Access Point and autostarting ArduCopter

Script 1) starts the firmware and script 2) redirects the output from the UDP sockets to the broadcast address of the WiFi network (If you setup your Pi as Access Point). All connected PCs will receive the output @ e.g. APMPlanner automatically. I think this approach is smarter than the current one. How you configure your RPi as AP is explained in the Inet.
The script 2) will automatically determine the broadcast address based on the /etc/network/interfaces file. For script 1) auto starting the correct firmware binary is determined in a new config file “ardupilot.conf”. For Copter with e. g. X-Frame, enter under “firmware” the name of the proper binary (e.g. “ArduCopter-quad”)
Have fun!

Best, Daniel

Update: I added some checks and made some changes (config file, auto detection of the IP for broadcasting).

Example: Generate a config file ("/etc/ardupilot.conf") like this, to tell the init.d script which binary to start.

[ArduPilot]
firmware ArduCopter-quad # or whatever

Then, make an init.d file:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          ArduPilot
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start ArduPilot at boot time
### END INIT INFO

NAME=ArduPilot
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DIR=/usr/bin
CONFF="/etc/ardupilot.conf"
CONS_OUT="/var/log/ArduPilot.log"
PIDFILE=/var/run/$NAME.pid
DESC="ArduPilot @ Navio+"

# Check for existence of a ArduPilot configuration configuration file
test -r $CONFF || { echo "$CONFF not existing";
        if [ "$1" = "stop" ]; then exit 0;
        else exit 6; fi; }

# Get ArduPilot configuration file (which firmware to load)
BIN=$(awk -v par="[ArduPilot]" '
          $1==par {f=1}
          f && /^\s*firmware/ {print $2; f=0}' $CONFF)

# Config file not properly set
if [ "$BIN" = "" ]; then echo "Error: firmware binary was not defined in $CONFF"; exit 0; fi

DAEMON=$DIR/$BIN
OPTIONS="-A udp:127.0.0.1:14550"

# Check for existence of a firmware binary
test -r $DAEMON || { echo "$BIN not existing";
        if [ "$1" = "stop" ]; then exit 0;
        else exit 6; fi; }

# Load some functions for the process administration
. /lib/lsb/init-functions

do_start() {
  log_daemon_msg "Starting system $DAEMON $ARGS daemon"
  /sbin/start-stop-daemon --start --pidfile $PIDFILE \
    -b --make-pidfile \
    --nicelevel -20 \
    --exec $DAEMON -- $OPTIONS > $CONS_OUT
  log_end_msg $?
}

do_stop() {
  log_daemon_msg "Stopping system $DAEMON $ARGS daemon"
  /sbin/start-stop-daemon --stop --pidfile $PIDFILE --verbose
  log_end_msg $?
}

case "$1" in
  start)
    do_start
    ;;
  stop)
    log_daemon_msg "Stopping system $DAEMON $ARGS daemon"
    do_stop
    ;;
  restart|reload|force-reload)
    do_stop
    do_start
    ;;
  status)
    status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
    ;;
  *)
    echo "Usage: /etc/init.d/$USER {start|stop|restart|status}"
    exit 1
    ;;
esac

exit 0

Here an updated init.d script for broadcasting the output of ArduPilot to the whole network.
It should support auto recognition of the proper broadcasting IP adress of the interface “wlan0”.

#!/bin/sh

### BEGIN INIT INFO
# Provides:          ArduProxy
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Multiplexes the UDP socket connection of ArduPilot
# Description:       If using the RPi as a WiFi access point, we want all connected computers to get the state of the vehicle.
### END INIT INFO

NAME=ArduProxy
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DIR=/usr/bin
BIN=socat
DAEMON=$DIR/$BIN
CONFF="/etc/network/interfaces"
DESC="ArduProxy @ Navio+"
PORT="14550"
PIDFILE=/var/run/$NAME.pid

# Check for missing binaries (socat)
test -x $DAEMON || { echo "$BIN not installed";
        if [ "$1" = "stop" ]; then exit 0;
        else exit 5; fi; }

# Check for existence of a network interfaces configuration file
test -r $CONFF || { echo "$CONFF not existing";
        if [ "$1" = "stop" ]; then exit 0;
        else exit 6; fi; }

# Get the network adress of the interface wlan0
NETWORK=$(awk -v par="wlan0" '
          /^iface/ && $2==par {f=1}
          f && /^\s*address/ {ip=$2; sub(".1$", ".255", ip); print ip; f=0}' $CONFF)

# If IP was found, prepare option parameter for 'socat'
# else exit this script
if [ "$NETWORK" = "" ]; then echo "Error: no address for interface wlan0 was defined."; exit 0; fi
OPTIONS="UDP4-LISTEN:$PORT,fork UDP4-DATAGRAM:$NETWORK:$PORT,broadcast"

# Load some functions for the process administration
. /lib/lsb/init-functions

do_start() {
  log_daemon_msg "Starting system $DAEMON $ARGS daemon"
  /sbin/start-stop-daemon --start --pidfile $PIDFILE \
    -b --make-pidfile \
    --exec $DAEMON -- $OPTIONS
  log_end_msg $?
}

do_stop() {
  log_daemon_msg "Stopping system $DAEMON $ARGS daemon"
  /sbin/start-stop-daemon --stop --pidfile $PIDFILE --verbose
  log_end_msg $?
}

case "$1" in
  start)
    do_start
    ;;
  stop)
    log_daemon_msg "Stopping system $DAEMON $ARGS daemon"
    do_stop
    ;;
  restart|reload|force-reload)
    do_stop
    do_start
    ;;
  status)
    status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
    ;;
  *)
    echo "Usage: /etc/init.d/$USER {start|stop|restart|status}"
    exit 1
    ;;
esac

exit 0
1 Like

I tried these scripts but my Apmplanner shows:

qml: HBD: Heartbeat started
qml: HBD: Heartbeat stopped

over and over again. Seems to me that Apmplanner does not have the time to fetch everything it needs before the connection is dropped.

Works fine if i use “-A 192.168.10.2:14550” (my groundstation ip) but not if i use “-A 127.0.0.1:14550” and then the socat command (sudo socat UDP4-LISTEN:14550,fork UDP4-DATAGRAM:192.168.10.255:14550,broadcast,range=192.168.10.0/255).

Do i need some other config at the ground station side?

Well, I also noticed this occasionally. If I give socat a fixed destination IP the problem disappears.
I think this is because the time to broadcast is longer than the timeout for a heartbeat, or due to packet loss.
I am not on that atm. The best solution in my opinion would be to implement this in the vehicle code.
The current implementation in ArduPilot is in my opinion not nice. However this is not related to Navio+ anymore.
Maybe someone here is more convenient with socat and may find a fix for this problem. Maybe, using TCP would already fix the problem, as packet loss or wrong packet order wouldn’t appear.

1 Like