├── .flake8 ├── .github └── workflows │ ├── python-cleanliness.yml │ ├── python-publish.yml │ └── windows_build.yml ├── .gitignore ├── .gitmodules ├── ANDROID.md ├── COPYING.txt ├── MAVProxy ├── MAVLink.xml ├── MAVProxyWinLAN.bat ├── MAVProxyWinUSB.bat ├── __init__.py ├── mavproxy.py ├── modules │ ├── __init__.py │ ├── lib │ │ ├── ANUGA │ │ │ ├── README.txt │ │ │ ├── __init__.py │ │ │ ├── geo_reference.py │ │ │ ├── lat_long_UTM_conversion.py │ │ │ └── redfearn.py │ │ ├── LowPassFilter2p.py │ │ ├── MacOS │ │ │ ├── __init__.py │ │ │ ├── backend_agg.py │ │ │ ├── backend_wx.py │ │ │ ├── backend_wxagg.py │ │ │ └── wxversion.py │ │ ├── __init__.py │ │ ├── camera_projection.py │ │ ├── dumpstacks.py │ │ ├── geodesic_grid.py │ │ ├── graph_ui.py │ │ ├── graphdefinition.py │ │ ├── grapher.py │ │ ├── icon.py │ │ ├── kmlread.py │ │ ├── live_graph.py │ │ ├── live_graph_ui.py │ │ ├── magfit.py │ │ ├── mav_fft.py │ │ ├── mission_item_protocol.py │ │ ├── mp_checklist.py │ │ ├── mp_elevation.py │ │ ├── mp_image.py │ │ ├── mp_instructor.py │ │ ├── mp_menu.py │ │ ├── mp_module.py │ │ ├── mp_settings.py │ │ ├── mp_substitute.py │ │ ├── mp_util.py │ │ ├── mp_widgets.py │ │ ├── msgstats.py │ │ ├── multiproc.py │ │ ├── multiproc_util.py │ │ ├── ntrip.py │ │ ├── opengl.py │ │ ├── optparse_gui │ │ │ ├── README.txt │ │ │ └── __init__.py │ │ ├── param_ftp.py │ │ ├── param_help.py │ │ ├── rline.py │ │ ├── rtcm3.py │ │ ├── srtm.py │ │ ├── textconsole.py │ │ ├── wavefront.py │ │ ├── win_layout.py │ │ ├── wx_addlink.py │ │ ├── wx_loader.py │ │ ├── wx_processguard.py │ │ ├── wx_util.py │ │ ├── wxconsole.py │ │ ├── wxconsole_ui.py │ │ ├── wxconsole_util.py │ │ ├── wxgrapheditor.py │ │ ├── wxhorizon.py │ │ ├── wxhorizon_ui.py │ │ ├── wxhorizon_util.py │ │ ├── wxrc.py │ │ ├── wxsaildash.py │ │ ├── wxsaildash_ui.py │ │ ├── wxsaildash_util.py │ │ ├── wxsettings.py │ │ └── wxsettings_ui.py │ ├── mavproxy_DGPS.py │ ├── mavproxy_GPSInject.py │ ├── mavproxy_GPSInput.py │ ├── mavproxy_HIL.py │ ├── mavproxy_OpenDroneID.py │ ├── mavproxy_SIYI │ │ ├── __init__.py │ │ ├── camera_view.py │ │ ├── raw_thermal.py │ │ └── tools │ │ │ ├── playback.py │ │ │ ├── temp_dir.py │ │ │ └── temp_view.py │ ├── mavproxy_SecureCommand.py │ ├── mavproxy_adsb.py │ ├── mavproxy_ais.py │ ├── mavproxy_antenna.py │ ├── mavproxy_anufireproject │ │ └── __init__.py │ ├── mavproxy_arm.py │ ├── mavproxy_asterix.py │ ├── mavproxy_auxopt.py │ ├── mavproxy_battery.py │ ├── mavproxy_calibration.py │ ├── mavproxy_cameraview.py │ ├── mavproxy_chat │ │ ├── __init__.py │ │ ├── assistant_setup │ │ │ ├── assistant_instructions.txt │ │ │ ├── copter_flightmodes.txt │ │ │ ├── delete_wakeup_timers.json │ │ │ ├── get_all_parameters.json │ │ │ ├── get_available_mavlink_messages.json │ │ │ ├── get_current_datetime.json │ │ │ ├── get_location_plus_dist_at_bearing.json │ │ │ ├── get_location_plus_offset.json │ │ │ ├── get_mavlink_message.json │ │ │ ├── get_mode_mapping.json │ │ │ ├── get_parameter.json │ │ │ ├── get_parameter_description.json │ │ │ ├── get_vehicle_location_and_yaw.json │ │ │ ├── get_vehicle_state.json │ │ │ ├── get_vehicle_type.json │ │ │ ├── get_wakeup_timers.json │ │ │ ├── plane_flightmodes.txt │ │ │ ├── rover_modes.txt │ │ │ ├── send_mavlink_command_int.json │ │ │ ├── send_mavlink_set_position_target_global_int.json │ │ │ ├── set_parameter.json │ │ │ ├── set_wakeup_timer.json │ │ │ ├── setup_assistant.py │ │ │ └── sub_modes.txt │ │ ├── chat_openai.py │ │ ├── chat_voice_to_text.py │ │ └── chat_window.py │ ├── mavproxy_checklist.py │ ├── mavproxy_cmdlong.py │ ├── mavproxy_console.py │ ├── mavproxy_dataflash_logger.py │ ├── mavproxy_devop.py │ ├── mavproxy_emuecu.py │ ├── mavproxy_example.py │ ├── mavproxy_fakegps.py │ ├── mavproxy_fence.py │ ├── mavproxy_fenceitem_protocol.py │ ├── mavproxy_fieldcheck │ │ ├── __init__.py │ │ ├── cmac-foamy-fence.txt │ │ ├── cmac-foamy-mission-ccw.txt │ │ ├── cmac-foamy-mission-cw.txt │ │ ├── cmac-foamy-rally.txt │ │ ├── springvalley-foamy-fence.txt │ │ ├── springvalley-foamy-mission-ccw.txt │ │ ├── springvalley-foamy-mission-cw.txt │ │ ├── springvalley-foamy-rally.txt │ │ ├── springvalleybottom-foamy-fence.txt │ │ ├── springvalleybottom-foamy-mission-ccw.txt │ │ ├── springvalleybottom-foamy-mission-cw.txt │ │ └── springvalleybottom-foamy-rally.txt │ ├── mavproxy_firmware.py │ ├── mavproxy_followtest.py │ ├── mavproxy_ftp.py │ ├── mavproxy_gasheli.py │ ├── mavproxy_generator.py │ ├── mavproxy_genobstacles.py │ ├── mavproxy_gimbal.py │ ├── mavproxy_gopro.py │ ├── mavproxy_graph.py │ ├── mavproxy_heliplane.py │ ├── mavproxy_help.py │ ├── mavproxy_horizon.py │ ├── mavproxy_instructor.py │ ├── mavproxy_joystick │ │ ├── __init__.py │ │ ├── controls.py │ │ ├── findjoy.py │ │ └── joysticks │ │ │ ├── FeiYing.yml │ │ │ ├── Logitech_WingMan_3D.yml │ │ │ ├── SparkFun Pro Micro.yml │ │ │ ├── T16S.yml │ │ │ ├── carolbox-usb.yml │ │ │ ├── cypress-spektrum.yml │ │ │ ├── great-planes.Interlink-X.yaml │ │ │ ├── great-planes.yml │ │ │ ├── jumper.yml │ │ │ ├── logicool-f310.yml │ │ │ ├── logitech-dual-action.yml │ │ │ ├── saili-simulator.yml │ │ │ ├── sony-playstation.yml │ │ │ ├── spektrumInterLinkDX.yml │ │ │ ├── sz-mypower-ds4.yml │ │ │ ├── taranis.yml │ │ │ ├── xbox-360.yml │ │ │ └── xboxdrv-mode2.yml │ ├── mavproxy_kmlread.py │ ├── mavproxy_layout.py │ ├── mavproxy_link.py │ ├── mavproxy_log.py │ ├── mavproxy_magical │ │ ├── __init__.py │ │ ├── data │ │ │ ├── arrow.mtl │ │ │ ├── arrow.obj │ │ │ ├── quadcopter.mtl │ │ │ └── quadcopter.obj │ │ ├── glrenderer.py │ │ ├── magical_ui.py │ │ ├── wxgeodesicgrid.py │ │ └── wxvehicle.py │ ├── mavproxy_map │ │ ├── GAreader.py │ │ ├── __init__.py │ │ ├── data │ │ │ ├── barrell.png │ │ │ ├── blueantenna.png │ │ │ ├── blueblimp.png │ │ │ ├── blueboat.png │ │ │ ├── bluecopter.png │ │ │ ├── blueheli.png │ │ │ ├── blueplane.png │ │ │ ├── bluerover.png │ │ │ ├── bluesinglecopter.png │ │ │ ├── bluesub.png │ │ │ ├── camera-small-red.png │ │ │ ├── cloud.png │ │ │ ├── flag.png │ │ │ ├── flame.png │ │ │ ├── greenantenna.png │ │ │ ├── greenblimp.png │ │ │ ├── greencopter.png │ │ │ ├── greenheli.png │ │ │ ├── greenplane.png │ │ │ ├── greenrover.png │ │ │ ├── greensinglecopter.png │ │ │ ├── greensub.png │ │ │ ├── hawk.png │ │ │ ├── home.png │ │ │ ├── hoop.png │ │ │ ├── image_vector_files │ │ │ │ └── heli_icon.svg │ │ │ ├── loading.jpg │ │ │ ├── migbird.png │ │ │ ├── orangecopter.png │ │ │ ├── orangeheli.png │ │ │ ├── orangeplane.png │ │ │ ├── orangerover.png │ │ │ ├── purpleplane.png │ │ │ ├── rallypoint.png │ │ │ ├── ramp.png │ │ │ ├── redantenna.png │ │ │ ├── redblimp.png │ │ │ ├── redboat.png │ │ │ ├── redcopter.png │ │ │ ├── redheli.png │ │ │ ├── redplane.png │ │ │ ├── redrover.png │ │ │ ├── redsinglecopter.png │ │ │ ├── redsub.png │ │ │ └── unavailable.jpg │ │ ├── mp_elevation.py │ │ ├── mp_slipmap.py │ │ ├── mp_slipmap_ui.py │ │ ├── mp_slipmap_util.py │ │ ├── mp_tile.py │ │ └── srtm.py │ ├── mavproxy_message.py │ ├── mavproxy_messagerate.py │ ├── mavproxy_misc.py │ ├── mavproxy_misseditor │ │ ├── __init__.py │ │ ├── button_renderer.py │ │ ├── me_defines.py │ │ ├── me_event.py │ │ ├── missionEditorFrame.py │ │ └── mission_editor.py │ ├── mavproxy_mmap │ │ ├── __init__.py │ │ ├── mmap_app │ │ │ ├── bing.js │ │ │ ├── bluemarble.js │ │ │ ├── drone-md.png │ │ │ ├── drone-sm.png │ │ │ ├── index.html │ │ │ └── modestmaps.js │ │ └── mmap_server.py │ ├── mavproxy_mode.py │ ├── mavproxy_movinghome.py │ ├── mavproxy_mqtt.py │ ├── mavproxy_msg.py │ ├── mavproxy_nmeagps.py │ ├── mavproxy_nmeaout.py │ ├── mavproxy_nokov │ │ └── __init__.py │ ├── mavproxy_nsh.py │ ├── mavproxy_ntrip.py │ ├── mavproxy_oldwp.py │ ├── mavproxy_optitrack │ │ ├── DataDescriptions.py │ │ ├── MoCapData.py │ │ ├── NatNetClient.py │ │ └── __init__.py │ ├── mavproxy_osd.py │ ├── mavproxy_output.py │ ├── mavproxy_param.py │ ├── mavproxy_paramedit │ │ ├── __init__.py │ │ ├── checklisteditor.py │ │ ├── param_editor.py │ │ ├── param_editor.wxg │ │ ├── param_editor_frame.py │ │ └── ph_event.py │ ├── mavproxy_park.py │ ├── mavproxy_ppp.py │ ├── mavproxy_proximity.py │ ├── mavproxy_rally.py │ ├── mavproxy_rallypoint_protocol.py │ ├── mavproxy_rc.py │ ├── mavproxy_rcsetup.py │ ├── mavproxy_relay.py │ ├── mavproxy_restserver.py │ ├── mavproxy_sail.py │ ├── mavproxy_sensors.py │ ├── mavproxy_serial.py │ ├── mavproxy_setpos.py │ ├── mavproxy_signing.py │ ├── mavproxy_silvus.py │ ├── mavproxy_smartcamera │ │ ├── __init__.py │ │ ├── sc_ExifWriter.py │ │ ├── sc_SonyQX1.py │ │ ├── sc_config.py │ │ ├── sc_main.py │ │ ├── sc_video.py │ │ ├── sc_webcam.py │ │ ├── smart_camera.cnf │ │ └── ssdp.py │ ├── mavproxy_soar.py │ ├── mavproxy_speech.py │ ├── mavproxy_swarm.py │ ├── mavproxy_system_time.py │ ├── mavproxy_terrain.py │ ├── mavproxy_test.py │ ├── mavproxy_timesync.py │ ├── mavproxy_tracker.py │ ├── mavproxy_tuneopt.py │ ├── mavproxy_ublox │ │ └── __init__.py │ ├── mavproxy_ucenter.py │ ├── mavproxy_useralerts.py │ ├── mavproxy_vicon.py │ ├── mavproxy_warning.py │ └── mavproxy_wp.py └── tools │ ├── MAVExplorer.bat │ ├── MAVExplorer.py │ ├── graphs │ ├── ekf3Graphs.xml │ ├── ekfGraphs.xml │ ├── mavgraphs.xml │ └── mavgraphs2.xml │ ├── mavflightview.py │ └── mavpicviewer │ ├── mavpicviewer.bat │ ├── mavpicviewer.py │ ├── mavpicviewer_image.py │ ├── mavpicviewer_mosaic.py │ ├── mavpicviewer_settings.py │ └── mavpicviewer_shared.py ├── MAVProxy_Icon ├── 3.ai ├── 3.jpg ├── 3.png ├── icon.jpg ├── icon.png ├── mockup.jpg ├── source file 2.ai ├── source file.ai ├── trans-BG-2.png ├── trans-BG.png ├── white-BG-2.jpg └── white-BG.jpg ├── README.md ├── docs ├── JOYSTICKS.md └── MavProxy_Screenshot_Termux.jpg ├── requirements.txt ├── scripts └── run_flake8.py ├── setup.py ├── shortcuts ├── ReadMe.md ├── mavexplorer.desktop ├── mavexplorer.png ├── mavpicviewer.desktop ├── mavpicviewer.png ├── mavproxy.desktop └── mavproxy.png └── windows ├── MAVExplorer.ico ├── MAVProxy.ico ├── MAVProxyWinBuild.bat ├── Startup Examples ├── MAVProxyLogput.bat └── MAVProxyMultiOutput.bat ├── mavinit.scr ├── mavpicviewer.ico ├── mavproxy.iss ├── mavproxy.spec └── returnVersion.py /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = 3 | # H301: one import per line 4 | H301, 5 | # H306: imports not in alphabetical order (time, os) 6 | H306, 7 | # E226: missing whitespace around arithmetic operator 8 | E226, 9 | # E261 at least two spaces before inline comment 10 | E261, 11 | # W504 line break after binary operator 12 | W504, 13 | # E203 whitespace before ':' 14 | E203, 15 | # E221 multiple spaces before operator 16 | E221 17 | 18 | max-line-length = 127 19 | -------------------------------------------------------------------------------- /.github/workflows/python-cleanliness.yml: -------------------------------------------------------------------------------- 1 | name: test Python cleanliness 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | concurrency: 6 | group: ci-${{github.workflow}}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-22.04 12 | 13 | steps: 14 | # git checkout the PR 15 | - uses: actions/checkout@v4 16 | with: 17 | submodules: 'recursive' 18 | 19 | - name: Install dependencies 20 | run: | 21 | python -m pip install -U flake8 22 | 23 | - name: Check Python with Flake8 24 | run: | 25 | scripts/run_flake8.py MAVProxy 26 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload MAVProxy Package 5 | 6 | on: 7 | release: 8 | types: [published] 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: '3.10' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install -U pip 24 | python -m pip install -U wheel 25 | python -m pip install -U pymavlink 26 | pip install build 27 | pip install -U . 28 | git submodule update --recursive --init 29 | - name: Build package 30 | run: python -m build 31 | - name: Publish package 32 | uses: pypa/gh-action-pypi-publish@release/v1 33 | with: 34 | user: __token__ 35 | password: ${{ secrets.PYPI_API_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/windows_build.yml: -------------------------------------------------------------------------------- 1 | name: Windows Build 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | concurrency: 5 | group: ci-${{github.workflow}}-${{ github.ref }} 6 | cancel-in-progress: true 7 | 8 | jobs: 9 | build: 10 | runs-on: 'windows-latest' 11 | strategy: 12 | matrix: 13 | python-version: ['3.10'] 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | submodules: 'recursive' 19 | - uses: actions/checkout@v4 20 | - name: Set up Python ${{ matrix.python-version }} 21 | uses: actions/setup-python@v5 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | - name: Install dependencies 25 | run: | 26 | python3 -m pip install -U wheel setuptools pip 27 | python3 -m pip install -U pywin32 lxml pymavlink numpy matplotlib pyserial opencv-python PyYAML Pygame Pillow wxpython prompt-toolkit scipy 28 | python3 -m pip install -U openai wave pyaudio 29 | python3 -m pip install -U pyinstaller==6.7.0 packaging 30 | - name: Download Inno Setup installer 31 | run: curl -L -o installer.exe http://files.jrsoftware.org/is/6/innosetup-6.3.1.exe 32 | - name: Install Inno Setup 33 | run: ./installer.exe /verysilent /allusers /dir=inst 34 | - name: Build MAVProxy 35 | run: | 36 | python3 -m pip install .[recommended] --user 37 | python3 -m pip list 38 | - name: Prepare installer 39 | run: | 40 | cd MAVProxy 41 | copy ..\\windows\\mavproxy.spec 42 | pyinstaller --clean mavproxy.spec 43 | del mavproxy.spec 44 | - name: Download parameters 45 | run: | 46 | mkdir Parameters 47 | $wc = New-Object System.Net.WebClient 48 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Rover/apm.pdef.xml', 'Parameters\Rover.xml') 49 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Copter/apm.pdef.xml', 'Parameters\Copter.xml') 50 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Plane/apm.pdef.xml', 'Parameters\Plane.xml') 51 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Sub/apm.pdef.xml', 'Parameters\Sub.xml') 52 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/AntennaTracker/apm.pdef.xml', 'Parameters\AntennaTracker.xml') 53 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Heli/apm.pdef.xml', 'Parameters\Heli.xml') 54 | $wc.DownloadFile('https://autotest.ardupilot.org/Parameters/Blimp/apm.pdef.xml', 'Parameters\Blimp.xml') 55 | - name: Build installer 56 | run: | 57 | cd windows 58 | $env:VERSION=$(python returnVersion.py) 59 | python3 returnVersion.py > version.txt 60 | ISCC.exe /dMyAppVersion=$env:VERSION mavproxy.iss 61 | ls Output 62 | - name: Archive build 63 | uses: actions/upload-artifact@v4 64 | with: 65 | name: MAVProxyInstaller 66 | path: windows/Output 67 | retention-days: 7 68 | - name: Pre Release 69 | uses: "softprops/action-gh-release@v2" 70 | if: github.ref == 'refs/heads/master' 71 | with: 72 | prerelease: true 73 | name: "Development Build" 74 | tag_name: "latest" 75 | files: windows/Output/*.* 76 | token: "${{ secrets.GITHUB_TOKEN }}" 77 | - name: Release 78 | uses: "softprops/action-gh-release@v2" 79 | if: startsWith(github.ref, 'refs/tags/v') 80 | with: 81 | prerelease: false 82 | files: windows/Output/*.* 83 | token: "${{ secrets.GITHUB_TOKEN }}" 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | mavproxy 2 | *~ 3 | *.o 4 | *.pyc 5 | *.log 6 | camera/ 7 | build/ 8 | dist/ 9 | gtest/ 10 | *.tlog 11 | *.raw 12 | MANIFEST 13 | *.egg-info 14 | .DS_Store 15 | *.bak 16 | *.orig 17 | windows/version.txt 18 | /.vscode 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "MAVProxy/modules/mavproxy_cesium"] 2 | path = MAVProxy/modules/mavproxy_cesium 3 | url = https://github.com/ArduPilot/MAVCesium.git 4 | -------------------------------------------------------------------------------- /ANDROID.md: -------------------------------------------------------------------------------- 1 | ## install MAVProxy on Android ? 2 | 3 | Yes, it's possible to install MAVProxy on Android, totally unsupported, no guarantees, good luck, but here goes. 4 | 5 | ### install/load Termux Android app from .apk on github 6 | see https://github.com/termux/termux-app for more. 7 | 8 | eg: https://github.com/termux/termux-app/releases/download/v0.118.0/termux-app_v0.118.0+github-debug_armeabi-v7a.apk 9 | 10 | tip: do NOT install from play store, its a really old version. 11 | 12 | Once installed, in the termux console run these commands: 13 | ``` 14 | pkg upgrade 15 | ``` 16 | [ answer 'y' to all questions.] 17 | 18 | ``` 19 | pkg install python 20 | ``` 21 | [3.10.x at time of testing] 22 | 23 | ``` 24 | pkg install libxml2* 25 | ``` 26 | [ for -dev pkg ] 27 | 28 | ``` 29 | pkg install libxslt* 30 | ``` 31 | [ for -dev pkg ] 32 | 33 | ``` 34 | pkg install python-* 35 | ``` 36 | [ for python-dev , be sure to include the '-' here.] 37 | 38 | ``` 39 | pip install --upgrade pip 40 | ``` 41 | pip is needed for the next few packages 42 | 43 | ``` 44 | pip install wheel 45 | pip install pymavlink 46 | ``` 47 | wheel isn't installed automatically in some cases, so we install it manually first 48 | 49 | #https://superuser.com/questions/1724176/why-pip-throwing-an-error-when-installing-numpy-in-termux 50 | ``` 51 | MATHLIB="m" pip3 install numpy 52 | ``` 53 | numpy doesnt install without this extra prefix on android , so we do it first as well. 54 | 55 | ``` 56 | pip install mavproxy 57 | ``` 58 | finally we install mavproxy! 59 | 60 | ``` 61 | pkg install mlocate 62 | updatedb 63 | ``` 64 | optionally other things that might be helpful 65 | 66 | ``` 67 | locate mavproxy.py 68 | ``` 69 | where is it? 70 | 71 | ``` 72 | mavproxy.py 73 | 74 | mavproxy.py --master=udp:1.2.3.4:14550 75 | ``` 76 | a few different ways to run it! 77 | eg: if u have udp mavlink data being forward to your phone over wifi, then 1.2.3.4 should be your PHONE's ip address, and it will receive the data. 78 | 79 | 80 | known issues: 81 | * --console and all the GUI parts of mavproxy don't work, as the 'WX' package isn't available for android. 82 | * no idea if using a usb/serial connecton works, but UDP-over-wifi definitely does! 83 | * totally unsupported, may break at any time and stop working. please do a pull-request to edit this file if you find these instructions no longer work. 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /MAVProxy/MAVLink.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | true 17 | 18 | 19 | 20 | aileron 21 | double 22 | /controls/flight/aileron 23 | 24 | 25 | elevator 26 | double 27 | /controls/flight/elevator 28 | 29 | 30 | rudder 31 | double 32 | /controls/flight/rudder 33 | 34 | 35 | throttle 36 | double 37 | /controls/engines/engine[0]/throttle 38 | 39 | 40 | 41 | 42 | 43 | true 44 | magic,0x4c56414d 45 | 46 | 47 | 48 | latitude 49 | double 50 | /position/latitude-deg 51 | 52 | 53 | longitude 54 | double 55 | /position/longitude-deg 56 | 57 | 58 | altitude 59 | double 60 | /position/altitude-ft 61 | 62 | 63 | heading 64 | double 65 | /orientation/heading-deg 66 | 67 | 68 | 69 | 70 | speed - north 71 | double 72 | /velocities/speed-north-fps 73 | 74 | 75 | speed - east 76 | double 77 | /velocities/speed-east-fps 78 | 79 | 80 | 81 | 82 | 83 | x-accel 84 | double 85 | /accelerations/pilot/x-accel-fps_sec 86 | 87 | 88 | y-accel 89 | double 90 | /accelerations/pilot/y-accel-fps_sec 91 | 92 | 93 | z-accel 94 | double 95 | /accelerations/pilot/z-accel-fps_sec 96 | 97 | 98 | 99 | roll-rate 100 | double 101 | /orientation/roll-rate-degps 102 | 103 | 104 | 105 | pitch-rate 106 | double 107 | /orientation/pitch-rate-degps 108 | 109 | 110 | 111 | yaw-rate 112 | double 113 | /orientation/yaw-rate-degps 114 | 115 | 116 | 117 | roll-deg 118 | double 119 | /orientation/roll-deg 120 | 121 | 122 | 123 | pitch-deg 124 | double 125 | /orientation/pitch-deg 126 | 127 | 128 | 129 | yaw-deg 130 | double 131 | /orientation/yaw-deg 132 | 133 | 134 | 135 | airspeed-kt 136 | double 137 | /velocities/airspeed-kt 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /MAVProxy/MAVProxyWinLAN.bat: -------------------------------------------------------------------------------- 1 | cd ..\ 2 | python.exe -m pip install --upgrade build . --user 3 | python.exe .\MAVProxy\mavproxy.py --master=0.0.0.0:14550 --console 4 | pause 5 | -------------------------------------------------------------------------------- /MAVProxy/MAVProxyWinUSB.bat: -------------------------------------------------------------------------------- 1 | cd ..\ 2 | python.exe -m pip install --upgrade build . --user 3 | python.exe .\MAVProxy\mavproxy.py --console 4 | pause -------------------------------------------------------------------------------- /MAVProxy/__init__.py: -------------------------------------------------------------------------------- 1 | '''MAVProxy MAVLink ground station libraries''' 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/__init__.py: -------------------------------------------------------------------------------- 1 | # Allow imports 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/ANUGA/README.txt: -------------------------------------------------------------------------------- 1 | 2 | This module adapted from ANUGA: 3 | 4 | https://anuga.anu.edu.au/ 5 | 6 | Many thanks to ANUGA for making this code available under the GPL! 7 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/ANUGA/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/lib/ANUGA/__init__.py -------------------------------------------------------------------------------- /MAVProxy/modules/lib/LowPassFilter2p.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from math import * 4 | 5 | class LowPassFilter2p: 6 | def __init__(self, sample_freq, cutoff_freq): 7 | self.cutoff_freq = cutoff_freq 8 | self.sample_freq = sample_freq 9 | self.a1 = 0.0 10 | self.a2 = 0.0 11 | self.b0 = 0.0 12 | self.b1 = 0.0 13 | self.b2 = 0.0 14 | self.delay_element_1 = None 15 | self.delay_element_2 = None 16 | self.set_cutoff_frequency(sample_freq, cutoff_freq) 17 | 18 | def set_cutoff_frequency(self, sample_freq, cutoff_freq): 19 | self.cutoff_freq = cutoff_freq 20 | if self.cutoff_freq <= 0.0: 21 | return 22 | fr = self.sample_freq/self.cutoff_freq 23 | ohm = tan(pi/fr) 24 | c = 1.0+2.0*cos(pi/4.0)*ohm + ohm*ohm 25 | self.b0 = ohm*ohm/c 26 | self.b1 = 2.0*self.b0 27 | self.b2 = self.b0 28 | self.a1 = 2.0*(ohm*ohm-1.0)/c 29 | self.a2 = (1.0-2.0*cos(pi/4.0)*ohm+ohm*ohm)/c 30 | 31 | def apply(self, sample): 32 | if self.delay_element_1 is None: 33 | self.delay_element_1 = sample 34 | self.delay_element_2 = sample 35 | delay_element_0 = sample - (self.delay_element_1 * self.a1) - (self.delay_element_2 * self.a2) 36 | output = (delay_element_0 * self.b0) + (self.delay_element_1 * self.b1) + (self.delay_element_2 * self.b2) 37 | 38 | self.delay_element_2 = self.delay_element_1 39 | self.delay_element_1 = delay_element_0 40 | 41 | return output 42 | 43 | if __name__ == "__main__": 44 | from pymavlink.rotmat import Vector3 45 | filter = LowPassFilter2p(1000.0, 98.0) 46 | 47 | v2 = filter.apply(Vector3(1,2,3)) 48 | print(v2) 49 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/MacOS/__init__.py: -------------------------------------------------------------------------------- 1 | # version of matplotlib backends modified to work with MacOS 2 | 3 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/__init__.py: -------------------------------------------------------------------------------- 1 | # Allow imports. 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/dumpstacks.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import threading, sys, traceback 5 | 6 | # Import dumpstacks to install a SIGQUIT handler that shows a stack dump for all stacks 7 | # From http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application 8 | 9 | def dumpstacks(signal, frame): 10 | id2name = dict([(th.ident, th.name) for th in threading.enumerate()]) 11 | code = [] 12 | for threadId, stack in sys._current_frames().items(): 13 | code.append("\n# Thread: %s(%d)" % (id2name.get(threadId, ""), threadId)) 14 | for filename, lineno, name, line in traceback.extract_stack(stack): 15 | code.append('File: "%s", line %d, in %s' % (filename, lineno, name)) 16 | if line: 17 | code.append(" %s" % (line.strip())) 18 | print("\n".join(code)) 19 | 20 | try: 21 | import signal 22 | signal.signal(signal.SIGQUIT, dumpstacks) 23 | except Exception as e: 24 | # Silently ignore failures installing this handler (probably won't work on Windows) 25 | pass 26 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/graph_ui.py: -------------------------------------------------------------------------------- 1 | from MAVProxy.modules.lib import grapher 2 | from MAVProxy.modules.lib import multiproc 3 | 4 | import errno 5 | import socket 6 | import copy 7 | 8 | graph_count = 1 9 | 10 | class Graph_UI(object): 11 | """docstring for ClassName""" 12 | def __init__(self, mestate): 13 | self.mestate = mestate 14 | self.xlim = None 15 | global graph_count 16 | self.count = graph_count 17 | graph_count += 1 18 | self.xlim_pipe = multiproc.Pipe() 19 | 20 | def display_graph(self, graphdef, flightmode_colourmap=None): 21 | '''display a graph''' 22 | if 'mestate' in globals(): 23 | self.mestate.console.write("Expression: %s\n" % ' '.join(graphdef.expression.split())) 24 | else: 25 | self.mestate.child_pipe_send_console.send("Expression: %s\n" % ' '.join(graphdef.expression.split())) 26 | #mestate.mlog.reduce_by_flightmodes(mestate.flightmode_selections) 27 | 28 | #setup the graph, then pass to a new process and display 29 | self.mg = grapher.MavGraph(flightmode_colourmap) 30 | if self.mestate.settings.title is not None: 31 | self.mg.set_title(self.mestate.settings.title) 32 | else: 33 | self.mg.set_title(graphdef.name) 34 | if self.mestate.settings.max_rate > 0: 35 | self.mg.set_max_message_rate(self.mestate.settings.max_rate) 36 | self.mg.set_marker(self.mestate.settings.marker) 37 | self.mg.set_condition(self.mestate.settings.condition) 38 | self.mg.set_xaxis(self.mestate.settings.xaxis) 39 | self.mg.set_linestyle(self.mestate.settings.linestyle) 40 | self.mg.set_show_flightmode(self.mestate.settings.show_flightmode) 41 | self.mg.set_legend(self.mestate.settings.legend) 42 | self.mg.add_mav(copy.copy(self.mestate.mlog)) 43 | for f in graphdef.expression.split(): 44 | self.mg.add_field(f) 45 | self.mg.process(self.mestate.flightmode_selections, self.mestate.mlog._flightmodes) 46 | self.lenmavlist = len(self.mg.mav_list) 47 | #Important - mg.mav_list is the full logfile and can be very large in size 48 | #To avoid slowdowns in Windows (which copies the vars to the new process) 49 | #We need to empty this var when we're finished with it 50 | self.mg.mav_list = [] 51 | child = multiproc.Process(target=self.mg.show, args=[self.lenmavlist,], kwargs={"xlim_pipe" : self.xlim_pipe}) 52 | child.start() 53 | self.xlim_pipe[1].close() 54 | self.mestate.mlog.rewind() 55 | 56 | def check_xlim_change(self): 57 | '''check for new X bounds''' 58 | if self.xlim_pipe is None: 59 | return None 60 | xlim = None 61 | try: 62 | while self.xlim_pipe[0].poll(): 63 | xlim = self.xlim_pipe[0].recv() 64 | except Exception: 65 | return None 66 | if xlim != self.xlim: 67 | return xlim 68 | return None 69 | 70 | def set_xlim(self, xlim): 71 | '''set new X bounds''' 72 | if self.xlim_pipe is not None and self.xlim != xlim: 73 | #print("send0: ", graph_count, xlim) 74 | try: 75 | self.xlim_pipe[0].send(xlim) 76 | except IOError: 77 | return False 78 | self.xlim = xlim 79 | return True 80 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/graphdefinition.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GraphDefinition class 3 | ''' 4 | 5 | class GraphDefinition(object): 6 | '''a pre-defined graph''' 7 | def __init__(self, name, expression, description, expressions, filename): 8 | self.name = name 9 | self.expression = expression 10 | self.description = description 11 | self.expressions = expressions 12 | self.filename = filename 13 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/icon.py: -------------------------------------------------------------------------------- 1 | """ 2 | MAVProxy icons generator 3 | """ 4 | import numpy as np 5 | from io import BytesIO 6 | from matplotlib.figure import Figure 7 | from matplotlib.gridspec import GridSpec 8 | import matplotlib.path as mpath 9 | import matplotlib.patches as mpatches 10 | from MAVProxy.modules.lib.wx_loader import wx 11 | 12 | 13 | class SimpleIcon(): 14 | """ 15 | Generate icons with Matplotlib. 16 | """ 17 | def __init__(self, text=None): 18 | LIGHT_BLUE_BACKGROUND = "#afceff" 19 | VIOLET_FONT = "#4800f0" 20 | t1 = np.arange(0.0, 5.0, 0.1) 21 | t2 = np.arange(0.0, 5.0, 0.02) 22 | 23 | def f(t): 24 | return np.exp(-t) * np.cos(2*np.pi*t) 25 | 26 | fig = Figure(figsize=(1.28, 1.28), facecolor=LIGHT_BLUE_BACKGROUND) 27 | spec = GridSpec(nrows=2, ncols=1, wspace=0, hspace=0.0, height_ratios=[1, 2]) 28 | ax = fig.add_subplot(spec[0]) 29 | ax.text(0, 0.8, 'MAV', style='italic', fontsize=20, weight='bold', color=VIOLET_FONT) 30 | if text is None: 31 | text = "GRAPH" 32 | ax.text(0, 0.1, text.upper(), style='italic', fontsize=14, weight='bold', color=VIOLET_FONT) 33 | ax.axis('off') 34 | 35 | ax = fig.add_subplot(spec[1], facecolor=LIGHT_BLUE_BACKGROUND) 36 | if text == "GRAPH" or text == "EXPLORER": 37 | ax.plot(t1, f(t1), color='tab:green', marker='o') 38 | ax.plot(t2, f(t2), color='red') 39 | ax.set_xticks(t1, minor=True) 40 | ax.grid(True, which='both', linestyle="--") 41 | if text == "CONSOLE": 42 | ax.plot([0, 2.5], [2.5, 1.25], color='red', linewidth=4) 43 | ax.plot([0, 2.5], [0, 1.25], color='red', linewidth=4) 44 | ax.plot([3, 5], [0, 0], color='red', linewidth=4) 45 | ax.axis('off') 46 | if text == "MAP": 47 | path_data = [ 48 | (mpath.Path.MOVETO, [2.5, 0]), 49 | (mpath.Path.LINETO, [1.25, 2.5]), 50 | (mpath.Path.CURVE3, [2.5, 5]), 51 | (mpath.Path.CURVE3, [3.75, 2.5]), 52 | (mpath.Path.LINETO, [3.75, 2.5]), 53 | (mpath.Path.CLOSEPOLY, [2.5, 0])] 54 | codes, verts = zip(*path_data) 55 | path = mpath.Path(verts, codes) 56 | 57 | patch = mpatches.PathPatch(path, facecolor='red', lw=2) 58 | ax.add_patch(patch) 59 | circle_neg = mpatches.Circle((2.5, 2.5), 0.5, color='white') 60 | ax.add_patch(circle_neg) 61 | 62 | ax.plot([0, 5/3.0, 10/3.0, 5], [5, 4, 5, 4], color='black', linewidth=2) 63 | ax.plot([0, 5/3.0, 10/3.0, 5], [-1, -2, -1, -2], color='black', linewidth=2) 64 | ax.plot([0, 0], [-1, 5], color='black', linewidth=2) 65 | ax.plot([5/3.0, 5/3.0], [-2, 4], color='black', linewidth=2) 66 | ax.plot([10/3.0, 10/3.0], [-1, 5], color='black', linewidth=2) 67 | ax.plot([5, 5], [-2, 4], color='black', linewidth=2) 68 | ax.set_xlim(-0.5, 5.5) 69 | ax.set_ylim(-2.5, 5.5) 70 | ax.axis('off') 71 | 72 | buf = BytesIO() 73 | fig.savefig(buf, format='png') 74 | buf.seek(0) 75 | svgimg = wx.Image(buf, wx.BITMAP_TYPE_PNG) 76 | self.img = svgimg 77 | 78 | def get_ico(self): 79 | """Get the ico from the image bitmap. 80 | need to be call after the wx.app is created.""" 81 | return wx.Icon(wx.Bitmap(self.img)) 82 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/live_graph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | 5 | MAVProxy realtime graphing module, partly based on the wx graphing 6 | demo by Eli Bendersky (eliben@gmail.com) 7 | 8 | http://eli.thegreenplace.net/files/prog_code/wx_mpl_dynamic_graph.py.txt 9 | """ 10 | 11 | import platform 12 | from MAVProxy.modules.lib import mp_util 13 | from MAVProxy.modules.lib import multiproc 14 | 15 | class LiveGraph(): 16 | ''' 17 | a live graph object using wx and matplotlib 18 | All of the GUI work is done in a child process to provide some insulation 19 | from the parent mavproxy instance and prevent instability in the GCS 20 | 21 | New data is sent to the LiveGraph instance via a pipe 22 | ''' 23 | def __init__(self, 24 | fields, 25 | title='MAVProxy: LiveGraph', 26 | timespan=20.0, 27 | tickresolution=0.2, 28 | colors=[ 'red', 'green', 'blue', 'orange', 'olive', 'cyan', 'magenta', 'brown', 29 | 'violet', 'purple', 'grey', 'black'], 30 | labels=None): 31 | self.fields = fields 32 | self.labels = labels 33 | self.colors = colors 34 | self.title = title 35 | self.timespan = timespan 36 | self.tickresolution = tickresolution 37 | self.values = [None]*len(self.fields) 38 | self.parent_pipe,self.child_pipe = multiproc.Pipe() 39 | self.close_graph = multiproc.Event() 40 | self.close_graph.clear() 41 | self.child = multiproc.Process(target=self.child_task) 42 | self.child.start() 43 | 44 | def child_task(self): 45 | '''child process - this holds all the GUI elements''' 46 | mp_util.child_close_fds() 47 | 48 | import matplotlib, platform 49 | if platform.system() != "Darwin": 50 | # on MacOS we can't set WxAgg here as it conflicts with the MacOS version 51 | matplotlib.use('WXAgg') 52 | 53 | from MAVProxy.modules.lib import wx_processguard 54 | from MAVProxy.modules.lib.wx_loader import wx 55 | 56 | app = wx.App(False) 57 | from MAVProxy.modules.lib import live_graph_ui 58 | app.frame = live_graph_ui.GraphFrame(state=self) 59 | app.frame.Show() 60 | app.MainLoop() 61 | 62 | def add_values(self, values): 63 | '''add some data to the graph''' 64 | if self.child.is_alive(): 65 | self.parent_pipe.send(values) 66 | 67 | def close(self): 68 | '''close the graph''' 69 | self.close_graph.set() 70 | if self.is_alive(): 71 | self.child.join(2) 72 | 73 | def is_alive(self): 74 | '''check if graph is still going''' 75 | return self.child.is_alive() 76 | 77 | 78 | if __name__ == "__main__": 79 | multiproc.freeze_support() 80 | # test the graph 81 | import time, math 82 | import live_graph 83 | livegraph = live_graph.LiveGraph(['sin(t)', 'cos(t)', 'sin(t+1)', 84 | 'cos(t+1)', 'sin(t+2)', 'cos(t+2)', 85 | 'cos(t+1)', 'sin(t+2)', 'cos(t+2)', 'x'], 86 | timespan=30, 87 | title='Graph Test', 88 | labels=['a','b','c','d']) 89 | while livegraph.is_alive(): 90 | t = time.time() 91 | livegraph.add_values([math.sin(t), math.cos(t), 92 | math.sin(t+1), math.cos(t+1), 93 | math.sin(t+1), math.cos(t+1), 94 | math.sin(t+1), math.cos(t+1), 95 | math.sin(t+2), math.cos(t+2)]) 96 | time.sleep(0.05) 97 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/mp_widgets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | some useful wx widgets 4 | 5 | Andrew Tridgell 6 | June 2012 7 | ''' 8 | 9 | from MAVProxy.modules.lib.wx_loader import wx 10 | import cv2 11 | import numpy as np 12 | import warnings 13 | 14 | class ImagePanel(wx.Panel): 15 | '''a resizable panel containing an image''' 16 | def __init__(self, parent, img): 17 | wx.Panel.__init__(self, parent, -1, size=(1, 1)) 18 | self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) 19 | self.set_image(img) 20 | self.Bind(wx.EVT_PAINT, self.on_paint) 21 | 22 | def on_paint(self, event): 23 | '''repaint the image''' 24 | dc = wx.AutoBufferedPaintDC(self) 25 | dc.DrawBitmap(self._bmp, 0, 0) 26 | 27 | def set_image(self, img): 28 | '''set the image to be displayed''' 29 | with warnings.catch_warnings(): 30 | warnings.simplefilter('ignore') 31 | if hasattr(img, 'shape'): 32 | (width, height) = (img.shape[1], img.shape[0]) 33 | self._bmp = wx.BitmapFromBuffer(width, height, np.uint8(img)) # http://stackoverflow.com/a/16866833/2559632 34 | elif hasattr(img, 'GetHeight'): 35 | self._bmp = wx.BitmapFromImage(img) 36 | else: 37 | print("Unsupported image type: %s" % type(img)) 38 | return 39 | self.SetMinSize((self._bmp.GetWidth(), self._bmp.GetHeight())) 40 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/multiproc.py: -------------------------------------------------------------------------------- 1 | ''' 2 | multi-processing abstraction 3 | This wraps the multiprocessing module, using billiard on MacOS 4 | and multiprocessing on Linux and Windows 5 | 6 | The key problem on MacOS is that you can't fork in any process that uses 7 | threading, which is almost all of processes as so many libraries use 8 | threads. So instead billiard uses an approach that uses fork+exec and re-runs 9 | the script in the child. It is horrible, but it seems to be the only way to 10 | make things work on MacOS 11 | ''' 12 | 13 | class PipeQueue(object): 14 | '''simulate a queue using a pipe. This is used to avoid a problem with 15 | pipes on MacOS, while still keeping similar syntax''' 16 | def __init__(self): 17 | (self.sender,self.receiver) = Pipe() 18 | self.alive = True 19 | self.pending = [] 20 | 21 | def close(self): 22 | self.alive = False 23 | self.sender.close() 24 | self.receiver.close() 25 | 26 | def put(self, *args): 27 | if not self.alive: 28 | return 29 | try: 30 | self.sender.send(*args) 31 | except Exception: 32 | self.close() 33 | 34 | def fill(self): 35 | if not self.alive: 36 | return 37 | try: 38 | while self.receiver.poll(): 39 | m = self.receiver.recv() 40 | self.pending.append(m) 41 | except Exception: 42 | self.alive = False 43 | self.close() 44 | 45 | def get(self): 46 | if not self.alive: 47 | return None 48 | self.fill() 49 | if len(self.pending) > 0: 50 | return self.pending.pop(0) 51 | return None 52 | 53 | def qsize(self): 54 | self.fill() 55 | return len(self.pending) 56 | 57 | def empty(self): 58 | return self.qsize() == 0 59 | 60 | import platform, os, sys 61 | 62 | # we use billiard (and forking disable) on MacOS, and also if USE_BILLIARD environment 63 | # is set. Using USE_BILLIARD allows for debugging of the crazy forking disable approach on 64 | # a saner platform 65 | # As of Python 3.8 the default start method for macOS is spawn and billiard is not required. 66 | if ((platform.system() == 'Darwin' or os.environ.get('USE_BILLIARD',None) is not None) 67 | and sys.version_info < (3, 8)): 68 | from billiard import Process, forking_enable, freeze_support, Pipe, Semaphore, Event, Lock 69 | forking_enable(False) 70 | Queue = PipeQueue 71 | else: 72 | from multiprocessing import Process, freeze_support, Pipe, Semaphore, Event, Lock, Queue 73 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/optparse_gui/README.txt: -------------------------------------------------------------------------------- 1 | This is optparse_gui from http://code.google.com/p/optparse-gui/ 2 | 3 | Thanks to slider for a great library! 4 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/param_ftp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | decode ftp parameter protocol data 4 | ''' 5 | 6 | import struct 7 | import sys 8 | 9 | class ParamData(object): 10 | def __init__(self): 11 | # params as (name, value, ptype) 12 | self.params = [] 13 | # defaults as (name, value, ptype) 14 | self.defaults = None 15 | 16 | def add_param(self, name, value, ptype): 17 | self.params.append((name,value,ptype)) 18 | 19 | def add_default(self, name, value, ptype): 20 | if self.defaults is None: 21 | self.defaults = [] 22 | self.defaults.append((name,value,ptype)) 23 | 24 | def ftp_param_decode(data): 25 | '''decode parameter data, returning ParamData''' 26 | pdata = ParamData() 27 | 28 | magic = 0x671b 29 | magic_defaults = 0x671c 30 | if len(data) < 6: 31 | return None 32 | magic2,num_params,total_params = struct.unpack(" 0 and data[0] == pad_byte: 58 | # skip pad bytes 59 | data = data[1:] 60 | 61 | if len(data) == 0: 62 | break 63 | 64 | ptype, plen = struct.unpack(">4) & 0x0F 66 | has_default = with_defaults and (flags&1) != 0 67 | ptype &= 0x0F 68 | 69 | if not ptype in data_types: 70 | print("paramftp: bad type 0x%x" % ptype) 71 | return None 72 | 73 | (type_len, type_format) = data_types[ptype] 74 | default_len = type_len if has_default else 0 75 | 76 | name_len = ((plen>>4) & 0x0F) + 1 77 | common_len = (plen & 0x0F) 78 | name = last_name[0:common_len] + data[2:2+name_len] 79 | vdata = data[2+name_len:2+name_len+type_len+default_len] 80 | last_name = name 81 | data = data[2+name_len+type_len+default_len:] 82 | if with_defaults: 83 | if has_default: 84 | v1,v2, = struct.unpack("<" + type_format + type_format, vdata) 85 | pdata.add_param(name, v1, ptype) 86 | pdata.add_default(name, v2, ptype) 87 | else: 88 | v, = struct.unpack("<" + type_format, vdata) 89 | pdata.add_param(name, v, ptype) 90 | pdata.add_default(name, v, ptype) 91 | else: 92 | v, = struct.unpack("<" + type_format, vdata) 93 | pdata.add_param(name, v, ptype) 94 | count += 1 95 | 96 | if count != total_params: 97 | print("paramftp: bad count %u should be %u" % (count, total_params)) 98 | return None 99 | 100 | return pdata 101 | 102 | if __name__ == "__main__": 103 | import sys 104 | fname = sys.argv[1] 105 | data = open(fname,'rb').read() 106 | print("Decoding file of length %u" % len(data)) 107 | pdata = ftp_param_decode(data) 108 | if pdata is None: 109 | print("Decode failed") 110 | sys.exit(1) 111 | for (name,value,ptype) in pdata.params: 112 | print(name.decode('utf-8'), value) 113 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/textconsole.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | MAVProxy default console 5 | """ 6 | import sys 7 | 8 | class SimpleConsole(): 9 | ''' 10 | a message console for MAVProxy 11 | ''' 12 | def __init__(self): 13 | pass 14 | 15 | def write(self, text, fg='black', bg='white'): 16 | '''write to the console''' 17 | if isinstance(text, str): 18 | sys.stdout.write(text) 19 | else: 20 | sys.stdout.write(str(text)) 21 | sys.stdout.flush() 22 | 23 | def writeln(self, text, fg='black', bg='white'): 24 | '''write to the console with linefeed''' 25 | if not isinstance(text, str): 26 | text = str(text) 27 | self.write(text + '\n', fg=fg, bg=bg) 28 | 29 | def set_status(self, name, text='', row=0, fg='black', bg='white'): 30 | '''set a status value''' 31 | pass 32 | 33 | def error(self, text, fg='red', bg='white'): 34 | self.writeln(text, fg=fg, bg=bg) 35 | 36 | def close(self): 37 | pass 38 | 39 | def is_alive(self): 40 | '''check if we are alive''' 41 | return True 42 | 43 | def set_menu(self, menu, callback): 44 | pass 45 | 46 | if __name__ == "__main__": 47 | # test the console 48 | import time 49 | console = SimpleConsole() 50 | while console.is_alive(): 51 | console.write('Tick', fg='red') 52 | console.write(" %s " % time.asctime()) 53 | console.writeln('tock', bg='yellow') 54 | time.sleep(0.5) 55 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wx_loader.py: -------------------------------------------------------------------------------- 1 | from MAVProxy.modules.lib import wx_util 2 | 3 | if not wx_util.safe: 4 | print('Cannot access wx from main thread.') 5 | import traceback 6 | print(traceback.print_stack()) 7 | raise Exception('Cannot access wx from main thread') 8 | 9 | import wx 10 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wx_processguard.py: -------------------------------------------------------------------------------- 1 | # Explicit information for the Python loader 2 | # that this subprocess can load wx, which is not process-safe. 3 | 4 | from MAVProxy.modules.lib import wx_util 5 | 6 | wx_util.safe = True 7 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wx_util.py: -------------------------------------------------------------------------------- 1 | # Maintain the guard for wx being able to be 2 | # loaded on this process. This is only needed 3 | # for Darwin, so to reduce error cases, only 4 | # implement it on Darwin. 5 | 6 | import sys 7 | safe = sys.platform != 'darwin' 8 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxconsole_util.py: -------------------------------------------------------------------------------- 1 | class Text(): 2 | '''text to write to console''' 3 | def __init__(self, text, fg='black', bg='white'): 4 | self.text = text 5 | self.fg = fg 6 | self.bg = bg 7 | 8 | class Value(): 9 | '''a value for the status bar''' 10 | def __init__(self, name, text, row=0, fg='black', bg='white'): 11 | self.name = name 12 | self.text = text 13 | self.row = row 14 | self.fg = fg 15 | self.bg = bg -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxgrapheditor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Graphical editing of graph definition 3 | ''' 4 | from MAVProxy.modules.lib.wx_loader import wx 5 | from MAVProxy.modules.lib.graphdefinition import GraphDefinition 6 | 7 | class GraphDialog(wx.Dialog): 8 | def __init__(self, title, graphdef, callback): 9 | wx.Dialog.__init__(self, None, -1, title, size=(900, 400)) 10 | 11 | self.callback = callback 12 | self.graphdef = graphdef 13 | 14 | self.panel = wx.Panel(self, -1) 15 | vbox = wx.BoxSizer(wx.VERTICAL) 16 | 17 | # name entry 18 | hbox_name = wx.BoxSizer(wx.HORIZONTAL) 19 | st_name = wx.StaticText(self.panel, -1, 'Name: ') 20 | self.tc_name = wx.TextCtrl(self.panel, -1, size=(400, -1)) 21 | try: 22 | self.tc_name.Value = self.graphdef.name 23 | except Exception: 24 | self.tc_name.Value = 'UNKNOWN' 25 | hbox_name.Add(st_name, 0, wx.LEFT, 10) 26 | hbox_name.Add(self.tc_name, 0, wx.LEFT, 35) 27 | vbox.Add(hbox_name, 0, wx.TOP, 10) 28 | 29 | # expression entry 30 | st = wx.StaticText(self.panel, -1, 'Expressions: ') 31 | vbox.Add(st, 0, wx.LEFT, 10) 32 | 33 | hbox_expressions = wx.BoxSizer(wx.HORIZONTAL) 34 | self.tc_expressions = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE|wx.HSCROLL, size=(800, 80)) 35 | elist = [] 36 | for e in self.graphdef.expressions: 37 | e = ' '.join(e.split()) 38 | elist.append(e) 39 | self.tc_expressions.Value = '\n'.join(elist) 40 | vbox.Add(self.tc_expressions, 0, wx.LEFT, 15) 41 | 42 | # description entry 43 | st = wx.StaticText(self.panel, -1, 'Description: ') 44 | vbox.Add(st, 0, wx.LEFT, 10) 45 | self.tc_description = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE) 46 | vbox.Add(self.tc_description, 1, wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, 15) 47 | self.tc_description.Value = self.graphdef.description 48 | 49 | # buttons 50 | button_save = wx.Button(self.panel, 1, 'Save') 51 | button_cancel = wx.Button(self.panel, 2, 'Cancel') 52 | button_test = wx.Button(self.panel, 3, 'Test') 53 | hbox_buttons = wx.BoxSizer(wx.HORIZONTAL) 54 | hbox_buttons.Add(button_save, 0, wx.LEFT, 10) 55 | hbox_buttons.Add(button_cancel, 0, wx.LEFT, 10) 56 | hbox_buttons.Add(button_test, 0, wx.LEFT, 10) 57 | vbox.Add(hbox_buttons, 0, wx.TOP, 10) 58 | self.Bind(wx.EVT_BUTTON, self.OnSave, id=1) 59 | self.Bind(wx.EVT_BUTTON, self.OnCancel, id=2) 60 | self.Bind(wx.EVT_BUTTON, self.OnTest, id=3) 61 | 62 | self.panel.SetSizer(vbox) 63 | self.Centre() 64 | 65 | def update_values(self): 66 | self.graphdef.name = self.tc_name.Value.strip() 67 | self.graphdef.expressions = self.tc_expressions.Value.split('\n') 68 | self.graphdef.description = self.tc_description.Value 69 | 70 | def OnCancel(self, event): 71 | self.Close() 72 | 73 | def OnTest(self, event): 74 | self.update_values() 75 | self.callback('test', self.graphdef) 76 | 77 | def OnSave(self, event): 78 | self.update_values() 79 | self.callback('save', self.graphdef) 80 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxhorizon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | MAVProxy horizon indicator. 5 | """ 6 | from MAVProxy.modules.lib import multiproc 7 | import time 8 | 9 | class HorizonIndicator(): 10 | ''' 11 | A horizon indicator for MAVProxy. 12 | ''' 13 | def __init__(self,title='MAVProxy: Horizon Indicator'): 14 | self.title = title 15 | # Create Pipe to send attitude information from module to UI 16 | self.child_pipe_recv,self.parent_pipe_send = multiproc.Pipe() 17 | self.close_event = multiproc.Event() 18 | self.close_event.clear() 19 | self.child = multiproc.Process(target=self.child_task) 20 | self.child.start() 21 | self.child_pipe_recv.close() 22 | 23 | def child_task(self): 24 | '''child process - this holds all the GUI elements''' 25 | self.parent_pipe_send.close() 26 | 27 | from MAVProxy.modules.lib import wx_processguard 28 | from MAVProxy.modules.lib.wx_loader import wx 29 | from MAVProxy.modules.lib.wxhorizon_ui import HorizonFrame 30 | # Create wx application 31 | app = wx.App(False) 32 | app.frame = HorizonFrame(state=self, title=self.title) 33 | app.frame.SetDoubleBuffered(True) 34 | app.frame.Show() 35 | app.MainLoop() 36 | self.close_event.set() # indicate that the GUI has closed 37 | 38 | def close(self): 39 | '''Close the window.''' 40 | self.close_event.set() 41 | if self.is_alive(): 42 | self.child.join(2) 43 | 44 | def is_alive(self): 45 | '''check if child is still going''' 46 | return self.child.is_alive() 47 | 48 | if __name__ == "__main__": 49 | # test the console 50 | multiproc.freeze_support() 51 | horizon = HorizonIndicator() 52 | while horizon.is_alive(): 53 | print('test') 54 | time.sleep(0.5) 55 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxhorizon_util.py: -------------------------------------------------------------------------------- 1 | class Attitude(): 2 | '''The current Attitude Data''' 3 | def __init__(self, attitudeMsg): 4 | self.pitch = attitudeMsg.pitch 5 | self.roll = attitudeMsg.roll 6 | self.yaw = attitudeMsg.yaw 7 | 8 | class VFR_HUD(): 9 | '''HUD Information.''' 10 | def __init__(self,hudMsg): 11 | self.airspeed = hudMsg.airspeed 12 | self.groundspeed = hudMsg.groundspeed 13 | self.heading = hudMsg.heading 14 | self.throttle = hudMsg.throttle 15 | self.climbRate = hudMsg.climb 16 | 17 | class Global_Position_INT(): 18 | '''Altitude relative to ground (GPS).''' 19 | def __init__(self,gpsINT,curTime): 20 | self.relAlt = gpsINT.relative_alt/1000.0 21 | self.curTime = curTime 22 | 23 | class BatteryInfo(): 24 | '''Voltage, current and remaning battery.''' 25 | def __init__(self,batMsg): 26 | self.voltage = batMsg.voltage_battery/1000.0 # Volts 27 | self.current = batMsg.current_battery/100.0 # Amps 28 | self.batRemain = batMsg.battery_remaining # % 29 | 30 | class FlightState(): 31 | '''Mode and arm state.''' 32 | def __init__(self,mode,armState): 33 | self.mode = mode 34 | self.armState = armState 35 | 36 | class WaypointInfo(): 37 | '''Current and final waypoint numbers, and the distance 38 | to the current waypoint.''' 39 | def __init__(self,current,final,currentDist,nextWPTime,wpBearing): 40 | self.current = current 41 | self.final = final 42 | self.currentDist = currentDist 43 | self.nextWPTime = nextWPTime 44 | self.wpBearing = wpBearing 45 | 46 | class FPS(): 47 | '''Stores intended frame rate information.''' 48 | def __init__(self,fps): 49 | self.fps = fps # if fps is zero, then the frame rate is unrestricted 50 | 51 | 52 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxsaildash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | MAVProxy sailing dashboard 5 | """ 6 | 7 | from MAVProxy.modules.lib import multiproc 8 | import time 9 | 10 | class SailingDashboard(object): 11 | ''' 12 | A sailing dashboard for MAVProxy 13 | ''' 14 | 15 | def __init__(self, title="MAVProxy: Sailing Dashboard"): 16 | self.title = title 17 | 18 | # create a pipe for communication from the module to the GUI 19 | self.child_pipe_recv, self.parent_pipe_send = multiproc.Pipe(duplex=False) 20 | self.close_event = multiproc.Event() 21 | self.close_event.clear() 22 | 23 | # create and start the child process 24 | self.child = multiproc.Process(target=self.child_task) 25 | self.child.start() 26 | 27 | # prevent the parent from using the child connection 28 | self.child_pipe_recv.close() 29 | 30 | def child_task(self): 31 | '''The child process hosts the GUI elements''' 32 | 33 | # prevent the child from using the parent connection 34 | self.parent_pipe_send.close() 35 | 36 | from MAVProxy.modules.lib import wx_processguard 37 | from MAVProxy.modules.lib.wx_loader import wx 38 | from MAVProxy.modules.lib.wxsaildash_ui import SailingDashboardFrame 39 | 40 | # create the wx application and pass self as the state 41 | app = wx.App() 42 | app.frame = SailingDashboardFrame(state=self, title=self.title, size=(800, 300)) 43 | app.frame.SetDoubleBuffered(True) 44 | app.frame.Show() 45 | app.MainLoop() 46 | 47 | # trigger a close event when the main app window is closed. 48 | # the event is monitored by the MAVProxy module which will 49 | # flag the module for unloading 50 | self.close_event.set() 51 | 52 | def close(self): 53 | '''Close the GUI''' 54 | 55 | # trigger a close event which is monitored by the 56 | # child gui process - it will close allowing the 57 | # process to be joined 58 | self.close_event.set() 59 | if self.is_alive(): 60 | self.child.join(timeout=2.0) 61 | 62 | def is_alive(self): 63 | '''Check if the GUI process is alive''' 64 | 65 | return self.child.is_alive() 66 | 67 | if __name__ == "__main__": 68 | '''A stand alone test for the sailing dashboard''' 69 | 70 | multiproc.freeze_support() 71 | sail_dash = SailingDashboard() 72 | while sail_dash.is_alive(): 73 | print('sailing dashboard is alive') 74 | time.sleep(0.5) 75 | 76 | 77 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxsaildash_util.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MAVProxy sailing dashboard utility classes 3 | ''' 4 | 5 | import enum 6 | 7 | class WindReference(enum.Enum): 8 | ''' 9 | An enumeration for the wind reference (either RELATIVE or TRUE) 10 | ''' 11 | 12 | RELATIVE = 1 13 | TRUE = 2 14 | 15 | class SpeedUnit(enum.Enum): 16 | ''' 17 | An enumeration for the units of speed: kph, mph, or knots 18 | ''' 19 | 20 | KPH = 1 21 | MPH = 2 22 | KNOTS = 3 23 | 24 | class WindAngleAndSpeed(object): 25 | ''' 26 | Wind angle and speed attributes 27 | ''' 28 | 29 | def __init__(self, reference, angle, speed, unit): 30 | self.wind_reference = reference 31 | self.wind_angle = angle 32 | self.wind_speed = speed 33 | self.wind_speed_unit = unit 34 | 35 | class WaterSpeedAndHeading(object): 36 | ''' 37 | Water speed and heading attributes 38 | ''' 39 | 40 | def __init__(self, water_speed, heading_true): 41 | self.water_speed = water_speed 42 | self.heading_true = heading_true 43 | -------------------------------------------------------------------------------- /MAVProxy/modules/lib/wxsettings.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Graphical editing of mp_settings object 3 | ''' 4 | import os, sys 5 | from MAVProxy.modules.lib import multiproc 6 | import threading 7 | 8 | class WXSettings(object): 9 | ''' 10 | a graphical settings dialog for mavproxy 11 | ''' 12 | def __init__(self, settings): 13 | self.settings = settings 14 | self.parent_pipe,self.child_pipe = multiproc.Pipe() 15 | self.close_event = multiproc.Event() 16 | self.close_event.clear() 17 | self.child = multiproc.Process(target=self.child_task) 18 | self.child.start() 19 | t = threading.Thread(target=self.watch_thread) 20 | t.daemon = True 21 | t.start() 22 | 23 | def child_task(self): 24 | '''child process - this holds all the GUI elements''' 25 | from MAVProxy.modules.lib import mp_util 26 | from MAVProxy.modules.lib import wx_processguard 27 | from MAVProxy.modules.lib.wx_loader import wx 28 | from MAVProxy.modules.lib.wxsettings_ui import SettingsDlg 29 | 30 | mp_util.child_close_fds() 31 | app = wx.App(False) 32 | dlg = SettingsDlg(self.settings) 33 | dlg.parent_pipe = self.parent_pipe 34 | dlg.ShowModal() 35 | dlg.Destroy() 36 | 37 | def watch_thread(self): 38 | '''watch for settings changes from child''' 39 | from MAVProxy.modules.lib.mp_settings import MPSetting 40 | while True: 41 | setting = self.child_pipe.recv() 42 | if not isinstance(setting, MPSetting): 43 | break 44 | try: 45 | self.settings.set(setting.name, setting.value) 46 | except Exception: 47 | print("Unable to set %s to %s" % (setting.name, setting.value)) 48 | 49 | def is_alive(self): 50 | '''check if child is still going''' 51 | return self.child.is_alive() 52 | 53 | 54 | if __name__ == "__main__": 55 | multiproc.freeze_support() 56 | 57 | def test_callback(setting): 58 | '''callback on apply''' 59 | print("Changing %s to %s" % (setting.name, setting.value)) 60 | 61 | # test the settings 62 | from MAVProxy.modules.lib import mp_settings, time 63 | from MAVProxy.modules.lib.mp_settings import MPSetting 64 | settings = mp_settings.MPSettings( 65 | [ MPSetting('link', int, 1, tab='TabOne'), 66 | MPSetting('altreadout', int, 10, range=(-30,1017), increment=1), 67 | MPSetting('pvalue', float, 0.3, range=(-3.0,1e6), increment=0.1, digits=2), 68 | MPSetting('enable', bool, True, tab='TabTwo'), 69 | MPSetting('colour', str, 'Blue', choice=['Red', 'Green', 'Blue']), 70 | MPSetting('foostr', str, 'blah', label='Foo String') ]) 71 | settings.set_callback(test_callback) 72 | dlg = WXSettings(settings) 73 | while dlg.is_alive(): 74 | time.sleep(0.1) 75 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_DGPS.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | support for a GCS attached DGPS system 4 | ''' 5 | 6 | import socket, errno 7 | from pymavlink import mavutil 8 | from MAVProxy.modules.lib import mp_module 9 | 10 | class DGPSModule(mp_module.MPModule): 11 | def __init__(self, mpstate): 12 | super(DGPSModule, self).__init__(mpstate, "DGPS", "DGPS injection support for SBP/RTCP/UBC") 13 | self.portnum = 13320 14 | self.port = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 15 | self.port.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 16 | self.port.bind(("127.0.0.1", self.portnum)) 17 | mavutil.set_close_on_exec(self.port.fileno()) 18 | self.port.setblocking(0) 19 | self.inject_seq_nr = 0 20 | print("DGPS: Listening for RTCM packets on UDP://%s:%s" % ("127.0.0.1", self.portnum)) 21 | 22 | def send_rtcm_msg(self, data): 23 | msglen = 180; 24 | 25 | if (len(data) > msglen * 4): 26 | print("DGPS: Message too large", len(data)) 27 | return 28 | 29 | # How many messages will we send? 30 | msgs = 0 31 | if (len(data) % msglen == 0): 32 | msgs = len(data) // msglen 33 | else: 34 | msgs = (len(data) // msglen) + 1 35 | 36 | for a in range(0, msgs): 37 | 38 | flags = 0 39 | 40 | # Set the fragment flag if we're sending more than 1 packet. 41 | if (msgs) > 1: 42 | flags = 1 43 | 44 | # Set the ID of this fragment 45 | flags |= (a & 0x3) << 1 46 | 47 | # Set an overall sequence number 48 | flags |= (self.inject_seq_nr & 0x1f) << 3 49 | 50 | 51 | amount = min(len(data) - a * msglen, msglen) 52 | datachunk = data[a*msglen : a*msglen + amount] 53 | 54 | self.master.mav.gps_rtcm_data_send( 55 | flags, 56 | len(datachunk), 57 | bytearray(datachunk.ljust(180, b'\0'))) 58 | 59 | # Send a terminal 0-length message if we sent 2 or 3 exactly-full messages. 60 | if (msgs < 4) and (len(data) % msglen == 0) and (len(data) > msglen): 61 | flags = 1 | (msgs & 0x3) << 1 | (self.inject_seq_nr & 0x1f) << 3 62 | self.master.mav.gps_rtcm_data_send( 63 | flags, 64 | 0, 65 | bytearray("".ljust(180, '\0'))) 66 | 67 | self.inject_seq_nr += 1 68 | 69 | 70 | 71 | def idle_task(self): 72 | '''called in idle time''' 73 | try: 74 | data = self.port.recv(1024) # Attempt to read up to 1024 bytes. 75 | except socket.error as e: 76 | if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK ]: 77 | return 78 | raise 79 | try: 80 | self.send_rtcm_msg(data) 81 | 82 | except Exception as e: 83 | print("DGPS: GPS Inject Failed:", e) 84 | 85 | def init(mpstate): 86 | '''initialise module''' 87 | return DGPSModule(mpstate) 88 | 89 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_SIYI/tools/temp_dir.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # save images in therm cap 4 | 5 | import sys 6 | import numpy as np 7 | import cv2 8 | import time 9 | import glob 10 | import os 11 | from MAVProxy.modules.lib.mp_image import MPImage 12 | from pymavlink import mavutil 13 | 14 | from argparse import ArgumentParser 15 | parser = ArgumentParser(description=__doc__) 16 | 17 | parser.add_argument("--min-temp", default=None, type=float, help="min temperature") 18 | parser.add_argument("--siyi-log", default=None, type=float, help="SIYI binlog") 19 | parser.add_argument("dirname", default=None, type=str, help="directory") 20 | args = parser.parse_args() 21 | 22 | DNAME=args.dirname 23 | mouse_temp=-1 24 | tmin = -1 25 | tmax = -1 26 | last_data = None 27 | C_TO_KELVIN = 273.15 28 | 29 | def update_title(): 30 | global tmin, tmax, mouse_temp 31 | cv2.setWindowTitle('Thermal', "Thermal: (%.1fC to %.1fC) %.1fC" % (tmin, tmax, mouse_temp)) 32 | 33 | def click_callback(event, x, y, flags, param): 34 | global last_data, mouse_temp 35 | if last_data is None: 36 | return 37 | p = last_data[y*640+x] 38 | mouse_temp = p - C_TO_KELVIN 39 | update_title() 40 | 41 | def display_file(fname): 42 | global mouse_temp, tmin, tmax, last_data 43 | print('Importing: ', fname) 44 | a = np.fromfile(fname, dtype='>u2') 45 | if len(a) != 640 * 512: 46 | print("Bad size %u" % len(a)) 47 | return 48 | # get in Kelvin 49 | a = (a / 64.0) 50 | 51 | C_TO_KELVIN = 273.15 52 | 53 | maxv = a.max() 54 | minv = a.min() 55 | 56 | tmin = minv - C_TO_KELVIN 57 | tmax = maxv - C_TO_KELVIN 58 | 59 | if args.min_temp is not None and tmax < args.min_temp: 60 | return 61 | 62 | print("Max=%.3fC Min=%.3fC" % (tmax, tmin)) 63 | if maxv <= minv: 64 | print("Bad range") 65 | return 66 | 67 | last_data = a 68 | 69 | # convert to 0 to 255 70 | a = (a - minv) * 65535.0 / (maxv - minv) 71 | 72 | # convert to uint8 greyscale as 640x512 image 73 | a = a.astype(np.uint16) 74 | a = a.reshape(512, 640) 75 | 76 | cv2.imshow('Thermal', a) 77 | cv2.setMouseCallback('Thermal', click_callback) 78 | cv2.setWindowTitle('Thermal', "Thermal: (%.1fC to %.1fC) %.1fC" % (tmin, tmax, mouse_temp)) 79 | 80 | cv2.waitKey(0) 81 | 82 | flist = sorted(glob.glob(DNAME + "/*bin")) 83 | 84 | for f in flist: 85 | display_file(f) 86 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_SIYI/tools/temp_view.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import numpy as np 5 | import cv2 6 | import time 7 | from MAVProxy.modules.lib.mp_image import MPImage 8 | 9 | FNAME=sys.argv[1] 10 | 11 | # little-endian 16 bit data 12 | # Celsius temp = Raw data/64-273.15. 13 | 14 | print('Importing: ', FNAME) 15 | a = np.fromfile(FNAME, dtype='>u2') 16 | # get in Kelvin 17 | a = (a / 64.0) 18 | 19 | C_TO_KELVIN = 273.15 20 | 21 | #a = np.clip(a, C_TO_KELVIN+50, C_TO_KELVIN+200) 22 | 23 | maxv = a.max() 24 | minv = a.min() 25 | print("Max=%.3fC Min=%.3fC" % (maxv-273.15, minv-273.15)) 26 | if maxv <= minv: 27 | print("Bad range") 28 | sys.exit(1) 29 | 30 | # convert to 0 to 255 31 | a = (a - minv) * 65535.0 / (maxv - minv) 32 | 33 | # convert to uint8 greyscale as 640x512 image 34 | a = a.astype(np.uint16) 35 | a = a.reshape(512, 640) 36 | 37 | #im.set_image(a) 38 | cv2.imshow('Grey16', a) 39 | while True: 40 | cv2.waitKey(1) 41 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_antenna.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | antenna pointing module 4 | Andrew Tridgell 5 | June 2012 6 | ''' 7 | 8 | import sys, os, time 9 | from cuav.lib import cuav_util 10 | from MAVProxy.modules.lib import mp_module 11 | 12 | class AntennaModule(mp_module.MPModule): 13 | def __init__(self, mpstate): 14 | super(AntennaModule, self).__init__(mpstate, "antenna", "antenna pointing module") 15 | self.gcs_location = None 16 | self.last_bearing = 0 17 | self.last_announce = 0 18 | self.add_command('antenna', self.cmd_antenna, "antenna link control") 19 | 20 | def cmd_antenna(self, args): 21 | '''set gcs location''' 22 | if len(args) != 2: 23 | if self.gcs_location is None: 24 | print("GCS location not set") 25 | else: 26 | print("GCS location %s" % str(self.gcs_location)) 27 | return 28 | self.gcs_location = (float(args[0]), float(args[1])) 29 | 30 | 31 | 32 | def mavlink_packet(self, m): 33 | '''handle an incoming mavlink packet''' 34 | if self.gcs_location is None and self.module('wp').wploader.count() > 0: 35 | home = self.module('wp').get_home() 36 | self.gcs_location = (home.x, home.y) 37 | print("Antenna home set") 38 | if self.gcs_location is None: 39 | return 40 | if m.get_type() == 'GPS_RAW' and self.gcs_location is not None: 41 | (gcs_lat, gcs_lon) = self.gcs_location 42 | bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat, m.lon) 43 | elif m.get_type() == 'GPS_RAW_INT' and self.gcs_location is not None: 44 | (gcs_lat, gcs_lon) = self.gcs_location 45 | bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat / 1.0e7, m.lon / 1.0e7) 46 | else: 47 | return 48 | self.console.set_status('Antenna', 'Antenna %.0f' % bearing, row=0) 49 | if abs(bearing - self.last_bearing) > 5 and (time.time() - self.last_announce) > 15: 50 | self.last_bearing = bearing 51 | self.last_announce = time.time() 52 | self.say("Antenna %u" % int(bearing + 0.5)) 53 | 54 | def init(mpstate): 55 | '''initialise module''' 56 | return AntennaModule(mpstate) 57 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/copter_flightmodes.txt: -------------------------------------------------------------------------------- 1 | This file holds the Copter flight mode name to number mapping 2 | 3 | STABILIZE = 0, // pilot directly controls the airframe angle with roll, pitch and yaw stick inputs. Pilot directly controls throttle 4 | ACRO = 1, // pilot directly controls the body-frame angular rate. pilot directly controls throttle 5 | ALT_HOLD = 2, // pilot directly controls the vehicle roll, pitch and yaw angles. Pilot's throttle control controls climb rate 6 | AUTO = 3, // fully automatic waypoint control using mission commands 7 | GUIDED = 4, // fully automatic fly to coordinate or fly at velocity/direction using mavlink commands. 8 | LOITER = 5, // pilot controls the vehicle's 3D speed and acceleration with roll, pitch and throttle input. Heading is controlled with the yaw stick 9 | RTL = 6, // automatic return to launching point 10 | CIRCLE = 7, // automatic circular flight with automatic throttle 11 | LAND = 9, // automatic landing with horizontal position control 12 | DRIFT = 11, // semi-autonomous position, yaw and throttle control. rarely used. 13 | SPORT = 13, // manual earth-frame angular rate control with manual throttle. very rarely used 14 | FLIP = 14, // automatically flip the vehicle 360 degrees 15 | AUTOTUNE = 15, // automatically tune the vehicle's roll and pitch gains 16 | POSHOLD = 16, // automatic position hold with manual override, with automatic throttle. very similar to Loiter mode 17 | BRAKE = 17, // full-brake using inertial/GPS system, no pilot input 18 | THROW = 18, // throw to launch mode using inertial/GPS system, no pilot input 19 | AVOID_ADSB = 19, // automatic avoidance of manned vehicle. very rarely used 20 | GUIDED_NOGPS = 20, // guided mode but only accepts attitude and altitude commands 21 | SMART_RTL = 21, // SMART_RTL returns vehicle home by retracing its steps 22 | FLOWHOLD = 22, // FLOWHOLD holds position with optical flow without rangefinder. similar to Loiter. very rarely used 23 | FOLLOW = 23, // follow attempts to follow another vehicle or ground station 24 | ZIGZAG = 24, // ZIGZAG mode is able to fly in a zigzag manner with predefined point A and point B. Normally used for crop spraying vehicles. 25 | SYSTEMID = 25, // System ID mode produces automated system identification signals in the controllers. very rarely used 26 | AUTOROTATE = 26, // Autonomous autorotation. Used only for traditional helicopters 27 | AUTO_RTL = 27, // return to launch but using an Auto mission starting from the DO_LAND_START command 28 | TURTLE = 28, // Flip vehicle to recover after crash 29 | 30 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/delete_wakeup_timers.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "delete_wakeup_timers", 5 | "description": "Delete all active wakeup timers. You can optionally provide a message parameter to filter which timers will be deleted based on their message. When specifying the message parameter, you can use regular expressions (regex) to match patterns within the timer messages. This is useful when you want to delete timers with specific keywords or patterns in their message. For example, to delete all timers containing the word 'hello', you can use the regex '.*hello.*', where the dot-star (.*) pattern matches any character sequence.", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "message": {"type": "string", "description": "wakeup message of timers to be deleted. regex values are accepted."} 10 | }, 11 | "required": [] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_all_parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_all_parameters", 5 | "description": "Get all available parameter names and values", 6 | "parameters": { 7 | "type": "object", 8 | "properties": {}, 9 | "required": [] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_available_mavlink_messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_available_mavlink_messages", 5 | "description": "Get a list of mavlink message names that can be retrieved using the get_mavlink_message function", 6 | "parameters": { 7 | "type": "object", 8 | "properties": {}, 9 | "required": [] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_current_datetime.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_current_datetime", 5 | "description": "Get the current date and time, e.g. 'Saturday, June 24, 2023 6:14:14 PM'", 6 | "parameters": { 7 | "type": "object", 8 | "properties": {}, 9 | "required": [] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_location_plus_dist_at_bearing.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_location_plus_dist_at_bearing", 5 | "description": "Calculate the latitude and longitude given an existing latitude and longitude and a distance in meters and a bearing in degrees", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "latitude": {"type": "number", "description": "latitude in degrees"}, 10 | "longitude": {"type": "number", "description": "longitude in degrees"}, 11 | "distance": {"type": "number", "description": "distance to move meters"}, 12 | "bearing": {"type": "number", "description": "bearing in degrees. 0 is North, 90 is East, etc"} 13 | }, 14 | "required": ["latitude", "longitude", "distance", "bearing"] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_location_plus_offset.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_location_plus_offset", 5 | "description": "Calculate the latitude and longitude given an existing latitude and longitude and distances (in meters) North and East", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "latitude": {"type": "number", "description": "latitude in degrees"}, 10 | "longitude": {"type": "number", "description": "longitude in degrees"}, 11 | "distance_north": {"type": "number", "description": "distance to move North in meters"}, 12 | "distance_east": {"type": "number", "description": "distance to move East in meters"} 13 | }, 14 | "required": ["latitude", "longitude", "distance_north", "distance_east"] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_mavlink_message.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_mavlink_message", 5 | "description": "Get a mavlink message including all fields and values sent by the vehicle. The list of available messages can be retrieved using the get_available_mavlink_messages", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "message": {"type": "string", "description": "mavlink message name (e.g. HEARTBEAT, VFR_HUD, GLOBAL_POSITION_INT, etc)"} 10 | }, 11 | "required": ["message"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_mode_mapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_mode_mapping", 5 | "description": "Get a list of mode names to mode numbers available for this vehicle. If the name or number parameter is provided only that mode's name and number will be returned. If neither name nor number is provided the full list of available modes will be returned", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "name": {"type": "string", "description": "flight mode name (e.g. Guided, Loiter, RTL)"}, 10 | "number": {"type": "number", "description": "flight mode number"} 11 | }, 12 | "required": [] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_parameter.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_parameter", 5 | "description": "Get a vehicle parameter's value. The full list of available parameters and their values is available using the get_all_parameters function", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "name": {"type": "string", "description": "parameter name (e.g. ARMING_CHECK, LOG_BITMASK). Regex expressions are supported"}, 10 | "value": {"type": "number", "description": "parameter value"} 11 | }, 12 | "required": ["name"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_parameter_description.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_parameter_description", 5 | "description": "Get vehicle parameter descriptions including description, units, min and max", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "name": {"type": "string", "description": "parameter name (e.g. ARMING_CHECK, LOG_BITMASK). Regex expressions are supported. set to * to get all parameter descriptions"} 10 | }, 11 | "required": ["name"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_vehicle_location_and_yaw.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_vehicle_location_and_yaw", 5 | "description": "Get the vehicle's current location including latitude, longitude, altitude above sea level and altitude above home", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "latitude": {"type": "number", "description": "latitude in degrees"}, 10 | "longitude": {"type": "number", "description": "longitude in degrees"}, 11 | "altitude_amsl": {"type": "number", "description": "altitude above sea level in meters (aka AMSL)"}, 12 | "altitude_above_home": {"type": "number", "description": "altitude above home in meters"}, 13 | "yaw": {"type": "number", "description": "vehicle yaw (aka heading) in degrees"} 14 | }, 15 | "required": [] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_vehicle_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_vehicle_state", 5 | "description": "Get the vehicle state including armed status and (flight) mode", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "armed": {"type": "boolean", "description": "vehicle armed status. True means motors can spin and vehicle can move."}, 10 | "mode": {"type": "number", "description": "flight flight mode. The number is specific to the vehicle type (e.g. Copter, Plane, Rover"} 11 | }, 12 | "required": [] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_vehicle_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_vehicle_type", 5 | "description": "Get the vehicle type (e.g. Copter, Plane, Rover, Boat, etc)", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "vehicle_type": {"type": "string", "description": "the vehicle type. Unknown if not known"} 10 | }, 11 | "required": [] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/get_wakeup_timers.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "get_wakeup_timers", 5 | "description": "Retrieves a list of all active wakeup timers. You can optionally provide a message parameter to filter timers by their associated messages. When specifying the message parameter, you can use regular expressions (regex) to match patterns within the timer messages. This is useful when you want to find timers with specific keywords or patterns in their messages. For example, to retrieve all timers containing the word 'hello', you can use the regex '.*hello.*', where the dot-star (.*) pattern matches any character sequence.", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "message": {"type": "string", "description": "wakeup message of timers to be retrieved. regex values are accepted."} 10 | }, 11 | "required": [] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/plane_flightmodes.txt: -------------------------------------------------------------------------------- 1 | This file holds the Plane flight mode name to number mapping. Modes starting with Q are only for use with QuadPlanes. 2 | 3 | MANUAL = 0, // pilot has direct control over servos without stabilization 4 | CIRCLE = 1, // Circle around a GPS waypoint 5 | STABILIZE = 2, // Level flight stabilization 6 | TRAINING = 3, // Limits the roll and pitch angles to keep the aircraft stable 7 | ACRO = 4, // Full manual aerobatic control with some stabilization 8 | FLY_BY_WIRE_A = 5, // Stabilized flight with manual throttle 9 | FLY_BY_WIRE_B = 6, // More stabilization than FLY_BY_WIRE_A 10 | CRUISE = 7, // Mixed manual and automatic throttle control 11 | AUTOTUNE = 8, // Automatically tune the PID controller for optimal performance 12 | AUTO = 10, // Fully autonomous flight, following a pre-programmed mission 13 | RTL = 11, // Return to Launch point 14 | LOITER = 12, // Circle around a point while maintaining altitude 15 | TAKEOFF = 13, // Automated takeoff sequence 16 | AVOID_ADSB = 14, // Avoidance maneuver triggered by ADS-B aircraft detection 17 | GUIDED = 15, // Remotely guided commands from GCS or companion computer 18 | INITIALISING = 16, // Initialization mode at startup 19 | QSTABILIZE = 17, // QuadPlane's stabilize mode. Similar to Copter's stabilize mode 20 | QHOVER = 18, // QuadPlane's hover mode. Similar to Copter's AltHold mode 21 | QLOITER = 19, // QuadPlane's loiter mode. Similar to Copter's Loiter mode 22 | QLAND = 20, // QuadPlane's land mode. Similar to Copter's Land mode 23 | QRTL = 21, // QuadPlane's Return to Launch mode. Similar to Copter's RTL mode 24 | QAUTOTUNE = 22, // QuadPlane's autotune mode. Similar to Copter's AutoTune mode 25 | QACRO = 23, // QuadPlane's acrobatic mode. Similar to Copter's Acro mode 26 | THERMAL = 24, // Thermal detection and exploitation mode 27 | LOITER_ALT_QLAND = 25, // QuadPlane's loiter to alt then land mode 28 | 29 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/rover_modes.txt: -------------------------------------------------------------------------------- 1 | This file holds the Rover (aka car) and boat mode name to number mapping. Rover "modes" are the same as "flight modes" for other vehicles. "Rover" is synonymous with "car" 2 | 3 | MANUAL = 0, // Pilot directly controls the vehicle's steering and throttle 4 | ACRO = 1, // Pilot controls the turn rate and speed 5 | STEERING = 3, // Pilot controls the steering using lateral acceleration. throttle stick controls speed 6 | HOLD = 4, // motor and steering outputs are disabled. Rovers will stop, boats will drift in this mode 7 | LOITER = 5, // hold position at the current location 8 | FOLLOW = 6, // follow a GPS-enabled device 9 | SIMPLE = 7, // Pilot controls the vehicles by moving the combined steering and throttle stick in the direction they wish to move. The direction of movement is relative to the vehicle's heading when first powered on 10 | DOCK = 8, // Automatic docking mode 11 | CIRCLE = 9, // Circle around a location recorded when the vehicle entered this mode 12 | AUTO = 10, // Fully autonomous mode following pre-programmed waypoints 13 | RTL = 11, // Return to Launch point 14 | SMART_RTL = 12, // Creates a path back to the launch point based on the rover's traveled path 15 | GUIDED = 15, // Guided control via a ground station or companion computer 16 | INITIALISING = 16, // Initialization mode at startup 17 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/send_mavlink_command_int.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "send_mavlink_command_int", 5 | "description": "Send a mavlink COMMAND_INT message to the vehicle. Available commands including changing the flight mode, arming, disarming, takeoff and commanding the vehicle to fly to a specific location", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "target_system": {"type": "integer", "minimum":0, "maximum":255, "description": "vehicle autopilot System ID. can be omitted"}, 10 | "target_component": {"type": "integer", "minimum":0, "maximum":255, "description": "vehicle autopilot Component ID. can be omitted"}, 11 | "frame": {"type": "integer", "minimum":0, "maximum":21, "description": "altitude type. see MAV_FRAME. 0 for altitude above sea level, 3 for altitude above home, 10 for altitude above terrain"}, 12 | "command": {"type": "integer", "minimum":0, "maximum":65535, "description": "MAVLink command id. See MAV_CMD for a full list of available commands"}, 13 | "current": {"type": "integer", "description": "not used. always zero"}, 14 | "autocontinue": {"type": "integer", "description": "not used. always zero"}, 15 | "param1": {"type": "number", "description": "parameter 1. see MAV_CMD enum"}, 16 | "param2": {"type": "number", "description": "parameter 2. see MAV_CMD enum"}, 17 | "param3": {"type": "number", "description": "parameter 3. see MAV_CMD enum"}, 18 | "param4": {"type": "number", "description": "parameter 4. see MAV_CMD enum"}, 19 | "x": {"type": "integer", "description": "latitude in degrees * 10^7"}, 20 | "y": {"type": "integer", "description": "longitude in degrees * 10^7"}, 21 | "z": {"type": "number", "description": "altitude in meters (relative to sea level, home or terrain depending on frame field)."} 22 | }, 23 | "required": ["frame", "command"] 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/send_mavlink_set_position_target_global_int.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "send_mavlink_set_position_target_global_int", 5 | "description": "Send a mavlink SET_POSITION_TARGET_GLOBAL_INT message to the vehicle. This message is the preferred way to command a vehicle to fly to a specified location or to fly at a specfied velocity", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "time_boot_ms": {"type": "integer", "description": "system timestamp. can be left as 0"}, 10 | "target_system": {"type": "integer", "minimum":0, "maximum":255, "description": "vehicle autopilot System ID. can be omitted"}, 11 | "target_component": {"type": "integer", "minimum":0, "maximum":255, "description": "vehicle autopilot Component ID. can be omitted"}, 12 | "coordinate_frame": {"type": "integer", "minimum":0, "maximum":21, "description": "altitude type. see MAV_FRAME. 5 for altitude above sea level, 6 for altitude above home, 11 for altitude above terrain"}, 13 | "type_mask": {"type": "integer", "minimum":0, "maximum":65535, "description": "Bitmap to indicate which dimensions should be ignored by the vehicle. see POSITION_TARGET_TYPEMASK. If only location (e.g. lat_int, lon_int and alt) is sent use 3576. If location and yaw are sent use 2552. If only velocity (e.g. vx, vy, vz) is sent use 2552. if velocity and yaw are sent use 2503. If only yaw is sent use 2559"}, 14 | "latitude": {"type": "number", "description": "latitude in degrees"}, 15 | "longitude": {"type": "number", "description": "longitude in degrees"}, 16 | "alt": {"type": "number", "description": "altitude in meters (relative to sea level, home or terrain depending on frame field)"}, 17 | "vx": {"type": "number", "description": "velocity North in m/s"}, 18 | "vy": {"type": "number", "description": "velocity East in m/s"}, 19 | "vz": {"type": "number", "description": "velocity Down in m/s"}, 20 | "afx": {"type": "number", "description": "acceleration North in m/s/s. rarely used, normally 0"}, 21 | "afy": {"type": "number", "description": "acceleration East in m/s/s. rarely used, normally 0"}, 22 | "afz": {"type": "number", "description": "acceleration Down in m/s/s. rarely used, normally 0"}, 23 | "yaw": {"type": "number", "minimum":-6.28318530717959, "maximum":6.28318530717959, "description": "yaw (aka heading) in radians"}, 24 | "yaw_rate": {"type": "number", "description": "yaw (aka heading) rotation rate in radians/second. rarely used, normally 0"} 25 | }, 26 | "required": ["coordinate_frame", "type_mask"] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/set_parameter.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "set_parameter", 5 | "description": "Set a vehicle parameter's value. The full list of parameters is available using the get_all_parameters function", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "name": {"type": "string", "description": "parameter name (e.g. ARMING_CHECK, LOG_BITMASK)"}, 10 | "value": {"type": "number", "description": "parameter value"} 11 | }, 12 | "required": ["name", "value"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/set_wakeup_timer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "function", 3 | "function": { 4 | "name": "set_wakeup_timer", 5 | "description": "Set a timer to wake you up in a specified number of seconds in the future. This allows taking actions in the future. The wakeup message will appear with the user role but will look something like WAKEUP:. Multiple wakeup messages are supported", 6 | "parameters": { 7 | "type": "object", 8 | "properties": { 9 | "seconds": {"type": "number", "description": "number of seconds in the future that the timer will wake you up"}, 10 | "message": {"type": "string", "description": "wakeup message that will be sent to you"} 11 | }, 12 | "required": ["seconds", "message"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/assistant_setup/sub_modes.txt: -------------------------------------------------------------------------------- 1 | This file holds the Sub (aka submarine) mode name to number mapping. 2 | 3 | STABILIZE = 0, // manual angle with manual depth/throttle 4 | ACRO = 1, // manual body-frame angular rate with manual depth/throttle 5 | ALT_HOLD = 2, // manual angle with automatic depth/throttle 6 | AUTO = 3, // fully automatic waypoint control using mission commands 7 | GUIDED = 4, // fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands 8 | CIRCLE = 7, // automatic circular flight with automatic throttle 9 | SURFACE = 9, // automatically return to surface, pilot maintains horizontal control 10 | POSHOLD = 16, // automatic position hold with manual override, with automatic throttle 11 | MANUAL = 19, // Pass-through input with no stabilization 12 | MOTOR_DETECT = 20 // Automatically detect motors orientation 13 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_chat/chat_voice_to_text.py: -------------------------------------------------------------------------------- 1 | ''' 2 | AI Chat Module voice-to-text class 3 | Randy Mackay, December 2023 4 | 5 | AP_FLAKE8_CLEAN 6 | ''' 7 | 8 | 9 | try: 10 | import pyaudio # install using, "sudo apt-get install python3-pyaudio" 11 | import wave # install with "pip3 install wave" 12 | from openai import OpenAI 13 | except Exception: 14 | print("chat: failed to import pyaudio, wave or openai. See https://ardupilot.org/mavproxy/docs/modules/chat.html") 15 | exit() 16 | 17 | # initializing the global list to keep and update the stop_recording state 18 | stop_recording = [False] 19 | 20 | 21 | class chat_voice_to_text(): 22 | def __init__(self): 23 | # initialise variables 24 | self.client = None 25 | self.assistant = None 26 | 27 | # set the OpenAI API key 28 | def set_api_key(self, api_key_str): 29 | self.client = OpenAI(api_key=api_key_str) 30 | 31 | # check connection to OpenAI assistant and connect if necessary 32 | # returns True if connection is good, False if not 33 | def check_connection(self): 34 | # create connection object 35 | if self.client is None: 36 | try: 37 | self.client = OpenAI() 38 | except Exception: 39 | print("chat: failed to connect to OpenAI") 40 | return False 41 | 42 | # return True if connected 43 | return self.client is not None 44 | 45 | # record audio from microphone 46 | # returns filename of recording or None if failed 47 | def record_audio(self): 48 | # Initialize PyAudio 49 | p = pyaudio.PyAudio() 50 | 51 | # Open stream 52 | try: 53 | stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=1024) 54 | except Exception: 55 | print("chat: failed to connect to microphone") 56 | return None 57 | 58 | # record until specified time 59 | frames = [] 60 | while not stop_recording[0]: 61 | data = stream.read(1024) 62 | frames.append(data) 63 | 64 | # Stop and close the stream 65 | stream.stop_stream() 66 | stream.close() 67 | p.terminate() 68 | 69 | # update the recording state back to false globally 70 | stop_recording[0] = False 71 | 72 | # Save audio file 73 | wf = wave.open("recording.wav", "wb") 74 | wf.setnchannels(1) 75 | wf.setsampwidth(pyaudio.PyAudio().get_sample_size(pyaudio.paInt16)) 76 | wf.setframerate(44100) 77 | wf.writeframes(b''.join(frames)) 78 | wf.close() 79 | return "recording.wav" 80 | 81 | # convert audio to text 82 | # returns transcribed text on success or None if failed 83 | def convert_audio_to_text(self, audio_filename): 84 | # check connection 85 | if not self.check_connection(): 86 | return None 87 | 88 | # Process with Whisper 89 | audio_file = open(audio_filename, "rb") 90 | transcript = self.client.audio.transcriptions.create( 91 | model="whisper-1", 92 | file=audio_file, 93 | response_format="text") 94 | return transcript 95 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_emuecu.py: -------------------------------------------------------------------------------- 1 | """ 2 | control EMU ECU system 3 | """ 4 | 5 | import time 6 | 7 | from MAVProxy.modules.lib import mp_module 8 | from MAVProxy.modules.lib import mp_settings 9 | 10 | class EMUECUModule(mp_module.MPModule): 11 | 12 | def __init__(self, mpstate): 13 | super(EMUECUModule, self).__init__(mpstate, "emuecu", "emuecu", public=False) 14 | self.emuecu_settings = mp_settings.MPSettings( 15 | [('port', int, 102)]) 16 | self.add_command('emu', self.cmd_emu, 'EMUECU control', 17 | ["", 18 | "set (EMUECUSETTING)"]) 19 | self.add_completion_function('(EMUECUSETTING)', 20 | self.emuecu_settings.completion) 21 | 22 | def mavlink_packet(self, msg): 23 | '''handle an incoming mavlink packet''' 24 | if msg.get_type() == 'SERIAL_CONTROL': 25 | print(msg) 26 | 27 | def cmd_emu(self, args): 28 | '''emu command handling''' 29 | if len(args) <= 0: 30 | print("Usage: emu ") 31 | return 32 | if args[0] == "send": 33 | self.cmd_send(args[1:]) 34 | elif args[0] == "set": 35 | self.emuecu_settings.command(args[1:]) 36 | 37 | def cmd_send(self, args): 38 | '''send command''' 39 | cmd = ' '.join(args) + '\n' 40 | buf = [ord(x) for x in cmd] 41 | buf.extend([0]*(70-len(buf))) 42 | mav = self.master.mav 43 | mav.serial_control_send(self.emuecu_settings.port, 44 | 0, 45 | 0, 0, 46 | len(cmd), buf) 47 | 48 | 49 | def init(mpstate): 50 | '''initialise module''' 51 | return EMUECUModule(mpstate) 52 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Example Module 4 | Peter Barker, September 2016 5 | 6 | This module simply serves as a starting point for your own MAVProxy module. 7 | 8 | 1. copy this module sidewise (e.g. "cp mavproxy_example.py mavproxy_coolfeature.py" 9 | 2. replace all instances of "example" with whatever your module should be called 10 | (e.g. "coolfeature") 11 | 12 | 3. trim (or comment) out any functionality you do not need 13 | ''' 14 | 15 | import os 16 | import os.path 17 | import sys 18 | from pymavlink import mavutil 19 | import errno 20 | import time 21 | 22 | from MAVProxy.modules.lib import mp_module 23 | from MAVProxy.modules.lib import mp_util 24 | from MAVProxy.modules.lib import mp_settings 25 | 26 | 27 | class example(mp_module.MPModule): 28 | def __init__(self, mpstate): 29 | """Initialise module""" 30 | super(example, self).__init__(mpstate, "example", "") 31 | self.status_callcount = 0 32 | self.boredom_interval = 10 # seconds 33 | self.last_bored = time.time() 34 | 35 | self.packets_mytarget = 0 36 | self.packets_othertarget = 0 37 | 38 | self.example_settings = mp_settings.MPSettings( 39 | [ ('verbose', bool, False), 40 | ]) 41 | self.add_command('example', self.cmd_example, "example module", ['status','set (LOGSETTING)']) 42 | 43 | def usage(self): 44 | '''show help on command line options''' 45 | return "Usage: example " 46 | 47 | def cmd_example(self, args): 48 | '''control behaviour of the module''' 49 | if len(args) == 0: 50 | print(self.usage()) 51 | elif args[0] == "status": 52 | print(self.status()) 53 | elif args[0] == "set": 54 | self.example_settings.command(args[1:]) 55 | else: 56 | print(self.usage()) 57 | 58 | def status(self): 59 | '''returns information about module''' 60 | self.status_callcount += 1 61 | self.last_bored = time.time() # status entertains us 62 | return("status called %(status_callcount)d times. My target positions=%(packets_mytarget)u Other target positions=%(packets_mytarget)u" % 63 | {"status_callcount": self.status_callcount, 64 | "packets_mytarget": self.packets_mytarget, 65 | "packets_othertarget": self.packets_othertarget, 66 | }) 67 | 68 | def boredom_message(self): 69 | if self.example_settings.verbose: 70 | return ("I'm very bored") 71 | return ("I'm bored") 72 | 73 | def idle_task(self): 74 | '''called rapidly by mavproxy''' 75 | now = time.time() 76 | if now-self.last_bored > self.boredom_interval: 77 | self.last_bored = now 78 | message = self.boredom_message() 79 | self.say("%s: %s" % (self.name,message)) 80 | # See if whatever we're connected to would like to play: 81 | self.master.mav.statustext_send(mavutil.mavlink.MAV_SEVERITY_NOTICE, 82 | message) 83 | 84 | def mavlink_packet(self, m): 85 | '''handle mavlink packets''' 86 | if m.get_type() == 'GLOBAL_POSITION_INT': 87 | if self.settings.target_system == 0 or self.settings.target_system == m.get_srcSystem(): 88 | self.packets_mytarget += 1 89 | else: 90 | self.packets_othertarget += 1 91 | 92 | def init(mpstate): 93 | '''initialise module''' 94 | return example(mpstate) 95 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/cmac-foamy-fence.txt: -------------------------------------------------------------------------------- 1 | -35.363720 149.163651 2 | -35.358795 149.164734 3 | -35.359211 149.160767 4 | -35.368622 149.162750 5 | -35.368279 149.166870 6 | -35.358795 149.164734 7 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/cmac-foamy-mission-ccw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.363262 149.165237 583.429993 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.361279 149.164230 30.000000 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.361229 149.163025 60.000000 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.364563 149.163773 60.000000 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.364384 149.164795 60.000000 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.361027 149.164093 60.000000 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.362915 149.162613 60.000000 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.363136 149.162750 60.000000 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.365467 149.164215 55.000000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.365620 149.165543 30.000000 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.363029 149.165192 -0.030000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/cmac-foamy-mission-cw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.363262 149.165237 584.039978 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.364239 149.164474 30.000000 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.364563 149.163773 60.000000 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.361229 149.163025 60.000000 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.361027 149.164093 60.000000 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.364384 149.164795 60.000000 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.362915 149.162613 60.000000 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.363136 149.162750 60.000000 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.360531 149.163452 55.000000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.361004 149.164841 30.000000 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.362377 149.165115 -0.030000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/cmac-foamy-rally.txt: -------------------------------------------------------------------------------- 1 | RALLY -35.363160 149.164101 60.000000 40.000000 0.000000 0 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalley-foamy-fence.txt: -------------------------------------------------------------------------------- 1 | -35.281086 149.007370 2 | -35.282536 149.005096 3 | -35.278564 149.005066 4 | -35.279636 149.009476 5 | -35.281803 149.010056 6 | -35.282536 149.005096 7 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalley-foamy-mission-ccw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.281315 149.005325 582.039978 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.281807 149.006989 24.879999 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281597 149.008514 43.990002 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280743 149.008179 37.040001 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281124 149.005753 54.560001 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281960 149.005981 55.720001 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.280418 149.007812 45.240002 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280895 149.008682 43.169998 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281326 149.008255 37.180000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281761 149.007767 17.639999 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.281963 149.006546 -3.030000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalley-foamy-mission-cw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.280651 149.005356 585.669983 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.280037 149.005600 15.000000 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.279388 149.005722 60.000000 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.279301 149.006836 60.000000 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281384 149.006958 60.000000 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281494 149.005844 60.000000 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.279713 149.007004 35.000000 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280079 149.007065 20.000000 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281940 149.007339 15.000000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.282162 149.005844 12.000000 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.280937 149.005768 0.000000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalley-foamy-rally.txt: -------------------------------------------------------------------------------- 1 | RALLY -35.281194 149.006725 100.000000 40.000000 0.000000 0 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalleybottom-foamy-fence.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 5000 0.000000 0.000000 0.000000 0.000000 -35.281086 149.007370 0.000000 0 3 | 1 0 0 5001 4.000000 0.000000 0.000000 0.000000 -35.282628 149.004323 0.000000 0 4 | 2 0 0 5001 4.000000 0.000000 0.000000 0.000000 -35.278564 149.005066 0.000000 0 5 | 3 0 0 5001 4.000000 0.000000 0.000000 0.000000 -35.279636 149.009476 0.000000 0 6 | 4 0 0 5001 4.000000 0.000000 0.000000 0.000000 -35.281803 149.010056 0.000000 0 7 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalleybottom-foamy-mission-ccw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.281315 149.005325 582.039978 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.281807 149.006989 24.879999 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281597 149.008514 43.990002 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280743 149.008179 37.040001 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281124 149.005753 54.560001 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281960 149.005981 55.720001 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.280418 149.007812 45.240002 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280895 149.008682 43.169998 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281326 149.008255 37.180000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281761 149.007767 17.639999 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.281963 149.006546 -3.030000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalleybottom-foamy-mission-cw.txt: -------------------------------------------------------------------------------- 1 | QGC WPL 110 2 | 0 0 0 16 0.000000 0.000000 0.000000 0.000000 -35.282402 149.005365 585.989990 1 3 | 1 0 3 22 10.000000 0.000000 0.000000 0.000000 -35.280037 149.005600 15.000000 1 4 | 2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.279388 149.005722 60.000000 1 5 | 3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.279301 149.006836 60.000000 1 6 | 4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281384 149.006958 60.000000 1 7 | 5 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281494 149.005844 60.000000 1 8 | 6 0 0 177 2.000000 -1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1 9 | 7 0 3 189 0.000000 0.000000 0.000000 0.000000 -35.279713 149.007004 35.000000 1 10 | 8 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.280079 149.007065 40.000000 1 11 | 9 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281671 149.007520 25.000000 1 12 | 10 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.281851 149.007122 15.000000 1 13 | 11 0 3 21 0.000000 0.000000 0.000000 1.000000 -35.282289 149.005488 0.000000 1 14 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_fieldcheck/springvalleybottom-foamy-rally.txt: -------------------------------------------------------------------------------- 1 | RALLY -35.281194 149.006725 100.000000 40.000000 0.000000 0 2 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_gopro.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | '''gopro control over mavlink for the solo-gimbal 3 | 4 | To use this module connect to a Solo with a GoPro installed on the gimbal. 5 | ''' 6 | 7 | import time, os 8 | 9 | from MAVProxy.modules.lib import mp_module 10 | from pymavlink import mavutil 11 | 12 | class GoProModule(mp_module.MPModule): 13 | 14 | def __init__(self, mpstate): 15 | super(GoProModule, self).__init__(mpstate, "gopro", "gopro handling") 16 | 17 | self.add_command('gopro', self.cmd_gopro, 'gopro control', [ 18 | 'status', 19 | 'shutter ', 20 | 'mode ', 21 | 'power ']) 22 | 23 | def cmd_gopro(self, args): 24 | '''gopro commands''' 25 | usage = "status, shutter , mode , power " 26 | mav = self.master.mav 27 | 28 | if args[0] == "status": 29 | self.cmd_gopro_status(args[1:]) 30 | return 31 | 32 | if args[0] == "shutter": 33 | name = args[1].lower() 34 | if name == 'start': 35 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 36 | mavutil.mavlink.GOPRO_COMMAND_SHUTTER, [1, 0 ,0 , 0]) 37 | return 38 | elif name == 'stop': 39 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 40 | mavutil.mavlink.GOPRO_COMMAND_SHUTTER, [0, 0 ,0 , 0]) 41 | return 42 | else: 43 | print("unrecognized") 44 | return 45 | 46 | if args[0] == "mode": 47 | name = args[1].lower() 48 | if name == 'video': 49 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 50 | mavutil.mavlink.GOPRO_COMMAND_CAPTURE_MODE, [0, 0 ,0 , 0]) 51 | return 52 | elif name == 'camera': 53 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 54 | mavutil.mavlink.GOPRO_COMMAND_CAPTURE_MODE, [1, 0 ,0 , 0]) 55 | return 56 | else: 57 | print("unrecognized") 58 | return 59 | 60 | if args[0] == "power": 61 | name = args[1].lower() 62 | if name == 'on': 63 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 64 | mavutil.mavlink.GOPRO_COMMAND_POWER, [1, 0 ,0 , 0]) 65 | return 66 | elif name == 'off': 67 | mav.gopro_set_request_send(self.target_system, mavutil.mavlink.MAV_COMP_ID_GIMBAL, 68 | mavutil.mavlink.GOPRO_COMMAND_POWER, [0, 0 ,0 , 0]) 69 | return 70 | else: 71 | print("unrecognized") 72 | return 73 | 74 | print(usage) 75 | 76 | def cmd_gopro_status(self, args): 77 | '''show gopro status''' 78 | master = self.master 79 | if 'GOPRO_HEARTBEAT' in master.messages: 80 | print(master.messages['GOPRO_HEARTBEAT']) 81 | else: 82 | print("No GOPRO_HEARTBEAT messages") 83 | 84 | def init(mpstate): 85 | '''initialise module''' 86 | return GoProModule(mpstate) 87 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/FeiYing.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | FeiYing Model KMODEL Simulator - G4-G7 and Above Controller 3 | match: 4 | - '*FeiYing*' 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 0 9 | - channel: 2 10 | type: axis 11 | id: 1 12 | - channel: 3 13 | type: axis 14 | id: 2 15 | - channel: 4 16 | type: axis 17 | id: 4 18 | - channel: 5 19 | type: button 20 | id: 0 21 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/Logitech_WingMan_3D.yml: -------------------------------------------------------------------------------- 1 | description: Logitech WingMan Force 3D joystick definition. 2 | match: 3 | - WingMan Force 3D* 4 | controls: 5 | 6 | # map axis id 2 to rc channel 1 7 | - channel: 1 8 | type: axis 9 | id: 0 10 | 11 | # map axis id 3 to rc channel 2 12 | - channel: 2 13 | type: axis 14 | id: 1 15 | 16 | # map axis id 1 to rc channel 3 17 | - channel: 3 18 | type: axis 19 | id: 2 20 | invert: true 21 | 22 | # map axis id 0 to rc channel 4 23 | - channel: 4 24 | type: axis 25 | id: 3 26 | 27 | # This maps the A, B, X, and Y buttons onto channel 5, providing 28 | # a convenient way to select between four different flight modes. 29 | # The PWM values here are for flight modes 1-4. 30 | - channel: 5 31 | type: multibutton 32 | buttons: 33 | - id: 0 34 | value: 1200 35 | - id: 1 36 | value: 1300 37 | - id: 2 38 | value: 1400 39 | - id: 3 40 | value: 1500 41 | 42 | # A hat operates like a toggle switch. When an axis goes positive, 43 | # it sets the `high` value, and when an axis goes negative it sets the 44 | # `low` value. When the hat is centered it does not change the 45 | # current channel value. This configuration maps the hat X axis to 46 | # channel 7 and the Y axis to channel 8; these are useful along with 47 | # the CH7_OPT and CH8_OPT APM parameters. 48 | - channel: 7 49 | type: hat 50 | id: 0 51 | axis: x 52 | - channel: 8 53 | type: hat 54 | id: 0 55 | axis: y 56 | 57 | # Buttons act as momentary switches. When pressed they set the 58 | # corresponding pwm to their `high` value, when released the pwm is 59 | # set to the `low` value. `low` defaults to 1000, `high` defaults 60 | # to 2000. 61 | - channel: 9 62 | type: button 63 | id: 4 64 | - channel: 10 65 | type: button 66 | id: 5 67 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/SparkFun Pro Micro.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | SUMD -> Joystick adapter using SparkFun Pro Micro AtMega 32u4 3 | 4 | match: 5 | - '*SparkFun Pro Micro*' 6 | 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | - channel: 3 15 | type: axis 16 | id: 2 17 | - channel: 4 18 | type: axis 19 | id: 3 20 | - channel: 5 21 | type: axis 22 | id: 4 23 | - channel: 6 24 | type: axis 25 | id: 5 26 | - channel: 7 27 | type: axis 28 | id: 6 29 | - channel: 8 30 | type: axis 31 | id: 7 32 | 33 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/T16S.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | RadioMaster T16 as a joystick via USB cable 3 | 4 | match: 5 | - '*TX16*' 6 | 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | - channel: 3 15 | type: axis 16 | id: 2 17 | - channel: 4 18 | type: axis 19 | id: 3 20 | - channel: 5 21 | type: axis 22 | id: 4 23 | - channel: 6 24 | type: axis 25 | id: 5 26 | - channel: 7 27 | type: axis 28 | id: 6 29 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/carolbox-usb.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | http://www.hobbyking.com/hobbyking/store/__13597__USB_Simulator_Cable_XTR_AeroFly_FMS.html 3 | Has 6 usable axes. This assumes mode 1 4 | match: 5 | - 'CarolBox USB*' 6 | controls: 7 | - channel: 1 8 | type: axis 9 | id: 3 10 | - channel: 2 11 | type: axis 12 | id: 0 13 | - channel: 3 14 | type: axis 15 | id: 1 16 | - channel: 4 17 | type: axis 18 | id: 4 19 | - channel: 5 20 | type: axis 21 | id: 5 22 | - channel: 7 23 | type: axis 24 | id: 2 25 | 26 | # NB: The configuration in mavproxy_joystick.py maps both channels 5 27 | # and 8 to axis 5. One of these is a typo. I'm assuming that it 28 | # should be axis 6 for channel 8. 29 | - channel: 8 30 | type: axis 31 | id: 6 32 | 33 | # From mavproxy_joystick.py: 34 | # 35 | # 'CarolBox USB*': 36 | # [(3, 500, 1500), 37 | # (0, 500, 1500), 38 | # (1, 700, 1500), 39 | # (4, 500, 1500), 40 | # (5, 500, 1500), 41 | # None, 42 | # (2, 500, 1500), 43 | # (5, 500, 1500)], 44 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/cypress-spektrum.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Spektrum DX8 With Cypress USB dsmX HID 3 | OrangeRX DSMX DSM2 USB Dongle 4 | Available here - https://hobbyking.com/en_us/orange-rx-dsmx-dsm2-compatible-protocol-usb-dongle-flight-simulator.html 5 | 6 | match: 7 | - Cypress USB dsmX HID 8 | 9 | controls: 10 | - channel: 1 11 | type: axis 12 | id: 0 # right control over and back 13 | 14 | - channel: 2 15 | type: axis 16 | id: 1 17 | 18 | - channel: 3 19 | type: axis 20 | id: 2 21 | 22 | - channel: 4 23 | type: axis 24 | id: 3 25 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/great-planes.Interlink-X.yaml: -------------------------------------------------------------------------------- 1 | description: > 2 | GREAT PLANES InterLink Elite or Great Planes GP Controller. 4 axes 3 | usable. 4 | match: 5 | - 'GREAT PLANES InterLink-X' 6 | 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 2 11 | invert: true 12 | - channel: 2 13 | type: axis 14 | id: 5 15 | - channel: 3 16 | type: axis 17 | id: 1 18 | - channel: 4 19 | type: axis 20 | id: 0 21 | - channel: 7 22 | type: axis 23 | id: 6 24 | invert: true 25 | 26 | # This maps the A, B, X, and Y buttons onto channel 5, providing 27 | # a convenient way to select between four different flight modes. 28 | # The PWM values here are for flight modes 1-4. 29 | - channel: 5 30 | type: multibutton 31 | buttons: 32 | - id: 3 33 | value: 1200 34 | - id: 4 35 | value: 1800 36 | 37 | 38 | # From mavproxy_joystick.py: 39 | # 40 | # 'GREAT PLANES InterLink Elite': 41 | # # 4 axes usable 42 | # [(0, 500, 1500), 43 | # (1, 500, 1500), 44 | # (2, -1000, 1500), 45 | # (4, 500, 1500), 46 | # None, 47 | # None, 48 | # None, 49 | # (3, 500, 1500)], 50 | # 51 | # 'Great Planes GP Controller': 52 | # # 4 axes usable 53 | # [(0, 500, 1500), 54 | # (1, -500, 1500), 55 | # (2, -1000, 1500), 56 | # (4, -500, 1500), 57 | # None, 58 | # None, 59 | # None, 60 | # (3, 500, 1500)], -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/great-planes.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | GREAT PLANES InterLink Elite or Great Planes GP Controller. 4 axes 3 | usable. 4 | match: 5 | - 'GREAT PLANES InterLink Elite' 6 | - 'Great Planes GP Controller' 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | - channel: 3 15 | type: axis 16 | id: 2 17 | invert: true 18 | - channel: 4 19 | type: axis 20 | id: 4 21 | - channel: 8 22 | type: axis 23 | id: 3 24 | 25 | # From mavproxy_joystick.py: 26 | # 27 | # 'GREAT PLANES InterLink Elite': 28 | # # 4 axes usable 29 | # [(0, 500, 1500), 30 | # (1, 500, 1500), 31 | # (2, -1000, 1500), 32 | # (4, 500, 1500), 33 | # None, 34 | # None, 35 | # None, 36 | # (3, 500, 1500)], 37 | # 38 | # 'Great Planes GP Controller': 39 | # # 4 axes usable 40 | # [(0, 500, 1500), 41 | # (1, -500, 1500), 42 | # (2, -1000, 1500), 43 | # (4, -500, 1500), 44 | # None, 45 | # None, 46 | # None, 47 | # (3, 500, 1500)], 48 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/jumper.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Jumper T16 transmitter as a joystick via USB cable 3 | 4 | match: 5 | - '*Jumper*' 6 | 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | - channel: 3 15 | type: axis 16 | id: 2 17 | - channel: 4 18 | type: axis 19 | id: 3 20 | - channel: 5 21 | type: axis 22 | id: 4 23 | - channel: 6 24 | type: axis 25 | id: 5 26 | - channel: 7 27 | type: axis 28 | id: 6 29 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/logicool-f310.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Support for the Logicool F310 joystick. 3 | match: 4 | - 'Logicool Logicool Dual Action' 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 2 9 | - channel: 2 10 | type: axis 11 | id: 1 12 | - channel: 3 13 | type: axis 14 | id: 3 15 | invert: true 16 | - channel: 4 17 | type: axis 18 | id: 0 19 | 20 | # This maps the A, B, X, and Y buttons onto channel 5, providing 21 | # a convenient way to select between four different flight modes. 22 | # The PWM values here are for flight modes 1-4. 23 | - channel: 5 24 | type: multibutton 25 | buttons: 26 | - id: 0 27 | value: 1200 28 | - id: 1 29 | value: 1300 30 | - id: 2 31 | value: 1400 32 | - id: 3 33 | value: 1500 34 | - id: 5 35 | value: 1700 36 | - id: 4 37 | value: 1800 38 | 39 | # A hat operates like a toggle switch. When an axis goes positive, 40 | # it sets the `high` value, and when an axis goes negative it sets the 41 | # `low` value. When the hat is centered it does not change the 42 | # current channel value. This configuration maps the hat X axis to 43 | # channel 7 and the Y axis to channel 8; these are useful along with 44 | # the CH7_OPT and CH8_OPT APM parameters. 45 | - channel: 7 46 | type: hat 47 | id: 0 48 | axis: x 49 | - channel: 8 50 | type: hat 51 | id: 0 52 | axis: y 53 | 54 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/logitech-dual-action.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Support for the Logitech F310 joystick in "D" mode. 3 | match: 4 | - Logitech Logitech Dual Action 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 2 9 | - channel: 2 10 | type: axis 11 | id: 3 12 | - channel: 3 13 | type: axis 14 | id: 1 15 | invert: true 16 | - channel: 4 17 | type: axis 18 | id: 0 19 | 20 | # This maps the A, B, X, and Y buttons onto channel 5, providing 21 | # a convenient way to select between four different flight modes. 22 | # The PWM values here are for flight modes 1-4. 23 | - channel: 5 24 | type: multibutton 25 | buttons: 26 | - id: 0 27 | value: 1200 28 | - id: 1 29 | value: 1300 30 | - id: 2 31 | value: 1400 32 | - id: 3 33 | value: 1500 34 | 35 | # A hat operates like a toggle switch. When an axis goes positive, 36 | # it sets the `high` value, and when an axis goes negative it sets the 37 | # `low` value. When the hat is centered it does not change the 38 | # current channel value. This configuration maps the hat X axis to 39 | # channel 7 and the Y axis to channel 8; these are useful along with 40 | # the CH7_OPT and CH8_OPT APM parameters. 41 | - channel: 7 42 | type: hat 43 | id: 0 44 | axis: x 45 | - channel: 8 46 | type: hat 47 | id: 0 48 | axis: y 49 | 50 | # Buttons act as momentary switches. When pressed they set the 51 | # corresponding pwm to their `high` value, when released the pwm is 52 | # set to the `low` value. `low` defaults to 1000, `high` defaults 53 | # to 2000. 54 | - channel: 9 55 | type: button 56 | id: 4 57 | - channel: 10 58 | type: button 59 | id: 5 60 | - channel: 11 61 | type: button 62 | id: 6 63 | - channel: 12 64 | type: button 65 | id: 7 66 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/saili-simulator.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Same as above but is reporting a different name 3 | http://www.hobbyking.com/hobbyking/store/__13597__USB_Simulator_Cable_XTR_AeroFly_FMS.html 4 | has 4 usable axes. The last 4 are binary switches and not PWM outputs. 5 | match: 6 | - '*SAILI Simulator*' 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 3 14 | - channel: 3 15 | type: axis 16 | id: 1 17 | - channel: 4 18 | type: axis 19 | id: 2 20 | - channel: 5 21 | type: axis 22 | id: 4 23 | - channel: 6 24 | type: axis 25 | id: 5 26 | - channel: 7 27 | type: axis 28 | id: 6 29 | - channel: 8 30 | type: axis 31 | id: 7 32 | 33 | # From mavproxy_joystick.py: 34 | # 35 | # '*SAILI Simulator*': 36 | # [(0, 500, 1500), 37 | # (3, 500, 1500), 38 | # (1, 500, 1500), 39 | # (2, 500, 1500), 40 | # (4, 500, 1500), 41 | # (5, 500, 1500), 42 | # (6, 500, 1500), 43 | # (7, 500, 1500)], 44 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/sony-playstation.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Sony PLAYSTATION(R)3 Controller. Only 4 axes usable. This assumes mode 1. 3 | match: 4 | - 'Sony PLAYSTATION(R)3 Controller' 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 2 9 | - channel: 2 10 | type: axis 11 | id: 1 12 | invert: true 13 | - channel: 3 14 | type: axis 15 | id: 3 16 | invert: true 17 | - channel: 4 18 | type: axis 19 | id: 0 20 | invert: true 21 | 22 | # From mavproxy_joystick.py: 23 | # 24 | # 'Sony PLAYSTATION(R)3 Controller': 25 | # # only 4 axes usable. This assumes mode 1 26 | # [(2, 500, 1500), 27 | # (1, -500, 1500), 28 | # (3, -500, 1000), 29 | # (0, -500, 1500)], 30 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/spektrumInterLinkDX.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Spektrum InterLinkDX. Only 7 axes usable. This assumes mode 2. 3 | match: 4 | - 'Spektrum InterLinkDX' 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 3 9 | invert: false 10 | - channel: 2 11 | type: axis 12 | id: 4 13 | invert: true 14 | - channel: 3 15 | type: axis 16 | id: 1 17 | invert: false 18 | - channel: 4 19 | type: axis 20 | id: 0 21 | invert: false 22 | - channel: 6 23 | type: axis 24 | id: 7 25 | invert: false 26 | - channel: 7 27 | type: button 28 | id: 11 29 | invert: false 30 | - channel: 8 31 | type: button 32 | id: 12 33 | - channel: 5 34 | type: multibutton 35 | buttons: 36 | - id: 1 37 | value: 1200 38 | - id: 2 39 | value: 1300 40 | - id: 3 41 | value: 1400 42 | - id: 4 43 | value: 1500 44 | - id: 5 45 | value: 1700 46 | - id: 6 47 | value: 1800 48 | 49 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/sz-mypower-ds4.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | SZ-MYPOWER DS Wired controller. Only 10 axes usable. This assumes mode 2. 3 | match: 4 | - 'SZ-MYPOWER DS4 Wired Controller' 5 | controls: 6 | - channel: 1 7 | type: axis 8 | id: 2 9 | invert: false 10 | - channel: 2 11 | type: axis 12 | id: 5 13 | invert: false 14 | - channel: 3 15 | type: axis 16 | id: 1 17 | invert: true 18 | - channel: 4 19 | type: axis 20 | id: 0 21 | invert: false 22 | - channel: 6 23 | type: axis 24 | id: 4 25 | invert: false 26 | - channel: 5 27 | type: multibutton 28 | buttons: 29 | - id: 0 30 | value: 1200 31 | - id: 1 32 | value: 1300 33 | - id: 2 34 | value: 1400 35 | - id: 3 36 | value: 1500 37 | - id: 5 38 | value: 1700 39 | - id: 4 40 | value: 1800 41 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/taranis.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | FrSky Taranis transmitter as a joystick via USB cable 3 | 4 | match: 5 | - 'FrSky FrSky Taranis*' 6 | 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 0 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | - channel: 3 15 | type: axis 16 | id: 2 17 | - channel: 4 18 | type: axis 19 | id: 3 20 | - channel: 5 21 | type: axis 22 | id: 4 23 | - channel: 6 24 | type: axis 25 | id: 5 26 | - channel: 7 27 | type: axis 28 | id: 6 29 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/xbox-360.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Microsoft X-Box 360 pad. This is for a USB cabled X-Box 360 3 | controller only 4 axes usable. Left and right trigger are ch5 and 4 | ch4. This assumes mode 1 5 | match: 6 | - 'Microsoft X-Box 360 pad' 7 | controls: 8 | - channel: 1 9 | type: axis 10 | id: 3 11 | - channel: 2 12 | type: axis 13 | id: 1 14 | invert: true 15 | - channel: 3 16 | type: axis 17 | id: 4 18 | invert: true 19 | - channel: 4 20 | type: axis 21 | id: 0 22 | - channel: 4 23 | type: axis 24 | id: 0 25 | - channel: 5 26 | type: axis 27 | id: 2 28 | - channel: 6 29 | type: axis 30 | id: 5 31 | 32 | # From mavproxy_joystick.py: 33 | # 34 | # 'Microsoft X-Box 360 pad': 35 | # # This is for a USB cabled X-Box 360 controller 36 | # # only 4 axes usable. Left and right trigger are ch5 and ch4. 37 | # # This assumes mode 1 38 | # [(3, 500, 1500), 39 | # (1, -500, 1500), 40 | # (4, -500, 1500), 41 | # (0, 500, 1500), 42 | # (2, 500, 1500), 43 | # (5, 500, 1500)], 44 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_joystick/joysticks/xboxdrv-mode2.yml: -------------------------------------------------------------------------------- 1 | description: > 2 | Support for Joysticks accessed via the "xboxdrv" utility. Tested with a 3 | Logitech F310. ABXY buttons are mapped to channel 5, flight modes 1-4. 4 | match: 5 | - Xbox Gamepad* 6 | controls: 7 | - channel: 1 8 | type: axis 9 | id: 2 10 | - channel: 2 11 | type: axis 12 | id: 3 13 | - channel: 3 14 | type: axis 15 | id: 1 16 | invert: true 17 | - channel: 4 18 | type: axis 19 | id: 0 20 | 21 | # This maps the A, B, X, and Y buttons onto channel 5, providing 22 | # a convenient way to select between four different flight modes. 23 | # The PWM values here are for flight modes 1-4. 24 | - channel: 5 25 | type: multibutton 26 | buttons: 27 | - id: 0 28 | value: 1200 29 | - id: 1 30 | value: 1300 31 | - id: 2 32 | value: 1400 33 | - id: 3 34 | value: 1500 35 | 36 | # A hat operates like a toggle switch. When an axis goes positive, 37 | # it sets the `high` value, and when an axis goes negative it sets the 38 | # `low` value. When the hat is centered it does not change the 39 | # current channel value. This configuration maps the hat X axis to 40 | # channel 7 and the Y axis to channel 8; these are useful along with 41 | # the CH7_OPT and CH8_OPT APM parameters. 42 | - channel: 7 43 | type: hat 44 | id: 0 45 | axis: x 46 | - channel: 8 47 | type: hat 48 | id: 0 49 | axis: y 50 | 51 | # Buttons act as momentary switches. When pressed they set the 52 | # corresponding pwm to their `high` value, when released the pwm is 53 | # set to the `low` value. `low` defaults to 1000, `high` defaults 54 | # to 2000. 55 | - channel: 9 56 | type: button 57 | id: 4 58 | - channel: 10 59 | type: button 60 | id: 5 61 | 62 | 63 | # This maps the bottom left/bottom right triggers to channels 11 and 64 | # 12. 65 | - channel: 11 66 | type: axis 67 | id: 4 68 | - channel: 12 69 | type: axis 70 | id: 5 71 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_layout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | '''window layout command handling''' 3 | 4 | from MAVProxy.modules.lib import mp_module 5 | 6 | class LayoutModule(mp_module.MPModule): 7 | def __init__(self, mpstate): 8 | super(LayoutModule, self).__init__(mpstate, "layout", "window layout handling", public = False) 9 | self.add_command('layout', self.cmd_layout, 10 | 'window layout management', 11 | [""]) 12 | 13 | def cmd_layout(self, args): 14 | '''handle layout command''' 15 | from MAVProxy.modules.lib import win_layout 16 | if len(args) < 1: 17 | print("usage: layout ") 18 | return 19 | if args[0] == "load": 20 | win_layout.load_layout(self.mpstate.settings.vehicle_name) 21 | elif args[0] == "save": 22 | win_layout.save_layout(self.mpstate.settings.vehicle_name) 23 | 24 | def init(mpstate): 25 | '''initialise module''' 26 | return LayoutModule(mpstate) 27 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_magical/data/arrow.mtl: -------------------------------------------------------------------------------- 1 | # Magical Arrow Material (c) by Intel Corporation 2 | # 3 | # Magical Arrow Material is licensed under a 4 | # Creative Commons Attribution-ShareAlike 4.0 International License. 5 | # 6 | # You should have received a copy of the license along with this 7 | # work. If not, see . 8 | newmtl None 9 | Ns 1 10 | Ka 0.047059 0.400000 0.415686 11 | Kd 0.047059 0.400000 0.415686 12 | Ks 0.500000 0.500000 0.500000 13 | d 1 14 | illum 2 15 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_magical/data/quadcopter.mtl: -------------------------------------------------------------------------------- 1 | # Magical Quadcopter Material (c) by Intel Corporation 2 | # 3 | # Magical Quadcopter Material is licensed under a 4 | # Creative Commons Attribution-ShareAlike 4.0 International License. 5 | # 6 | # You should have received a copy of the license along with this 7 | # work. If not, see . 8 | newmtl BlackMaterial 9 | Ns 92.156863 10 | Ka 0.200000 0.200000 0.200000 11 | Kd 0.200000 0.200000 0.200000 12 | Ks 0.500000 0.500000 0.500000 13 | Ke 0.000000 0.000000 0.000000 14 | Ni 1.000000 15 | d 1.000000 16 | illum 2 17 | 18 | newmtl BlueMaterial 19 | Ns 92.156863 20 | Ka 0.003922 0.419608 0.611765 21 | Kd 0.003922 0.419608 0.611765 22 | Ks 0.500000 0.500000 0.500000 23 | Ke 0.000000 0.000000 0.000000 24 | Ni 1.000000 25 | d 1.000000 26 | illum 2 27 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_magical/glrenderer.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Intel Corporation. All rights reserved. 2 | # 3 | # This file is free software: you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # See the GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program. If not, see . 15 | from OpenGL.GL import * 16 | from pymavlink.rotmat import Vector3 17 | 18 | from MAVProxy.modules.lib import opengl 19 | from MAVProxy.modules.lib.wx_loader import wx 20 | 21 | from wx import glcanvas 22 | 23 | class Renderer(object): 24 | ''' 25 | Base class for rendering 3D opengl objects in Magical UI. It preforms 26 | common routines for the renderers used. The method render() should perform 27 | the rendering routine. The default implementation only does basic setup and 28 | can be called from the subclass. 29 | ''' 30 | def __init__(self, background): 31 | glClearColor(*background) 32 | 33 | self.program = opengl.Program() 34 | self.program.compile_and_link() 35 | 36 | self.program.use_light(opengl.Light( 37 | position=Vector3(-2.0, 0.0, -1.0), 38 | ambient=Vector3(0.8, 0.8, 0.8), 39 | diffuse=Vector3(0.5, 0.5, 0.5), 40 | specular=Vector3(0.25, 0.25, 0.25), 41 | att_linear=0.000, 42 | att_quad=0.000, 43 | )) 44 | 45 | self.camera = opengl.Camera() 46 | # Adjust camera to show NED coordinates properly 47 | self.camera.base = ( 48 | Vector3( 0, 1, 0), 49 | Vector3( 0, 0,-1), 50 | Vector3(-1, 0, 0), 51 | ) 52 | self.camera.position = Vector3(-100.0, 0, 0) 53 | 54 | near = -self.camera.position.x - 1.0 55 | far = near + 2.0 56 | self.projection = opengl.Orthographic(near=near, far=far) 57 | self.program.use_projection(self.projection) 58 | 59 | def set_viewport(self, viewport): 60 | glViewport(*viewport) 61 | 62 | def render(self): 63 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 64 | self.program.use_camera(self.camera) 65 | 66 | class GLCanvas(glcanvas.GLCanvas): 67 | def __init__(self, *k, **kw): 68 | kw['attribList'] = (glcanvas.WX_GL_SAMPLES, 4) 69 | super(GLCanvas, self).__init__(*k, **kw) 70 | self.context = glcanvas.GLContext(self) 71 | self.renderer = None 72 | 73 | self.Bind(wx.EVT_PAINT, self.OnPaint) 74 | 75 | def CreateRenderer(self): 76 | raise NotImplementedError() 77 | 78 | def OnPaint(self, evt): 79 | w, h = self.GetClientSize() 80 | e = min(w, h) 81 | if not e: 82 | return 83 | 84 | self.SetCurrent(self.context) 85 | 86 | if not self.renderer: 87 | self.CreateRenderer() 88 | 89 | x, y = int((w - e) / 2), int((h - e) / 2) 90 | self.renderer.set_viewport((x, y, e, e)) 91 | self.renderer.render() 92 | 93 | self.SwapBuffers() 94 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/barrell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/barrell.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/blueantenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/blueantenna.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/blueblimp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/blueblimp.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/blueboat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/blueboat.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/bluecopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/bluecopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/blueheli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/blueheli.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/blueplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/blueplane.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/bluerover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/bluerover.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/bluesinglecopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/bluesinglecopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/bluesub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/bluesub.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/camera-small-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/camera-small-red.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/cloud.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/flag.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/flame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/flame.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greenantenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greenantenna.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greenblimp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greenblimp.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greencopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greencopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greenheli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greenheli.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greenplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greenplane.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greenrover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greenrover.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greensinglecopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greensinglecopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/greensub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/greensub.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/hawk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/hawk.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/home.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/hoop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/hoop.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/loading.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/loading.jpg -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/migbird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/migbird.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/orangecopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/orangecopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/orangeheli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/orangeheli.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/orangeplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/orangeplane.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/orangerover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/orangerover.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/purpleplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/purpleplane.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/rallypoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/rallypoint.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/ramp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/ramp.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redantenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redantenna.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redblimp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redblimp.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redboat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redboat.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redcopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redcopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redheli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redheli.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redplane.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redrover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redrover.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redsinglecopter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redsinglecopter.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/redsub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/redsub.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/data/unavailable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_map/data/unavailable.jpg -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/mp_elevation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | '''backwards-compatability module - ElevationModel was moved into lib 4 | but we don't want to break existing users 5 | ''' 6 | 7 | 8 | from MAVProxy.modules.lib.mp_elevation import * 9 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_map/srtm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | '''backwards-compatability module - srtm was moved into lib 4 | but we don't want to break existing users 5 | ''' 6 | 7 | 8 | from MAVProxy.modules.lib.srtm import * 9 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_message.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Arbitrary Message Module 4 | Peter Barker, September 2017 5 | 6 | ''' 7 | 8 | import time 9 | 10 | from MAVProxy.modules.lib import mp_module 11 | from MAVProxy.modules.lib import mp_settings 12 | 13 | 14 | class message(mp_module.MPModule): 15 | def __init__(self, mpstate): 16 | """Initialise module""" 17 | super(message, self).__init__(mpstate, "message", "") 18 | self.status_callcount = 0 19 | self.boredom_interval = 10 # seconds 20 | self.last_bored = time.time() 21 | 22 | self.packets_mytarget = 0 23 | self.packets_othertarget = 0 24 | self.verbose = False 25 | 26 | self.message_settings = mp_settings.MPSettings( 27 | [('verbose', bool, False)]) 28 | self.add_command('message', self.cmd_message, "message module", []) 29 | 30 | def usage(self): 31 | '''show help on command line options''' 32 | return "Usage: message TYPE ARG..." 33 | 34 | def cmd_message(self, args): 35 | if len(args) == 0: 36 | print(self.usage()) 37 | else: 38 | packettype = args[0] 39 | methodname = packettype.lower() + "_send" 40 | transformed = [eval(x) for x in args[1:]] 41 | try: 42 | method = getattr(self.master.mav, methodname) 43 | except AttributeError: 44 | print("Unable to find %s" % methodname) 45 | return 46 | method(*transformed) 47 | 48 | 49 | def init(mpstate): 50 | '''initialise module''' 51 | return message(mpstate) 52 | 53 | 54 | # STABILIZE> message MISSION_CLEAR_ALL int(1) int(1) 55 | # STABILIZE> Got MAVLink msg: MISSION_ACK {target_system : 255, 56 | # target_component : 0, type : 0} 57 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_misseditor/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | mission editor module 4 | Michael Day 5 | June 2104 6 | ''' 7 | 8 | from MAVProxy.modules.lib import mp_module 9 | 10 | class MissionEditorModule(mp_module.MPModule): 11 | ''' 12 | A Mission Editor for use with MAVProxy 13 | ''' 14 | def __init__(self, mpstate): 15 | super(MissionEditorModule, self).__init__(mpstate, "misseditor", "mission editor", public = True) 16 | 17 | # to work around an issue on MacOS this module is a thin wrapper around a separate MissionEditorMain object 18 | from MAVProxy.modules.mavproxy_misseditor import mission_editor 19 | self.me_main = mission_editor.MissionEditorMain(mpstate, self.module('terrain').ElevationModel.database) 20 | 21 | def unload(self): 22 | '''unload module''' 23 | self.me_main.unload() 24 | 25 | def idle_task(self): 26 | self.me_main.idle_task() 27 | if self.me_main.needs_unloading: 28 | self.needs_unloading = True 29 | 30 | def mavlink_packet(self, m): 31 | self.me_main.mavlink_packet(m) 32 | 33 | def click_updated(self): 34 | self.me_main.update_map_click_position(self.mpstate.click_location) 35 | 36 | def init(mpstate): 37 | '''initialise module''' 38 | return MissionEditorModule(mpstate) 39 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_misseditor/button_renderer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Custom button render class for use inside a wx.grid 4 | (ported from http://forums.wxwidgets.org/viewtopic.php?t=14403 ) 5 | Michael Day 6 | June 2014 7 | ''' 8 | 9 | from ..lib.wx_loader import wx 10 | from wx import grid 11 | import copy 12 | 13 | class ButtonRenderer(wx.grid.PyGridCellRenderer): 14 | def __init__(self,label,width=75,height=25): 15 | self.label = label 16 | self.width = width 17 | self.height = height 18 | 19 | wx.grid.PyGridCellRenderer.__init__(self) 20 | 21 | def Clone(self): 22 | return copy.copy(self) 23 | 24 | def GetBestSize(self, grid, dc, row, col): 25 | return wx.Size(self.width,self.height) 26 | 27 | def Draw(self, grid, attr, dc, rect, row, col, isSelected): 28 | dc.SetBrush(wx.Brush(wx.SystemSettings.GetColour( 29 | wx.SYS_COLOUR_BTNFACE))) 30 | dc.DrawRectangle( rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight()) 31 | #draw a shaded rectangle to emulate a button 32 | #(taken from src/generic/renderg.cpp) 33 | strength = 1 34 | pen1 = wx.Pen(wx.WHITE, strength) 35 | dc.SetPen(pen1) 36 | dc.DrawLine(rect.GetLeft()+strength-1, rect.GetTop()+strength-1, 37 | rect.GetLeft()+strength-1, rect.GetBottom()-strength+1) 38 | dc.DrawLine(rect.GetLeft()+strength-1, rect.GetTop()+strength-1, 39 | rect.GetRight()-strength, rect.GetTop()+strength-1) 40 | pen2 = wx.Pen(wx.BLACK, strength) 41 | dc.SetPen(pen2) 42 | dc.DrawLine(rect.GetRight()-strength, rect.GetTop(), 43 | rect.GetRight()-strength, rect.GetBottom()); 44 | dc.DrawLine(rect.GetLeft(), rect.GetBottom(), 45 | rect.GetRight() - strength, rect.GetBottom()); 46 | 47 | ''' 48 | #another drawing routine 49 | #(taken from src/generic/renderg.cpp) 50 | #Could port this later for animating the button when clicking 51 | 52 | const wxCoord x = rect.x, 53 | y = rect.y, 54 | w = rect.width, 55 | h = rect.height; 56 | 57 | dc.SetBrush(*wxTRANSPARENT_BRUSH); 58 | 59 | wxPen pen(*wxBLACK, 1); 60 | 61 | dc.SetPen(pen); 62 | dc.DrawLine( x+w, y, x+w, y+h ); // right (outer) 63 | dc.DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) 64 | 65 | pen.SetColour(wxColour(wxT("DARK GREY"))); 66 | dc.SetPen(pen); 67 | dc.DrawLine( x+w-1, y, x+w-1, y+h ); // right (inner) 68 | dc.DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) 69 | 70 | pen.SetColour(*wxWHITE); 71 | dc.SetPen(pen); 72 | dc.DrawRectangle( x, y, w, 1 ); // top (outer) 73 | dc.DrawRectangle( x, y, 1, h ); // left (outer) 74 | dc.DrawLine( x, y+h-1, x+1, y+h-1 ); 75 | dc.DrawLine( x+w-1, y, x+w-1, y+1 ); 76 | ''' 77 | 78 | # draw the button-label 79 | dc.SetBackgroundMode(wx.TRANSPARENT ) 80 | dc.SetTextForeground(attr.GetTextColour() ) 81 | dc.SetFont( attr.GetFont() ) 82 | #dc.DrawLabel( wxT("Delete"), rect, 83 | dc.DrawLabel( self.label, rect, 84 | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) 85 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_misseditor/me_defines.py: -------------------------------------------------------------------------------- 1 | from pymavlink import mavutil 2 | import fnmatch 3 | 4 | miss_cmds = {} 5 | frame_enum = {0: "Abs", 3: "Rel", 10: "AGL"} 6 | frame_enum_rev = {v:k for k,v in frame_enum.items()} 7 | 8 | # auto-generate the list of mission commands 9 | for cmd in mavutil.mavlink.enums['MAV_CMD']: 10 | enum = mavutil.mavlink.enums['MAV_CMD'][cmd] 11 | name = enum.name 12 | name = name.replace('MAV_CMD_','') 13 | if name == 'ENUM_END': 14 | continue 15 | miss_cmds[cmd] = name 16 | 17 | def cmd_reverse_lookup(command_name): 18 | '''returns 0 if key not found''' 19 | for key, value in miss_cmds.items(): 20 | if (value.upper() == command_name.upper()): 21 | return key 22 | return 0 23 | 24 | # a wildcard map from parameter descriptions to column names. If not found in this map 25 | # then the default "Pn" is used 26 | description_map = [ 27 | ('Empty' , '-'), 28 | ('Latitude*' , 'Lat'), 29 | ('Longitude*' , 'Lon'), 30 | ('Altitude*' , 'Alt'), 31 | ('Minimum pitch*' , 'Pitch'), 32 | ('Yaw*' , 'Yaw'), 33 | ('Desired yaw*' , 'Yaw'), 34 | ('Radius*' , 'Radius'), 35 | ('Turns*' , 'Turns'), 36 | ('Seconds*' , 'Time(s)'), 37 | ('Delay in seconds*' , 'Time(s)'), 38 | ('On / Off*' , 'Enable'), 39 | ('Descent / Ascend' , 'Rate'), 40 | ('Finish Altitude' , 'Altitude'), 41 | ('Distance*' , 'Distance'), 42 | ('Mode*' , 'Mode'), 43 | ('Custom mode*' , 'CustomMode'), 44 | ('Sequence*' , 'Seq'), 45 | ('Repeat*' , 'Repeat'), 46 | ('Speed type*' , 'SpeedType'), 47 | ('Speed*' , 'Speed'), 48 | ('Throttle*' , 'Throttle') 49 | ] 50 | 51 | def make_column_label(command_name, description, default): 52 | '''try to work out a reasonable column name from parameter description''' 53 | for (pattern, label) in description_map: 54 | if fnmatch.fnmatch(description, pattern): 55 | return label 56 | return default 57 | 58 | 59 | def get_column_labels(command_name): 60 | '''return dictionary of column labels if available''' 61 | cmd = cmd_reverse_lookup(command_name) 62 | if cmd == 0: 63 | return {} 64 | labels = {} 65 | enum = mavutil.mavlink.enums['MAV_CMD'][cmd] 66 | for col in enum.param.keys(): 67 | labels[col] = make_column_label(command_name, enum.param[col], "P%u" % col) 68 | return labels 69 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_misseditor/me_event.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Event class and enums for Mission Editor 4 | Michael Day 5 | June 2014 6 | ''' 7 | #MissionEditorEvents come FROM the GUI (with a few exceptions where the Mission Editor Module sends a message to itself, e.g., MEE_TIME_TO_QUIT) 8 | #MissionEditorGUIEvents go TO the GUI 9 | #enum for MissionEditorEvent types 10 | MEE_READ_WPS = 0 11 | MEE_WRITE_WPS = 1 12 | MEE_TIME_TO_QUIT = 2 13 | MEE_GET_WP_RAD = 3 14 | MEE_GET_LOIT_RAD = 4 15 | MEE_GET_WP_DEFAULT_ALT = 5 16 | MEE_WRITE_WP_NUM = 6 17 | MEE_LOAD_WP_FILE = 7 18 | MEE_SAVE_WP_FILE = 8 19 | MEE_SET_WP_RAD = 9 20 | MEE_SET_LOIT_RAD = 10 21 | MEE_SET_WP_DEFAULT_ALT = 11 22 | #enum of MissionEditorGUIEvent types 23 | MEGE_CLEAR_MISS_TABLE = 0 24 | MEGE_ADD_MISS_TABLE_ROWS = 1 25 | MEGE_SET_MISS_ITEM = 2 26 | MEGE_SET_WP_RAD = 3 27 | MEGE_SET_LOIT_RAD = 4 28 | MEGE_SET_WP_DEFAULT_ALT = 5 29 | MEGE_SET_LAST_MAP_CLICK_POS = 6 30 | 31 | class MissionEditorEvent: 32 | def __init__(self, type, **kwargs): 33 | self.type = type 34 | self.arg_dict = kwargs 35 | 36 | if not self.type in [MEE_READ_WPS, MEE_WRITE_WPS, MEGE_CLEAR_MISS_TABLE, 37 | MEGE_ADD_MISS_TABLE_ROWS, MEGE_SET_MISS_ITEM, MEE_TIME_TO_QUIT, 38 | MEE_GET_WP_RAD, MEE_GET_LOIT_RAD, MEGE_SET_WP_RAD, MEGE_SET_LOIT_RAD, 39 | MEE_GET_WP_DEFAULT_ALT, MEGE_SET_WP_DEFAULT_ALT, MEE_WRITE_WP_NUM, 40 | MEE_LOAD_WP_FILE, MEE_SAVE_WP_FILE, MEE_SET_WP_RAD, MEE_SET_LOIT_RAD, 41 | MEE_SET_WP_DEFAULT_ALT]: 42 | raise TypeError("Unrecongized MissionEditorEvent type:" + str(self.type)) 43 | 44 | def get_type(self): 45 | return self.type 46 | 47 | def get_arg(self, key): 48 | if not key in self.arg_dict: 49 | print("No key %s in %s" % (key, str(self.type))) 50 | return None 51 | return self.arg_dict[key] 52 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import webbrowser 4 | 5 | import mmap_server 6 | 7 | g_module_context = None 8 | 9 | from MAVProxy.modules.lib import mp_module 10 | 11 | class MMapModule(mp_module.MPModule): 12 | def __init__(self, mpstate): 13 | super(MMapModule, self).__init__(mpstate, 'mmap', 'modest map display') 14 | self.lat = None 15 | self.lon = None 16 | self.alt = None 17 | self.speed = None 18 | self.airspeed = None 19 | self.groundspeed = None 20 | self.heading = 0 21 | self.wp_change_time = 0 22 | self.fence_change_time = 0 23 | self.server = None 24 | self.server = mmap_server.start_server('127.0.0.1', port=9999, module_state=self) 25 | webbrowser.open('http://127.0.0.1:9999/', autoraise=True) 26 | 27 | def unload(self): 28 | """unload module""" 29 | self.server.terminate() 30 | 31 | def mavlink_packet(self, m): 32 | """handle an incoming mavlink packet""" 33 | mtype = m.get_type() 34 | if mtype == 'GPS_RAW': 35 | (self.lat, self.lon) = (m.lat, m.lon) 36 | elif mtype == 'GPS_RAW_INT': 37 | (self.lat, self.lon) = (m.lat / 1.0e7, m.lon / 1.0e7) 38 | elif mtype == "VFR_HUD": 39 | self.heading = m.heading 40 | self.alt = m.alt 41 | self.airspeed = m.airspeed 42 | self.groundspeed = m.groundspeed 43 | 44 | def init(mpstate): 45 | '''initialise module''' 46 | return MMapModule(mpstate) -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/mmap_app/bing.js: -------------------------------------------------------------------------------- 1 | // namespacing! 2 | if (!MM) { 3 | MM = { }; 4 | } 5 | 6 | MM.BingProvider = function(key, style, onready) { 7 | 8 | this.key = key; 9 | this.style = style; 10 | 11 | // hit the imagery metadata service 12 | // http://msdn.microsoft.com/en-us/library/ff701716.aspx 13 | 14 | // Aerial, AerialWithLabels, Road 15 | var script = document.createElement('script'); 16 | script.type = 'text/javascript'; 17 | document.getElementsByTagName('head')[0].appendChild(script); 18 | script.src = 'http://dev.virtualearth.net/REST/V1/Imagery/Metadata/'+style+'/?key='+key+'&jsonp=onBingComplete'; 19 | 20 | function toMicrosoft(column, row, zoom) { 21 | // generate zoom string by interleaving row/col bits 22 | // NB:- this assumes you're only asking for positive row/cols 23 | var quadKey = ""; 24 | for (var i = 1; i <= zoom; i++) { 25 | var rowBit = (row >> zoom-i) & 1; 26 | var colBit = (column >> zoom-i) & 1; 27 | quadKey += (rowBit << 1) + colBit; 28 | } 29 | return quadKey; 30 | } 31 | 32 | var provider = this; 33 | 34 | window.onBingComplete = function(data) { 35 | var resourceSets = data.resourceSets; 36 | for (var i = 0; i < resourceSets.length; i++) { 37 | var resources = data.resourceSets[i].resources; 38 | for (var j = 0; j < resources.length; j++) { 39 | var resource = resources[j]; 40 | 41 | var serverSalt = Math.floor(Math.random() * 4); 42 | provider.getTile = function(coord) { 43 | var quadKey = toMicrosoft(coord.column, coord.row, coord.zoom); 44 | // this is so that requests will be consistent in this session, rather than totally random 45 | var server = Math.abs(serverSalt + coord.column + coord.row + coord.zoom) % 4; 46 | return resource.imageUrl 47 | .replace('{quadkey}',quadKey) 48 | .replace('{subdomain}', resource.imageUrlSubdomains[server]); 49 | }; 50 | // TODO: use resource.imageWidth 51 | // TODO: use resource.imageHeight 52 | } 53 | } 54 | 55 | // TODO: display data.brandLogoUri 56 | // TODO: display data.copyright 57 | onready(provider); 58 | }; 59 | }; 60 | 61 | MM.BingProvider.prototype = { 62 | key: null, 63 | style: null, 64 | subdomains: null, 65 | getTileUrl: null 66 | }; 67 | 68 | MM.extend(MM.BingProvider, MM.MapProvider); 69 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/mmap_app/bluemarble.js: -------------------------------------------------------------------------------- 1 | MM.BlueMarbleProvider = function() { 2 | MM.MapProvider.call(this, function(coordinate) { 3 | coordinate = this.sourceCoordinate(coordinate); 4 | if (!coordinate) return null; 5 | var img = coordinate.zoom.toFixed(0) +'-r'+ coordinate.row.toFixed(0) +'-c'+ coordinate.column.toFixed(0) + '.jpg'; 6 | return 'http://s3.amazonaws.com/com.modestmaps.bluemarble/' + img; 7 | }); 8 | }; 9 | 10 | com.modestmaps.extend(MM.BlueMarbleProvider, MM.MapProvider); 11 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/mmap_app/drone-md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_mmap/mmap_app/drone-md.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/mmap_app/drone-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy/modules/mavproxy_mmap/mmap_app/drone-sm.png -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mmap/mmap_server.py: -------------------------------------------------------------------------------- 1 | import BaseHTTPServer 2 | import json 3 | import os.path 4 | import thread 5 | import urlparse 6 | 7 | DOC_DIR = os.path.join(os.path.dirname(__file__), 'mmap_app') 8 | 9 | 10 | class Server(BaseHTTPServer.HTTPServer): 11 | def __init__(self, handler, address='', port=9999, module_state=None): 12 | BaseHTTPServer.HTTPServer.__init__(self, (address, port), handler) 13 | self.allow_reuse_address = True 14 | self.module_state = module_state 15 | 16 | 17 | class Handler(BaseHTTPServer.BaseHTTPRequestHandler): 18 | def do_GET(self): 19 | scheme, host, path, params, query, frag = urlparse.urlparse(self.path) 20 | if path == '/data': 21 | state = self.server.module_state 22 | data = {'lat': state.lat, 23 | 'lon': state.lon, 24 | 'heading': state.heading, 25 | 'alt': state.alt, 26 | 'airspeed': state.airspeed, 27 | 'groundspeed': state.groundspeed} 28 | self.send_response(200) 29 | self.end_headers() 30 | self.wfile.write(json.dumps(data)) 31 | else: 32 | # Remove leading '/'. 33 | path = path[1:] 34 | # Ignore all directories. E.g. for ../../bar/a.txt serve 35 | # DOC_DIR/a.txt. 36 | unused_head, path = os.path.split(path) 37 | # for / serve index.html. 38 | if path == '': 39 | path = 'index.html' 40 | content = None 41 | error = None 42 | try: 43 | import pkg_resources 44 | name = __name__ 45 | if name == "__main__": 46 | name = "MAVProxy.modules.mavproxy_mmap.????" 47 | content = pkg_resources.resource_stream(name, "mmap_app/%s" % path).read() 48 | except IOError as e: 49 | error = str(e) 50 | if content: 51 | self.send_response(200) 52 | self.end_headers() 53 | self.wfile.write(content) 54 | else: 55 | self.send_response(404) 56 | self.end_headers() 57 | self.wfile.write('Error: %s' % (error,)) 58 | 59 | 60 | def start_server(address, port, module_state): 61 | server = Server( 62 | Handler, address=address, port=port, module_state=module_state) 63 | thread.start_new_thread(server.serve_forever, ()) 64 | return server 65 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_mqtt.py: -------------------------------------------------------------------------------- 1 | from paho.mqtt import MQTTException 2 | from MAVProxy.modules.lib import mp_settings 3 | from MAVProxy.modules.lib import mp_module 4 | import paho.mqtt.client as mqtt 5 | import json 6 | import numbers 7 | 8 | 9 | class MqttModule(mp_module.MPModule): 10 | 11 | def __init__(self, mpstate): 12 | super(MqttModule, self).__init__(mpstate, "mqtt", "mqtt publisher") 13 | self.client = mqtt.Client() 14 | self.device_prefix = '' 15 | self.mqtt_settings = mp_settings.MPSettings( 16 | [('ip', str, '127.0.0.1'), 17 | ('port', int, '1883'), 18 | ('name', str, 'mavproxy'), 19 | ('prefix', str, '') 20 | ]) 21 | self.add_command('mqtt', self.mqtt_command, "mqtt module", ['connect', 'set (MQTTSETTING)']) 22 | self.add_completion_function('(MQTTSETTING)', self.mqtt_settings.completion) 23 | 24 | def mavlink_packet(self, m): 25 | """handle an incoming mavlink packet""" 26 | try: 27 | data = self.convert_to_dict(m) 28 | self.client.publish(f'{self.mqtt_settings.prefix}/{m.get_type()}', json.dumps(data)) 29 | except MQTTException as e: 30 | print(f'mqtt: Exception occurred: {e}') 31 | 32 | def connect(self): 33 | """connect to mqtt broker""" 34 | try: 35 | self.client.reinitialise(client_id=self.mqtt_settings.name) 36 | print(f'connecting to {self.mqtt_settings.ip}:{self.mqtt_settings.port}') 37 | self.client.connect(self.mqtt_settings.ip, int(self.mqtt_settings.port), 30) 38 | except MQTTException as e: 39 | print(f'mqtt: could not establish connection: {e}') 40 | return 41 | print('connected...') 42 | 43 | def mqtt_command(self, args): 44 | """control behaviour of the module""" 45 | if len(args) == 0: 46 | print(self.usage()) 47 | elif args[0] == 'set': 48 | self.mqtt_settings.command(args[1:]) 49 | elif args[0] == 'connect': 50 | self.connect() 51 | 52 | def usage(self): 53 | """show help on command line options""" 54 | return "Usage: mqtt " 55 | 56 | def convert_to_dict(self, message): 57 | """converts mavlink message to python dict""" 58 | if hasattr(message, '_fieldnames'): 59 | result = {} 60 | for field in message._fieldnames: 61 | result[field] = self.convert_to_dict(getattr(message, field)) 62 | return result 63 | if isinstance(message, numbers.Number): 64 | return message 65 | return str(message) 66 | 67 | 68 | def init(mpstate): 69 | """initialise module""" 70 | return MqttModule(mpstate) 71 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_msg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Msg Module 4 | Peter barker, September 2016 5 | 6 | Simple "msg" command sends statustext 7 | 8 | ''' 9 | 10 | from pymavlink import mavutil 11 | import time 12 | 13 | from MAVProxy.modules.lib import mp_module 14 | from MAVProxy.modules.lib import mp_util 15 | from MAVProxy.modules.lib import mp_settings 16 | 17 | 18 | class msg(mp_module.MPModule): 19 | def __init__(self, mpstate): 20 | """Initialise module""" 21 | super(msg, self).__init__(mpstate, "msg", "") 22 | self.status_callcount = 0 23 | self.boredom_interval = 10 # seconds 24 | self.last_bored = time.time() 25 | 26 | self.packets_mytarget = 0 27 | self.packets_othertarget = 0 28 | self.verbose = False 29 | 30 | self.msg_settings = mp_settings.MPSettings( 31 | [ ('verbose', bool, False), 32 | ]) 33 | self.add_command('msg', self.cmd_msg, "statustext sending", []) 34 | 35 | def usage(self): 36 | '''show help on command line options''' 37 | return "Usage: msg message" 38 | 39 | def cmd_msg(self, args): 40 | '''control behaviour of the module''' 41 | if len(args) == 0: 42 | print(self.usage()) 43 | txt = ' '.join(args) 44 | self.master.mav.statustext_send(mavutil.mavlink.MAV_SEVERITY_NOTICE, 45 | txt.encode('utf8')) 46 | 47 | def init(mpstate): 48 | '''initialise module''' 49 | return msg(mpstate) 50 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_optitrack/__init__.py: -------------------------------------------------------------------------------- 1 | # use optitrack data to provide ATT_POS_MOCAP data 2 | # it works with optitrack motion capture cameras and optitrack motive tracker software (https://optitrack.com/software/motive/) 3 | # yuan-chu tai 4 | 5 | import time 6 | from pymavlink import mavutil 7 | from MAVProxy.modules.lib import mp_module 8 | from MAVProxy.modules.lib import mp_util 9 | from MAVProxy.modules.lib import mp_settings 10 | from MAVProxy.modules.mavproxy_optitrack import NatNetClient 11 | 12 | class optitrack(mp_module.MPModule): 13 | def __init__(self, mpstate): 14 | """Initialise module""" 15 | super(optitrack, self).__init__(mpstate, "optitrack", "optitrack") 16 | self.optitrack_settings = mp_settings.MPSettings( 17 | [('server', str, '127.0.0.1'), 18 | ('client', str, '127.0.0.1'), 19 | ('msg_intvl_ms', int, 75), 20 | ('obj_id', int, 1), 21 | ('print_lv', int, 0), 22 | ('multicast', bool, True)] 23 | ) 24 | self.add_command('optitrack', self.cmd_optitrack, "optitrack control", ['', '', 'set (OPTITRACKSETTING)']) 25 | self.streaming_client = NatNetClient.NatNetClient() 26 | # Configure the streaming client to call our rigid body handler on the emulator to send data out. 27 | self.streaming_client.rigid_body_listener = self.receive_rigid_body_frame 28 | self.last_msg_time = 0 29 | self.started = False 30 | 31 | # This is a callback function that gets connected to the NatNet client. It is called once per rigid body per frame 32 | def receive_rigid_body_frame(self, new_id, position, rotation): 33 | if (new_id == self.optitrack_settings.obj_id): 34 | now = time.time() 35 | if (now - self.last_msg_time) > (self.optitrack_settings.msg_intvl_ms * 0.001): 36 | time_us = int(now * 1.0e6) 37 | self.master.mav.att_pos_mocap_send(time_us, (rotation[3], rotation[0], rotation[2], -rotation[1]), position[0], position[2], -position[1]) 38 | self.last_msg_time = now 39 | 40 | def usage(self): 41 | '''show help on command line options''' 42 | return "Usage: optitrack " 43 | 44 | def cmd_start(self): 45 | self.streaming_client.set_client_address(self.optitrack_settings.client) 46 | self.streaming_client.set_server_address(self.optitrack_settings.server) 47 | self.streaming_client.set_print_level(self.optitrack_settings.print_lv) 48 | self.streaming_client.set_use_multicast(self.optitrack_settings.multicast) 49 | self.streaming_client.run() 50 | self.started = True 51 | 52 | def cmd_optitrack(self, args): 53 | '''control behaviour of the module''' 54 | if len(args) == 0: 55 | print(self.usage()) 56 | elif args[0] == "start": 57 | self.cmd_start() 58 | elif args[0] == "stop": 59 | if self.started: 60 | self.started = False 61 | self.streaming_client.shutdown() 62 | elif args[0] == "set": 63 | self.optitrack_settings.command(args[1:]) 64 | else: 65 | print(self.usage()) 66 | 67 | def init(mpstate): 68 | '''initialise module''' 69 | return optitrack(mpstate) 70 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_paramedit/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | param editor module 4 | Akshath Singhal 5 | June 2019 6 | ''' 7 | 8 | from MAVProxy.modules.lib import mp_module 9 | 10 | 11 | class ParamEditorModule(mp_module.MPModule): 12 | ''' 13 | A Graphical parameter editor for use with MAVProxy 14 | ''' 15 | def __init__(self, mpstate): 16 | super(ParamEditorModule, self).__init__(mpstate, 17 | "paramedit", "param edit", 18 | public=True) 19 | 20 | # to work around an issue on MacOS this module is a thin wrapper 21 | # around a separate ParamEditorMain object 22 | self.pe_main = None 23 | self.mpstate = mpstate 24 | 25 | def unload(self): 26 | '''unload module''' 27 | if self.pe_main: 28 | self.pe_main.unload() 29 | 30 | def idle_task(self): 31 | if not self.pe_main: 32 | # wait for parameter module to load 33 | if self.module('param') is None: 34 | return 35 | from MAVProxy.modules.mavproxy_paramedit import param_editor 36 | self.pe_main = param_editor.ParamEditorMain(self.mpstate) 37 | if self.pe_main: 38 | if self.pe_main.needs_unloading: 39 | self.needs_unloading = True 40 | self.pe_main.idle_task() 41 | 42 | def mavlink_packet(self, m): 43 | if self.pe_main: 44 | self.pe_main.mavlink_packet(m) 45 | 46 | 47 | def init(mpstate): 48 | '''initialise module''' 49 | return ParamEditorModule(mpstate) 50 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_paramedit/ph_event.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Event class and enums for Parameter Editor 4 | 5 | ''' 6 | # ParamEditorEvents come FROM the GUI (with a few exceptions where the 7 | # Parameter Editor Module sends a message to itself). 8 | # ParamEditorEditorGUIEvents go to the GUI 9 | # enum for ParamEditorEvent types 10 | PEE_READ_KEY = 0 11 | PEE_LOAD_FILE = 1 12 | PEE_SAVE_FILE = 2 13 | PEE_READ_PARAM = 3 14 | PEE_WRITE_PARAM = 4 15 | PEE_TIME_TO_QUIT = 5 16 | PEE_RESET = 6 17 | PEE_FETCH = 7 18 | # enum of ParamEditorGUIEvent types 19 | PEGE_READ_PARAM = 0 20 | PEGE_REFRESH_PARAM = 1 21 | PEGE_WRITE_SUCC = 2 22 | PEGE_RCIN = 3 23 | 24 | 25 | class ParamEditorEvent: 26 | def __init__(self, type, **kwargs): 27 | self.type = type 28 | self.arg_dict = kwargs 29 | 30 | if self.type not in [PEE_SAVE_FILE, PEE_LOAD_FILE, PEE_READ_KEY, 31 | PEGE_REFRESH_PARAM, PEGE_READ_PARAM, PEGE_RCIN, 32 | PEE_READ_PARAM, PEE_WRITE_PARAM, PEE_RESET, 33 | PEE_TIME_TO_QUIT, PEGE_WRITE_SUCC, PEE_FETCH]: 34 | raise TypeError("Unrecongized ParamEditorEvent type:" + 35 | str(self.type)) 36 | 37 | def get_type(self): 38 | return self.type 39 | 40 | def get_arg(self, key): 41 | if key not in self.arg_dict: 42 | print("No key %s in %s" % (key, str(self.type))) 43 | return None 44 | return self.arg_dict[key] 45 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_ppp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | A PPP over MAVLink module 4 | Andrew Tridgell 5 | May 2012 6 | ''' 7 | 8 | import time, os, fcntl, pty 9 | 10 | from MAVProxy.modules.lib import mp_module 11 | 12 | class PPPModule(mp_module.MPModule): 13 | def __init__(self, mpstate): 14 | super(PPPModule, self).__init__(mpstate, "ppp", "PPP link") 15 | self.command = "noauth nodefaultroute nodetach nodeflate nobsdcomp mtu 128".split() 16 | self.packet_count = 0 17 | self.byte_count = 0 18 | self.ppp_fd = -1 19 | self.pid = -1 20 | self.add_command('ppp', self.cmd_ppp, "ppp link control") 21 | 22 | 23 | def ppp_read(self, ppp_fd): 24 | '''called from main select loop in mavproxy when the pppd child 25 | sends us some data''' 26 | buf = os.read(ppp_fd, 100) 27 | if len(buf) == 0: 28 | # EOF on the child fd 29 | self.stop_ppp_link() 30 | return 31 | print("ppp packet len=%u" % len(buf)) 32 | master = self.master 33 | master.mav.ppp_send(len(buf), buf) 34 | 35 | def start_ppp_link(self): 36 | '''startup the link''' 37 | cmd = ['pppd'] 38 | cmd.extend(self.command) 39 | (self.pid, self.ppp_fd) = pty.fork() 40 | if self.pid == 0: 41 | os.execvp("pppd", cmd) 42 | raise RuntimeError("pppd exited") 43 | if self.ppp_fd == -1: 44 | print("Failed to create link fd") 45 | return 46 | 47 | # ensure fd is non-blocking 48 | fcntl.fcntl(self.ppp_fd, fcntl.F_SETFL, fcntl.fcntl(self.ppp_fd, fcntl.F_GETFL) | os.O_NONBLOCK) 49 | self.byte_count = 0 50 | self.packet_count = 0 51 | 52 | # ask mavproxy to add us to the select loop 53 | self.mpself.select_extra[self.ppp_fd] = (self.ppp_read, self.ppp_fd) 54 | 55 | 56 | def stop_ppp_link(self): 57 | '''stop the link''' 58 | if self.ppp_fd == -1: 59 | return 60 | try: 61 | self.mpself.select_extra.pop(self.ppp_fd) 62 | os.close(self.ppp_fd) 63 | os.waitpid(self.pid, 0) 64 | except Exception: 65 | pass 66 | self.pid = -1 67 | self.ppp_fd = -1 68 | print("stopped ppp link") 69 | 70 | 71 | def cmd_ppp(self, args): 72 | '''set ppp parameters and start link''' 73 | usage = "ppp " 74 | if len(args) == 0: 75 | print(usage) 76 | return 77 | if args[0] == "command": 78 | if len(args) == 1: 79 | print("ppp.command=%s" % " ".join(self.command)) 80 | else: 81 | self.command = args[1:] 82 | elif args[0] == "start": 83 | self.start_ppp_link() 84 | elif args[0] == "stop": 85 | self.stop_ppp_link() 86 | elif args[0] == "status": 87 | self.console.writeln("%u packets %u bytes" % (self.packet_count, self.byte_count)) 88 | 89 | def unload(self): 90 | '''unload module''' 91 | self.stop_ppp_link() 92 | 93 | def mavlink_packet(self, m): 94 | '''handle an incoming mavlink packet''' 95 | if m.get_type() == 'PPP' and self.ppp_fd != -1: 96 | print("got ppp mavlink pkt len=%u" % m.length) 97 | os.write(self.ppp_fd, m.data[:m.length]) 98 | 99 | def init(mpstate): 100 | '''initialise module''' 101 | return PPPModule(mpstate) 102 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_serial.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | '''serial_control MAVLink handling''' 3 | 4 | import time, os, fnmatch, sys 5 | from pymavlink import mavutil, mavwp 6 | from MAVProxy.modules.lib import mp_settings 7 | from MAVProxy.modules.lib import mp_module 8 | 9 | class SerialModule(mp_module.MPModule): 10 | def __init__(self, mpstate): 11 | super(SerialModule, self).__init__(mpstate, "serial", "serial control handling") 12 | self.add_command('serial', self.cmd_serial, 13 | 'remote serial control', 14 | ['', 15 | 'set (SERIALSETTING)']) 16 | self.serial_settings = mp_settings.MPSettings( 17 | [ ('port', int, 0), 18 | ('baudrate', int, 57600), 19 | ('timeout', int, 500) 20 | ] 21 | ) 22 | self.add_completion_function('(SERIALSETTING)', self.serial_settings.completion) 23 | self.locked = False 24 | 25 | def mavlink_packet(self, m): 26 | '''handle an incoming mavlink packet''' 27 | if m.get_type() == 'SERIAL_CONTROL': 28 | data = m.data[:m.count] 29 | s = ''.join(str(chr(x)) for x in data) 30 | sys.stdout.write(s) 31 | 32 | def serial_lock(self, lock): 33 | '''lock or unlock the port''' 34 | mav = self.master.mav 35 | if lock: 36 | flags = mavutil.mavlink.SERIAL_CONTROL_FLAG_EXCLUSIVE 37 | self.locked = True 38 | else: 39 | flags = 0 40 | self.locked = False 41 | mav.serial_control_send(self.serial_settings.port, 42 | flags, 43 | 0, 0, 0, [0]*70) 44 | 45 | def serial_send(self, args): 46 | '''send some bytes''' 47 | mav = self.master.mav 48 | flags = 0 49 | if self.locked: 50 | flags |= mavutil.mavlink.SERIAL_CONTROL_FLAG_EXCLUSIVE 51 | if self.serial_settings.timeout != 0: 52 | flags |= mavutil.mavlink.SERIAL_CONTROL_FLAG_RESPOND 53 | if self.serial_settings.timeout >= 500: 54 | flags |= mavutil.mavlink.SERIAL_CONTROL_FLAG_MULTI 55 | 56 | s = ' '.join(args) 57 | s = s.replace('\\r', '\r') 58 | s = s.replace('\\n', '\n') 59 | buf = [ord(x) for x in s] 60 | buf.extend([0]*(70-len(buf))) 61 | mav.serial_control_send(self.serial_settings.port, 62 | flags, 63 | self.serial_settings.timeout, 64 | self.serial_settings.baudrate, 65 | len(s), buf) 66 | 67 | def cmd_serial(self, args): 68 | '''serial control commands''' 69 | usage = "Usage: serial " 70 | if len(args) < 1: 71 | print(usage) 72 | return 73 | if args[0] == "lock": 74 | self.serial_lock(True) 75 | elif args[0] == "unlock": 76 | self.serial_lock(False) 77 | elif args[0] == "set": 78 | self.serial_settings.command(args[1:]) 79 | elif args[0] == "send": 80 | self.serial_send(args[1:]) 81 | else: 82 | print(usage) 83 | 84 | def init(mpstate): 85 | '''initialise module''' 86 | return SerialModule(mpstate) 87 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_smartcamera/sc_webcam.py: -------------------------------------------------------------------------------- 1 | """ 2 | sc_webcam.py 3 | 4 | This file includes functions to: 5 | initialise a web cam 6 | capture image from web cam 7 | 8 | Image size is held in the smart_camera.cnf 9 | """ 10 | 11 | import sys 12 | import time 13 | import math 14 | import cv2 15 | import sc_config 16 | 17 | class SmartCameraWebCam: 18 | 19 | def __init__(self, instance): 20 | 21 | # health 22 | self.healthy = False; 23 | 24 | # record instance 25 | self.instance = instance 26 | self.config_group = "camera%d" % self.instance 27 | 28 | # get image resolution 29 | self.img_width = sc_config.config.get_integer(self.config_group,'width',640) 30 | self.img_height = sc_config.config.get_integer(self.config_group,'height',480) 31 | 32 | # background image processing variables 33 | self.img_counter = 0 # num images requested so far 34 | 35 | # latest image captured 36 | self.latest_image = None 37 | 38 | # setup video capture 39 | self.camera = cv2.VideoCapture(self.instance) 40 | 41 | # check we can connect to camera 42 | if not self.camera.isOpened(): 43 | print("failed to open webcam %d" % self.instance) 44 | 45 | # __str__ - print position vector as string 46 | def __str__(self): 47 | return "SmartCameraWebCam Object W:%d H:%d" % (self.img_width, self.img_height) 48 | 49 | # latest_image - returns latest image captured 50 | def get_latest_image(self): 51 | # write to file 52 | #imgfilename = "C:\Users\rmackay9\Documents\GitHub\ardupilot-balloon-finder\smart_camera\img%d-%d.jpg" % (cam_num,cam.get_image_counter()) 53 | imgfilename = "img%d-%d.jpg" % (self.instance,self.get_image_counter()) 54 | print (imgfilename) 55 | cv2.imwrite(imgfilename, self.latest_image) 56 | return self.latest_image 57 | 58 | # get_image_counter - returns number of images captured since startup 59 | def get_image_counter(self): 60 | return self.img_counter 61 | 62 | # take_picture - take a picture 63 | # returns True on success 64 | def take_picture(self): 65 | # setup video capture 66 | print("Taking Picture") 67 | self.camera = cv2.VideoCapture(self.instance) 68 | self.camera.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,self.img_width) 69 | self.camera.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,self.img_height) 70 | 71 | # check we can connect to camera 72 | if not self.camera.isOpened(): 73 | self.healty = False 74 | return False 75 | 76 | # get an image from the webcam 77 | success_flag, self.latest_image=self.camera.read() 78 | 79 | # release camera 80 | self.camera.release() 81 | 82 | # if successful overwrite our latest image 83 | if success_flag: 84 | self.img_counter = self.img_counter+1 85 | return True 86 | 87 | # return failure 88 | return False 89 | 90 | # main - tests SmartCameraWebCam class 91 | def main(self): 92 | 93 | while True: 94 | # send request to image capture for image 95 | if self.take_picture(): 96 | # display image 97 | cv2.imshow ('image_display', self.get_latest_image()) 98 | else: 99 | print("no image") 100 | 101 | # check for ESC key being pressed 102 | k = cv2.waitKey(5) & 0xFF 103 | if k == 27: 104 | break 105 | 106 | # take a rest for a bit 107 | time.sleep(0.01) 108 | 109 | # run test run from the command line 110 | if __name__ == "__main__": 111 | sc_webcam0 = SmartCameraWebCam(0) 112 | sc_webcam0.main() 113 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_smartcamera/smart_camera.cnf: -------------------------------------------------------------------------------- 1 | [camera0] 2 | # for no camera set type = 0, for webcam set type = 1 3 | type = 2 4 | #width = 640 5 | #height = 480 6 | #horizontal-fov = 70.42 7 | #vertical-fov = 43.3 8 | #video_output_file = ~/smartcamera-%%Y-%%m-%%d-%%H-%%M.avi 9 | 10 | [general] 11 | WirelessPort = wlan0 12 | #debug = True 13 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_smartcamera/ssdp.py: -------------------------------------------------------------------------------- 1 | # thanks to 2 | # https://gist.github.com/dankrause/6000248 3 | # 4 | # Copyright 2014 Dan Krause 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import socket 19 | import httplib 20 | import StringIO 21 | 22 | class SSDPResponse(object): 23 | class _FakeSocket(StringIO.StringIO): 24 | def makefile(self, *args, **kw): 25 | return self 26 | def __init__(self, response): 27 | r = httplib.HTTPResponse(self._FakeSocket(response)) 28 | r.begin() 29 | self.location = r.getheader("location") 30 | self.usn = r.getheader("usn") 31 | self.st = r.getheader("st") 32 | self.cache = r.getheader("cache-control").split("=")[1] 33 | def __repr__(self): 34 | return "".format(**self.__dict__) 35 | 36 | def discover(service, if_ip=None, timeout=2, retries=1): 37 | group = ("239.255.255.250", 1900) 38 | message = "\r\n".join([ 39 | 'M-SEARCH * HTTP/1.1', 40 | 'HOST: {0}:{1}', 41 | 'MAN: "ssdp:discover"', 42 | 'ST: {st}','MX: 3','','']) 43 | socket.setdefaulttimeout(timeout) 44 | responses = [] 45 | for _ in range(retries): 46 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 47 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 48 | sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) 49 | if if_ip is not None: 50 | sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(if_ip)) 51 | sock.sendto(message.format(*group, st=service), group) 52 | while True: 53 | try: 54 | response = SSDPResponse(sock.recv(1024)) 55 | responses.append(response) 56 | except socket.timeout: 57 | break 58 | return responses 59 | 60 | # Example: 61 | # import ssdp 62 | # ssdp.discover("roku:ecp") 63 | 64 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_soar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' 3 | Soaring Module 4 | Ryan Friedman 5 | 6 | This module displays the estimated soaring thermals on the map. 7 | A circle is drawn with the estimated radius from ArduSoar's estimated thermal location. 8 | 9 | Note that this module uses NAMED_VALUE_FLOAT messages from the autopilot, 10 | a temporary measure until a proper mavlink message is decided upon. 11 | 12 | AP_FLAKE8_CLEAN 13 | ''' 14 | 15 | from MAVProxy.modules.lib import mp_module, mp_util 16 | from MAVProxy.modules.mavproxy_map import mp_slipmap 17 | 18 | import time 19 | 20 | 21 | class soar(mp_module.MPModule): 22 | _SOAR_THERMAL_MAP_OBJ_ID = "soar-thermal" 23 | _CLEAR_STALE_THERMAL_TIME = 5.0 24 | 25 | def __init__(self, mpstate): 26 | """Initialise module""" 27 | super(soar, self).__init__(mpstate, "soar", "") 28 | self._strength = None 29 | self._radius = None 30 | self._x = None 31 | self._y = None 32 | self._last_draw_time = time.time() 33 | 34 | def mavlink_packet(self, m): 35 | '''handle mavlink packets''' 36 | 37 | if m.get_type() == 'NAMED_VALUE_FLOAT' and m.name.startswith("SOAR"): 38 | if m.name == "SOAREKFX0": 39 | self._strength = m.value 40 | elif m.name == "SOAREKFX1": 41 | self._radius = m.value 42 | elif m.name == "SOAREKFX2": 43 | self._x = m.value 44 | elif m.name == "SOAREKFX3": 45 | self._y = m.value 46 | else: 47 | raise NotImplementedError(m.name) 48 | 49 | self.draw_thermal_estimate() 50 | 51 | def idle_task(self): 52 | '''called rapidly by mavproxy''' 53 | 54 | if time.time() - self._last_draw_time > self._CLEAR_STALE_THERMAL_TIME: 55 | self.clear_thermal_estimate() 56 | 57 | def draw_thermal_estimate(self): 58 | 59 | if self._radius is None: 60 | return 61 | if self._x is None: 62 | return 63 | if self._y is None: 64 | return 65 | 66 | wp_module = self.module('wp') 67 | if wp_module is None: 68 | return 69 | home = wp_module.get_home() 70 | if home is None: 71 | return 72 | 73 | home_lat = home.x 74 | home_lng = home.y 75 | 76 | (thermal_lat, thermal_lon) = mp_util.gps_offset(home_lat, home_lng, self._y, self._x) 77 | 78 | slipcircle = mp_slipmap.SlipCircle( 79 | self._SOAR_THERMAL_MAP_OBJ_ID, # key 80 | "thermals", # layer 81 | (thermal_lat, thermal_lon), # latlon 82 | self._radius, # radius 83 | (0, 255, 255), 84 | linewidth=2) 85 | for mp in self.module_matching('map*'): 86 | self._last_draw_time = time.time() 87 | mp.map.add_object(slipcircle) 88 | 89 | def clear_thermal_estimate(self): 90 | for mp in self.module_matching('map*'): 91 | mp.map.remove_object(self._SOAR_THERMAL_MAP_OBJ_ID) 92 | 93 | 94 | def init(mpstate): 95 | '''initialise module''' 96 | return soar(mpstate) 97 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | '''test flight for DCM noise''' 3 | 4 | import time, math 5 | 6 | def enum(**enums): 7 | return type('Enum', (), enums) 8 | 9 | TestState = enum(INIT=1, FBWA=2, AUTO=3) 10 | 11 | from MAVProxy.modules.lib import mp_module 12 | 13 | class TestModule(mp_module.MPModule): 14 | def __init__(self, mpstate): 15 | super(TestModule, self).__init__(mpstate, "test", "test flight") 16 | self.state = TestState.INIT 17 | print("Module test loaded") 18 | 19 | def mavlink_packet(self, m): 20 | '''handle an incoming mavlink packet''' 21 | if self.state == TestState.INIT: 22 | if self.status.flightmode == "MANUAL": 23 | self.mpstate.functions.process_stdin("switch 4") 24 | self.mpstate.functions.process_stdin("rc 2 1300") 25 | self.mpstate.functions.process_stdin("rc 3 2000") 26 | self.mpstate.functions.process_stdin("module load sensors") 27 | self.mpstate.functions.process_stdin("watch sensors") 28 | self.mpstate.functions.process_stdin("wp list") 29 | self.state = TestState.FBWA 30 | if self.state == TestState.FBWA: 31 | if self.status.altitude > 60: 32 | self.mpstate.functions.process_stdin("rc 2 1500") 33 | self.mpstate.functions.process_stdin("auto") 34 | self.state = TestState.AUTO 35 | 36 | def init(mpstate): 37 | '''initialise module''' 38 | return TestModule(mpstate) 39 | -------------------------------------------------------------------------------- /MAVProxy/modules/mavproxy_timesync.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import print_function 4 | 5 | """ 6 | Currently what I do is run a sync every second and keep the following: 7 | time_send 8 | time_receive 9 | 10 | As a result the delta between GCS time and drone time is: 11 | dtime = (time_send + time_receive) / 2 - drone_time; 12 | 13 | And when doing that a lot the dtime will average to the correct 14 | delta. As a result it is now possible to know exactly when a 15 | "GLOBAL_POSITION_INT" was created in GCS time. 16 | """ 17 | 18 | from MAVProxy.modules.lib import mp_module 19 | 20 | 21 | class TimeSyncModule(mp_module.MPModule): 22 | def __init__(self, mpstate): 23 | super(TimeSyncModule, self).__init__(mpstate, "timesync") 24 | self.add_command('timesync', self.cmd_timesync, "timesync") 25 | 26 | def cmd_timesync(self, args): 27 | if (len(args) != 1): 28 | print("Usage: timesync CURRENT_TIME") 29 | return 30 | 31 | self.master.mav.timesync_send(0, int(args[0])) 32 | 33 | def mavlink_packet(self, m): 34 | '''handle an incoming mavlink packet''' 35 | if m.get_type() == 'TIMESYNC': 36 | print(m) 37 | 38 | 39 | def init(mpstate): 40 | '''initialise module''' 41 | return TimeSyncModule(mpstate) 42 | -------------------------------------------------------------------------------- /MAVProxy/tools/MAVExplorer.bat: -------------------------------------------------------------------------------- 1 | cd ..\..\ 2 | python.exe -m pip install --upgrade build . --user 3 | python.exe .\MAVProxy\tools\MAVExplorer.py 4 | pause 5 | -------------------------------------------------------------------------------- /MAVProxy/tools/mavpicviewer/mavpicviewer.bat: -------------------------------------------------------------------------------- 1 | cd ..\..\ 2 | python setup.py build install --user 3 | python .\MAVProxy\tools\mavpicviewer\mavpicviewer.py 4 | pause 5 | -------------------------------------------------------------------------------- /MAVProxy/tools/mavpicviewer/mavpicviewer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | MAV Picture Viewer 5 | 6 | Quick and efficient reviewing of images taken from a drone 7 | 8 | AP_FLAKE8_CLEAN 9 | ''' 10 | 11 | import os 12 | from argparse import ArgumentParser 13 | from MAVProxy.modules.lib import multiproc 14 | import mavpicviewer_image 15 | import mavpicviewer_mosaic 16 | 17 | prefix_str = "mavpicviewer: " 18 | 19 | 20 | # main function 21 | if __name__ == "__main__": 22 | multiproc.freeze_support() 23 | parser = ArgumentParser(description=__doc__) 24 | parser.add_argument("filepath", nargs='?', default=".", help="filename or directory holding images") 25 | args = parser.parse_args() 26 | 27 | # check destination directory exists 28 | if not os.path.exists(args.filepath): 29 | exit(prefix_str + "invalid destination directory") 30 | 31 | # create queue for interprocess communication 32 | mosaic_to_image_comm, image_to_mosaic_comm = multiproc.Pipe() 33 | 34 | # create image viewer 35 | mavpicviewer_image.mavpicviewer_image(args.filepath, image_to_mosaic_comm) 36 | 37 | # create mosaic 38 | mavpicviewer_mosaic.mavpicviewer_mosaic(args.filepath, mosaic_to_image_comm) 39 | -------------------------------------------------------------------------------- /MAVProxy/tools/mavpicviewer/mavpicviewer_settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | MAV Picture Viewer Settings Window 5 | 6 | User configuration of Settings 7 | 8 | AP_FLAKE8_CLEAN 9 | ''' 10 | 11 | from MAVProxy.modules.lib import mp_util 12 | if mp_util.has_wxpython: 13 | from MAVProxy.modules.lib.wx_loader import wx 14 | 15 | 16 | class mavpicviewer_settings: 17 | """window to capture picviewer settings""" 18 | 19 | def __init__(self, settings_changed_cb): 20 | 21 | # add settings window 22 | self.settings_frame = wx.Frame(None, title="Settings", size=(300, 80)) 23 | 24 | # add FOV input box and 25 | self.settings_fov_text = wx.StaticText(self.settings_frame, id=-1, label="FOV", pos=(10, 10)) 26 | self.settings_fov_input = wx.TextCtrl(self.settings_frame, id=-1, pos=(50, 10), size=(100, -1), 27 | style=wx.TE_PROCESS_ENTER) 28 | 29 | # add Set FOV button 30 | self.settings_set_button = wx.Button(self.settings_frame, id=-1, label="Set FOV", pos=(200, 10), size=(75, 25)) 31 | self.settings_frame.Bind(wx.EVT_BUTTON, self.settings_set_button_click, self.settings_set_button) 32 | self.settings_frame.Bind(wx.EVT_TEXT_ENTER, self.settings_set_button_click, self.settings_fov_input) 33 | 34 | # add Yaw input box 35 | self.settings_yaw_text = wx.StaticText(self.settings_frame, id=-1, label="Yaw", pos=(10, 40)) 36 | self.settings_yaw_input = wx.TextCtrl(self.settings_frame, id=-1, pos=(50, 40), size=(100, -1), 37 | style=wx.TE_PROCESS_ENTER) 38 | 39 | # add Set Yaw button 40 | self.settings_setyaw_button = wx.Button(self.settings_frame, id=-1, label="Set YAW", pos=(200, 40), size=(75, 25)) 41 | self.settings_frame.Bind(wx.EVT_BUTTON, self.settings_setyaw_button_click, self.settings_setyaw_button) 42 | self.settings_frame.Bind(wx.EVT_TEXT_ENTER, self.settings_setyaw_button_click, self.settings_yaw_input) 43 | 44 | # handle close event 45 | self.settings_frame.Bind(wx.EVT_CLOSE, self.settings_close_button_click) 46 | 47 | # record callback function 48 | self.settings_changed_cb = settings_changed_cb 49 | 50 | # show settings window 51 | def show_settings_window(self, event): 52 | """show settings window""" 53 | self.settings_frame.Show() 54 | 55 | # settings window event handlers 56 | def settings_set_button_click(self, event): 57 | """settings window event handlers""" 58 | self.settings_changed_cb("FOV", self.settings_fov_input.GetValue()) 59 | self.settings_frame.Hide() 60 | 61 | def settings_setyaw_button_click(self, event): 62 | """settings window event handlers""" 63 | self.settings_changed_cb("YAW", self.settings_yaw_input.GetValue()) 64 | print("YAW set to: ", self.settings_yaw_input.GetValue()) 65 | self.settings_frame.Hide() 66 | 67 | # close/hide settings window 68 | def settings_close_button_click(self, event): 69 | """settings window event handlers""" 70 | self.settings_frame.Hide() 71 | -------------------------------------------------------------------------------- /MAVProxy/tools/mavpicviewer/mavpicviewer_shared.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | MAV Picture Viewer Shared Classes 5 | 6 | Quick and efficient reviewing of images taken from a drone 7 | 8 | AP_FLAKE8_CLEAN 9 | ''' 10 | 11 | import os 12 | 13 | 14 | # defintions for RGB colours 15 | RGB_YELLOW = (255, 255, 0) 16 | RGB_RED = (255, 0, 0) 17 | RGB_GREEN = (0, 255, 0) 18 | RGB_BLUE = (0, 0, 255) 19 | 20 | 21 | # Loc (aka Location) class holds lat, lon, alt 22 | class Loc: 23 | def __init__(self, lat, lon, alt, terr_alt=0): 24 | self.lat = lat 25 | self.lon = lon 26 | self.alt = alt 27 | self.terr_alt = terr_alt 28 | 29 | 30 | # Pos (aka Position) class holds X, Y pixel coordinates 31 | class Pos: 32 | def __init__(self, X, Y): 33 | self.X = X 34 | self.Y = Y 35 | 36 | 37 | # POI (aka Point of Interest) class holds two positions and two locations 38 | class POI: 39 | def __init__(self, pos1, pos2, loc1, loc2): 40 | self.pos1 = pos1 41 | self.pos2 = pos2 42 | self.loc1 = loc1 43 | self.loc2 = loc2 44 | 45 | 46 | # Tempclass holds Temp Max, X, Y pixel coordinates 47 | class TempAndPos: 48 | def __init__(self, temp_max, temp_pos_x, temp_pos_y): 49 | self.temp_max = temp_max 50 | self.temp_pos_x = temp_pos_x 51 | self.temp_pos_y = temp_pos_y 52 | 53 | 54 | # return an array of files for a given directory and extension 55 | def get_file_list(directory, extensions): 56 | '''return file list for a directory''' 57 | flist = [] 58 | for filename in os.listdir(directory): 59 | extension = filename.split('.')[-1] 60 | if extension.lower() in extensions: 61 | flist.append(os.path.join(directory, filename)) 62 | sorted_list = sorted(flist, key=str.lower) 63 | return sorted_list 64 | 65 | 66 | # communication objects for mosaic and image viewer 67 | # set the file list (a dictionary of paths to images) 68 | class SetFilelist: 69 | def __init__(self, filelist): 70 | self.filelist = filelist 71 | 72 | 73 | # set the current file number (aka current image being viewed) 74 | class SetFilenumber: 75 | def __init__(self, filenumber): 76 | self.filenumber = filenumber 77 | 78 | 79 | # set the FOV in degrees 80 | class SetFOV: 81 | def __init__(self, fov): 82 | self.fov = fov 83 | 84 | 85 | # set the Yaw in degrees 86 | class SetYaw: 87 | def __init__(self, yaw): 88 | self.yaw = yaw 89 | 90 | 91 | # close the application 92 | class Close: 93 | def __init__(self): 94 | pass 95 | 96 | 97 | # set the Image's location (lat, lon, alt, terr_alt) 98 | class SetImageLoc: 99 | def __init__(self, filenumber, loc): 100 | self.filenumber = filenumber 101 | self.loc = loc 102 | 103 | 104 | # set POI for the given filenumber 105 | class SetPOI: 106 | def __init__(self, filenumber, poi): 107 | self.filenumber = filenumber 108 | self.poi = poi 109 | 110 | 111 | # clear POI for the given filenumber 112 | class ClearPOI: 113 | def __init__(self, filenumber): 114 | self.filenumber = filenumber 115 | 116 | 117 | # clear ALL POIs for all images 118 | class ClearAllPOI: 119 | def __init__(self): 120 | pass 121 | 122 | 123 | # request temperatures from all images 124 | class GetTempForAllImages: 125 | def __init__(self): 126 | pass 127 | 128 | 129 | # set Temp data for the given filenumber 130 | class SetTempAndPos: 131 | def __init__(self, filenumber, temp_max, temp_pos_x, temp_pos_y): 132 | self.filenumber = filenumber 133 | self.temp_max = temp_max 134 | self.temp_pos_x = temp_pos_x 135 | self.temp_pos_y = temp_pos_y 136 | -------------------------------------------------------------------------------- /MAVProxy_Icon/3.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/3.ai -------------------------------------------------------------------------------- /MAVProxy_Icon/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/3.jpg -------------------------------------------------------------------------------- /MAVProxy_Icon/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/3.png -------------------------------------------------------------------------------- /MAVProxy_Icon/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/icon.jpg -------------------------------------------------------------------------------- /MAVProxy_Icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/icon.png -------------------------------------------------------------------------------- /MAVProxy_Icon/mockup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/mockup.jpg -------------------------------------------------------------------------------- /MAVProxy_Icon/source file 2.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/source file 2.ai -------------------------------------------------------------------------------- /MAVProxy_Icon/source file.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/source file.ai -------------------------------------------------------------------------------- /MAVProxy_Icon/trans-BG-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/trans-BG-2.png -------------------------------------------------------------------------------- /MAVProxy_Icon/trans-BG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/trans-BG.png -------------------------------------------------------------------------------- /MAVProxy_Icon/white-BG-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/white-BG-2.jpg -------------------------------------------------------------------------------- /MAVProxy_Icon/white-BG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/MAVProxy_Icon/white-BG.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub Actions](https://github.com/ardupilot/MAVProxy/actions/workflows/windows_build.yml/badge.svg) 2 | 3 | MAVProxy 4 | 5 | This is a MAVLink ground station written in python. 6 | 7 | Please see https://ardupilot.org/mavproxy/index.html for more information 8 | 9 | This ground station was developed as part of the CanberraUAV OBC team 10 | entry 11 | 12 | License 13 | ------- 14 | 15 | MAVProxy is released under the GNU General Public License v3 or later 16 | 17 | 18 | Maintainers 19 | ----------- 20 | 21 | The best way to discuss MAVProxy with the maintainers is to join the 22 | mavproxy channel on ArduPilot discord at https://ardupilot.org/discord 23 | 24 | Lead Developers: Andrew Tridgell and Peter Barker 25 | 26 | Windows Maintainer: Stephen Dade 27 | 28 | MacOS Maintainer: Rhys Mainwaring 29 | -------------------------------------------------------------------------------- /docs/MavProxy_Screenshot_Termux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/docs/MavProxy_Screenshot_Termux.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pymavlink>=2.4.14 2 | pyserial>=3.0 3 | numpy 4 | -------------------------------------------------------------------------------- /scripts/run_flake8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | Runs flake8 over Python files which contain a marker indicating 5 | they are clean, ensures that they actually are 6 | 7 | AP_FLAKE8_CLEAN 8 | """ 9 | 10 | import os 11 | import subprocess 12 | import sys 13 | 14 | import argparse 15 | 16 | os.environ['PYTHONUNBUFFERED'] = '1' 17 | 18 | 19 | class Flake8Checker(object): 20 | def __init__(self, basedirs): 21 | self.retcode = 0 22 | self.files_to_check = [] 23 | self.basedirs = basedirs 24 | 25 | def progress(self, string): 26 | print("****** %s" % (string,)) 27 | 28 | def check(self): 29 | if len(self.files_to_check) == 0: 30 | return 31 | for path in self.files_to_check: 32 | self.progress("Checking (%s)" % path) 33 | ret = subprocess.run(["flake8", "--show-source"] + self.files_to_check, 34 | stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 35 | if ret.returncode != 0: 36 | self.progress("Flake8 check failed: (%s)" % (ret.stdout)) 37 | self.retcode = 1 38 | 39 | def run(self): 40 | for basedir in self.basedirs: 41 | for (dirpath, dirnames, filenames) in os.walk(basedir): 42 | for filename in filenames: 43 | if os.path.splitext(filename)[1] != ".py": 44 | continue 45 | filepath = os.path.join(dirpath, filename) 46 | content = open(filepath).read() 47 | if "AP_FLAKE8_CLEAN" not in content: 48 | continue 49 | self.files_to_check.append(filepath) 50 | self.check() 51 | return self.retcode 52 | 53 | 54 | if __name__ == '__main__': 55 | parser = argparse.ArgumentParser(description='Check all Python files for flake8 cleanliness') 56 | parser.add_argument('DIRPATH', nargs="+", default=[], help='directory to recurse into') 57 | args = parser.parse_args() 58 | 59 | checker = Flake8Checker(args.DIRPATH) 60 | sys.exit(checker.run()) 61 | -------------------------------------------------------------------------------- /shortcuts/ReadMe.md: -------------------------------------------------------------------------------- 1 | Installing Linux shortcuts for MAVPRoxy and MAVExplorer with icons 2 | 3 | 1. Copy the .desktop files to the .local/share/applications directory in your home directory. You may need to use CRTL-H to see the .local directory in your file manager. 4 | 2. Copy the .png icon files to the .icon directory in your home directory. 5 | 3. Open the Software search page (Show Applications button on launcher bar) 6 | 4. Find either MAVProxy or MAVExplorer and add to favorites to have them in the launch bar 7 | 5. If you rather have a desktop shortcut, copy the appropriate desktop file to the Desktop. You may be asked to verify that this is a trusted application, if so, do so. 8 | 9 | Notes: the MAVProxy shortcut will store its data files (mav.param, mav.tlog, etc.) in a directory called MAVProxy_data n the home directory, if it exists, or the home directory if it does not...you can edit the mavproxy.desktop to change the directory if you wish. 10 | 11 | If you place a copy of the mavexplorer.desktop file on the desktop, you can drag and drop a log file onto it and it will open using it. 12 | -------------------------------------------------------------------------------- /shortcuts/mavexplorer.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Terminal=true 5 | Exec=bash -c 'export PATH="$PATH:~/.local/bin"; MAVExplorer.py %F' 6 | Name=MAVExplorer 7 | Icon=mavexplorer 8 | Comment=MAVExplorer Log Analyzer 9 | 10 | -------------------------------------------------------------------------------- /shortcuts/mavexplorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/shortcuts/mavexplorer.png -------------------------------------------------------------------------------- /shortcuts/mavpicviewer.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Terminal=true 5 | Exec=bash -c 'export PATH="$PATH:~/.local/bin"; mavpicviewer.py %F' 6 | Name=MAVPicViewer 7 | Icon=mavpicviewer 8 | Comment=Picture Review Tool 9 | 10 | -------------------------------------------------------------------------------- /shortcuts/mavpicviewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/shortcuts/mavpicviewer.png -------------------------------------------------------------------------------- /shortcuts/mavproxy.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Terminal=true 5 | Exec=bash -c 'cd ~/MAVProxy_data ;mavproxy.py --console --map' 6 | Name=MAVProxy 7 | Icon=mavproxy 8 | Comment=MAVProxy GCS 9 | 10 | -------------------------------------------------------------------------------- /shortcuts/mavproxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/shortcuts/mavproxy.png -------------------------------------------------------------------------------- /windows/MAVExplorer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/windows/MAVExplorer.ico -------------------------------------------------------------------------------- /windows/MAVProxy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/windows/MAVProxy.ico -------------------------------------------------------------------------------- /windows/MAVProxyWinBuild.bat: -------------------------------------------------------------------------------- 1 | rem build the standalone MAVProxy.exe for Windows. 2 | rem This assumes Python and pip are on the system path 3 | rem This assumes InnoSetup is installed in C:\Program Files (x86)\Inno Setup 6 4 | rem If it is not, change the INNOSETUP environment variable accordingly 5 | SETLOCAL enableextensions 6 | 7 | if "%INNOSETUP%" == "" (set "INNOSETUP=C:\Program Files (x86)\Inno Setup 6") 8 | 9 | rem get the version 10 | for /f "tokens=*" %%a in ( 11 | 'python.exe returnVersion.py' 12 | ) do ( 13 | set VERSION=%%a 14 | ) 15 | 16 | rem -----Upgrade pymavlink if needed----- 17 | if exist "..\..\pymavlink" ( 18 | rem Rebuild and use pymavlink from pymavlink sources if available 19 | pushd ..\..\pymavlink 20 | python.exe setup.py build install --user 21 | popd 22 | ) else ( 23 | if exist "..\..\mavlink\pymavlink" ( 24 | rem Rebuild and use pymavlink from mavlink\pymavlink sources if available 25 | pushd ..\..\mavlink\pymavlink 26 | python.exe setup.py build install --user 27 | popd 28 | ) else ( 29 | pip.exe install pymavlink -U --user 30 | ) 31 | ) 32 | 33 | rem -----Install additional Python packages----- 34 | python.exe -m pip install -U wheel setuptools pip 35 | python.exe -m pip install pywin32 lxml pymavlink numpy matplotlib pyserial opencv-python PyYAML Pygame Pillow wxpython prompt-toolkit scipy 36 | python.exe -m pip install -U openai wave pyaudio 37 | python.exe -m pip install -U pyinstaller==6.7.0 packaging 38 | python.exe -m pip install -U requests 39 | 40 | rem -----Build MAVProxy----- 41 | cd ..\ 42 | python.exe -m pip install .[recommended] --user 43 | cd .\MAVProxy 44 | copy ..\windows\mavproxy.spec 45 | pyinstaller -y --clean mavproxy.spec 46 | del mavproxy.spec 47 | 48 | rem -----Create version Info----- 49 | @echo off 50 | @echo %VERSION%> ..\windows\version.txt 51 | @echo on 52 | 53 | rem -----Download parameter files----- 54 | cd ..\ 55 | mkdir Parameters 56 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Rover/apm.pdef.xml' -Destination 'Parameters\Rover.xml'" 57 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Copter/apm.pdef.xml' -Destination 'Parameters\Copter.xml'" 58 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Plane/apm.pdef.xml' -Destination 'Parameters\Plane.xml'" 59 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Sub/apm.pdef.xml' -Destination 'Parameters\Sub.xml'" 60 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/AntennaTracker/apm.pdef.xml' -Destination 'Parameters\AntennaTracker.xml'" 61 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Heli/apm.pdef.xml' -Destination 'Parameters\Heli.xml'" 62 | powershell.exe "Start-BitsTransfer -Source 'http://autotest.ardupilot.org/Parameters/Blimp/apm.pdef.xml' -Destination 'Parameters\Blimp.xml'" 63 | 64 | rem -----Build the Installer----- 65 | cd .\windows 66 | rem Newer Inno Setup versions do not require a -compile flag, please add it if you have an old version 67 | "%INNOSETUP%\ISCC.exe" /dMyAppVersion=%VERSION% mavproxy.iss 68 | 69 | pause 70 | -------------------------------------------------------------------------------- /windows/Startup Examples/MAVProxyLogput.bat: -------------------------------------------------------------------------------- 1 | rem This demonstrates saving the logfile (tlog) to a specific directory 2 | rem In this case all logs will be saved to the user's Documents/Test1 folder 3 | mavproxy.exe --master=0.0.0.0:14550 --state-basedir=%USERPROFILE%\Documents --aircraft=Test1 4 | pause -------------------------------------------------------------------------------- /windows/Startup Examples/MAVProxyMultiOutput.bat: -------------------------------------------------------------------------------- 1 | rem This demonstrates multiple TCP and UDP outputs from MAVProxy 2 | rem It will send a mavlink stream to the first connection to this computer's 3 | rem IP address and UDP port 15000 and TCP port 16000 4 | mavproxy.exe --master=0.0.0.0:14550 --out=udpin:0.0.0.0:15000 --out=tcpin:0.0.0.0:16000 5 | pause 6 | -------------------------------------------------------------------------------- /windows/mavpicviewer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArduPilot/MAVProxy/224e88628ad2cf90e5059282c2ae209a94d2bce8/windows/mavpicviewer.ico -------------------------------------------------------------------------------- /windows/returnVersion.py: -------------------------------------------------------------------------------- 1 | # This script reads the setup.py and returns the current version number 2 | # Used as part of building the WIndows setup file (MAVProxyWinBuild.bat) 3 | # It assumes there is a line like this: 4 | # version = "12344" 5 | 6 | # glob supports Unix style pathname extensions 7 | with open("../setup.py") as f: 8 | searchlines = f.readlines() 9 | for i, line in enumerate(searchlines): 10 | if "version = " in line: 11 | print(line[11:len(line)-2]) 12 | break 13 | --------------------------------------------------------------------------------