DroneResponse / hardware-tests

0 stars 2 forks source link

Gimbal test #4

Open murphym18 opened 3 years ago

murphym18 commented 3 years ago

Streamline Designs has sourced a gimbal for our drones. The gimbal accepts the conventions put forth by MAVLink 1.0. So to control it, you must send it Storm32 commands (or so I believe). The Gimbal Manager built into PX4 may or may not be able to control a MAVLink 1.0 gimbal. If it can, then we should use the gimbal manager because that would give us a consistent interface moving forward. If it can’t then we may need to bypass the gimbal manager and address our gimbal commands directly to the gimbal.

We need to investigate how to move forward.

murphym18 commented 3 years ago

I looked into using mavros to control the gimbal. Mavros doesn't provide a high-level interface for controlling the gimbal. Instead we'll need to create/parse MAVLink messages (in binary form). Unfortunately this is made slightly harder because the version of pymavlink on PyPi doesn't include the message definitions we need. So we'll need to build a custom version and this page explains how to do it.

To figure this out, I made a hardware test that parses all the mavlink it receives from the typhoon h480 (simulated in gazebo). It raises errors like these:

[ERROR] [1634601784.341581]: bad callback: <function read_gimbal_cid.<locals>.cb at 0x7fd83f50c5e0>
Traceback (most recent call last):
  File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 750, in _invoke_callback
    cb(msg)
# more output...
  File "...site-packages/pymavlink/dialects/v20/common.py", line 12383, in decode
    raise MAVError('unknown MAVLink message ID %s' % str(mapkey))
pymavlink.dialects.v20.common.MAVError: unknown MAVLink message ID 284

[ERROR] [1634601784.357548]: bad callback: <function read_gimbal_cid.<locals>.cb at 0x7fd83f50c5e0>
Traceback (most recent call last):
  File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 750, in _invoke_callback
    cb(msg)
# more output...
  File "...site-packages/pymavlink/dialects/v20/common.py", line 12383, in decode
    raise MAVError('unknown MAVLink message ID %s' % str(mapkey))
pymavlink.dialects.v20.common.MAVError: unknown MAVLink message ID 285

Message IDs 284, and 285 are among the missing defintions. They refer to GIMBAL_DEVICE_SET_ATTITUDE and GIMBAL_DEVICE_ATTITUDE_STATUS messages.

But we need a version of pymavlink with other message definitions too. Including these:

murphym18 commented 3 years ago

Building pymavlink is pretty involved. We're not going to want to do this every time we make a docker image so I created a pip-installable archive. When we wanna get the hardware tests set up quickly we can just install the archive. I included it as a dependency in the requirements.txt file. But for our future reference, here is a script that will generate and install pymavlink from source:

#!/bin/bash

if [ `id -u` -eq 0 ]
then
    apt update
    apt install --yes git python3 python-is-python3 python3-pip python3-lxml libxml2-utils
else
    sudo apt update
    sudo apt install --yes git python3 python-is-python3 python3-pip python3-lxml libxml2-utils
fi

python -m pip install --user future

git clone --recurse-submodules https://github.com/mavlink/mavlink.git
cd mavlink
export PYTHONPATH="$PYTHONPATH:$PWD"
MAVLINK_DIR="$PWD"

### Generate the python modules
# 2.0
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/AVSSUAS.py" external/dialects/AVSSUAS.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/storm32.py" external/dialects/storm32.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/ASLUAV.py" message_definitions/v1.0/ASLUAV.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/all.py" message_definitions/v1.0/all.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/ardupilotmega.py" message_definitions/v1.0/ardupilotmega.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/common.py" message_definitions/v1.0/common.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/development.py" message_definitions/v1.0/development.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/icarous.py" message_definitions/v1.0/icarous.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/matrixpilot.py" message_definitions/v1.0/matrixpilot.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/minimal.py" message_definitions/v1.0/minimal.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/paparazzi.py" message_definitions/v1.0/paparazzi.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/python_array_test.py" message_definitions/v1.0/python_array_test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/standard.py" message_definitions/v1.0/standard.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/test.py" message_definitions/v1.0/test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/uAvionix.py" message_definitions/v1.0/uAvionix.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=2.0 --output="$MAVLINK_DIR/pymavlink/dialects/v20/ualberta.py" message_definitions/v1.0/ualberta.xml

# 1.0
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/AVSSUAS.py" external/dialects/AVSSUAS.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/storm32.py" external/dialects/storm32.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/ASLUAV.py" message_definitions/v1.0/ASLUAV.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/all.py" message_definitions/v1.0/all.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/ardupilotmega.py" message_definitions/v1.0/ardupilotmega.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/common.py" message_definitions/v1.0/common.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/development.py" message_definitions/v1.0/development.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/icarous.py" message_definitions/v1.0/icarous.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/matrixpilot.py" message_definitions/v1.0/matrixpilot.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/minimal.py" message_definitions/v1.0/minimal.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/paparazzi.py" message_definitions/v1.0/paparazzi.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/python_array_test.py" message_definitions/v1.0/python_array_test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/standard.py" message_definitions/v1.0/standard.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/test.py" message_definitions/v1.0/test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/uAvionix.py" message_definitions/v1.0/uAvionix.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=1.0 --output="$MAVLINK_DIR/pymavlink/dialects/v10/ualberta.py" message_definitions/v1.0/ualberta.xml

# 0.9
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/AVSSUAS.py" external/dialects/AVSSUAS.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/storm32.py" external/dialects/storm32.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/ASLUAV.py" message_definitions/v1.0/ASLUAV.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/all.py" message_definitions/v1.0/all.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/ardupilotmega.py" message_definitions/v1.0/ardupilotmega.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/common.py" message_definitions/v1.0/common.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/development.py" message_definitions/v1.0/development.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/icarous.py" message_definitions/v1.0/icarous.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/matrixpilot.py" message_definitions/v1.0/matrixpilot.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/minimal.py" message_definitions/v1.0/minimal.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/paparazzi.py" message_definitions/v1.0/paparazzi.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/python_array_test.py" message_definitions/v1.0/python_array_test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/standard.py" message_definitions/v1.0/standard.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/test.py" message_definitions/v1.0/test.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/uAvionix.py" message_definitions/v1.0/uAvionix.xml
python -m pymavlink.tools.mavgen --lang=Python --wire-protocol=0.9 --output="$MAVLINK_DIR/pymavlink/dialects/v09/ualberta.py" message_definitions/v1.0/ualberta.xml

python -m pip uninstall pymavlink

cd "$MAVLINK_DIR/pymavlink"
export NOGEN=1
python setup.py install --user
tawfiq1200 commented 3 years ago

The missing and the found message definitions seem to be here, for instance, this.

murphym18 commented 3 years ago

Yes, I'm thankful the missing message definitions were in the github.com/mavlink/mavlink repo. I was able to build that from source using the script in my last comment. It's too bad the verson of that library on PyPi is outdated. The pip-installable package I made, is just a more up-to-date version (with some slight modification so that it installs). There is a bug in pymavlink's setup.py file. My modification is a work-around. I wonder if that bug is preventing them from updating pymavlink on PyPi.