Hi @niklasebner -
I would recommend against using the Kakute F4 flight controller. We’ve not tested it with ArduSub or ArduRover, and when used with BlueOS it won’t support LUA scripts. That said, you could get things working without lua scripts using Pymavlink, but that is a less elegant solution in my opinion.
LUA scripts are convenient because they are run by the autopilot, but don’t require expanding the autopilot firmware with more functionality. The specific code used in my HAUV script to send an HTTP request to my extension is
function start_video_recording()
local sock = Socket(0)
if not sock:bind("0.0.0.0", 9988) then
gcs:send_text(6, "Failed to bind socket")
sock:close()
return false
end
if not sock:connect(HTTP_HOST, HTTP_PORT) then
gcs:send_text(6, string.format("Failed to connect to %s:%d", HTTP_HOST, HTTP_PORT))
sock:close()
return false
end
local request = "GET /start?split_duration=2 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
gcs:send_text(6, string.format("Sending request to http://%s:%d/start?split_duration=2", HTTP_HOST, HTTP_PORT))
sock:send(request, string.len(request))
sock:close()
gcs:send_text(6, "Video recording started")
return true
end
This is received by this code in the extension:
@app.route('/start', methods=['GET'])
def start():
global process, recording, start_time
try:
if recording:
return jsonify({"success": False, "message": "Already recording"}), 400
# Ensure the video directory exists
os.makedirs("/app/videorecordings", exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"video_{timestamp}.mp4"
filepath = os.path.join("/app/videorecordings", filename)
pipeline = ("v4l2src device=/dev/video2 ! "
"video/x-h264,width=1920,height=1080,framerate=30/1 ! "
f"h264parse ! mp4mux ! filesink location={filepath}")
command = ["gst-launch-1.0", "-e"] + shlex.split(pipeline)
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
logger.info(f"Starting recording with command: {' '.join(command)}")
if process.poll() is not None:
stdout, stderr = process.communicate()
logger.error(f"Process failed to start. stdout: {stdout.decode()}, stderr: {stderr.decode()}")
raise Exception(f"Failed to start recording: {stderr.decode()}")
recording = True
start_time = datetime.now()
return jsonify({"success": True})
except Exception as e:
logger.error(f"Error in start endpoint: {str(e)}")
recording = False
start_time = None
if process:
try:
process.kill()
except:
pass
process = None
return jsonify({"success": False, "message": str(e)}), 500
If you don’t want to switch to a Navigator, your extension would not only need to handle your image capture goals, but also communicate with the autopilot to change modes and arm/disarm the system. You can read about that here, but it has been primarily been tested with ArduSub, so some challenges may be lurking…
I’d also strongly recommend against a “traditional” VPN - they are very difficult to setup correctly, unreliable, and limited in bandwidth in most circumstances - and BlueRobotics has not tested other solutions for compatibility with BlueOS. ZeroTier is essentially a VPN, and if you need to access other devices on the network, you can do so. . Essentially, a ZeroTier device has a ZeroTier IP that canbe accessed from any device on the same virtual ethernet switch that is represented by your ZeroTier network.