SHOTS: Update for buttons, AC Master, & speeds

Update to all smart shots for some or all of the following:
- Button handling for the new Open Solo button handling rework
- Copter yaw compatibility with ArduCopter master
- Accelleration fixes and standardization
This commit is contained in:
Matt 2017-12-16 11:36:51 -05:00
parent 296a8af950
commit 39743a9be0
10 changed files with 230 additions and 142 deletions

View File

@ -1,52 +1,48 @@
# follow.py '''
# shotmanager follow.py
# shotmanager
# The Follow Me smart shot controller.
# Runs as a DroneKit-Python script.
#
# Created by Will Silva on 12/14/2015.
# Altitude and Leash follow created by Jason Short 2/25/2016
# Copyright (c) 2016 3D Robotics.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from dronekit import Vehicle, LocationGlobalRelative, VehicleMode The Follow Me smart shot controller.
Runs as a DroneKit-Python script.
Created by Will Silva on 12/14/2015.
Altitude and Leash follow created by Jason Short 2/25/2016
Copyright (c) 2016 3D Robotics.
Licensed under the Apache License, Version 2.0 (the "License");
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
from pymavlink import mavutil
import os import os
from os import sys, path
import math import math
import struct import struct
import monotonic import monotonic
import collections import collections
sys.path.append(os.path.realpath(''))
import app_packet import app_packet
import camera import camera
import location_helpers import location_helpers
import pathHandler import pathHandler
import shotLogger import shotLogger
from shotManagerConstants import *
import shots import shots
import socket import socket
from dronekit import Vehicle, LocationGlobalRelative, VehicleMode
from pymavlink import mavutil
from shotManagerConstants import *
from orbitController import OrbitController from orbitController import OrbitController
from lookAtController import LookAtController from lookAtController import LookAtController
from flyController import FlyController from flyController import FlyController
from leashController import LeashController from leashController import LeashController
from os import sys, path
from vector3 import Vector3 from vector3 import Vector3
# on host systems these files are located here
from sololink import btn_msg from sololink import btn_msg
sys.path.append(os.path.realpath(''))
FOLLOW_PORT = 14558 FOLLOW_PORT = 14558
SOCKET_TIMEOUT = 0.01 SOCKET_TIMEOUT = 0.01
@ -75,27 +71,38 @@ ROI_ALT_FILTER_GAIN = 0.65 # Relative contribution of the previous and new data
logger = shotLogger.logger logger = shotLogger.logger
'''
Define the different followStates:
# Define the different followStates: Follow Wait
Initial state before everything is ready. This state exits when the
first ROI is sent from the app. (in filterROI()) The shot will probably
only be in this state for a few ticks.
# Follow Wait Look At Me
# Initial state before everything is ready. This state exits when the first ROI is sent from the app. (in filterROI()) The shot will probably only be in this state for a few ticks. Copter does not move unless commanded by stick actions, but the camera
# Look At Me rotates to keep the ROI in frame
# Copter does not move unless commanded by stick actions, but the camera rotates to keep the ROI in frame
# Follow Orbit: Default behaviour. Follow Orbit: Default behaviour.
# Copter translates to keep the user in frame, maintining a offset in a particular direction (i.e. North) of the user. Copter translates to keep the user in frame, maintining a offset in a
# Once the orbit is started (cruise via the app or with sticks) then the copter orbits around the ROI, keeping the subject in frame. particular direction (i.e. North) of the user. Once the orbit is started
# Follow Leash (cruise via the app or with sticks) then the copter orbits around the ROI,
# Copter tries to stay behind the user's direction of motion. keeping the subject in frame.
# If the copter is within the leash length from the user, the leash is "slack" so the copter rotates but does not move.
# Once the copter gets further from the user. It swings around to get behind the user and keep up. Follow Leash
# User can adjust altitude and radius with sticks but cannot strafe manually. Copter tries to stay behind the user's direction of motion.
# Follow Free Look If the copter is within the leash length from the user, the leash is
# Copter maintains an offset from the ROI and can get dragged around as the ROI moves "slack" so the copter rotates but does not move. Once the copter gets
# User can move the copter with the roll/pitch sticks like FLY mode further from the user. It swings around to get behind the user and keep up.
# User can adjust the altitude with the controller paddle User can adjust altitude and radius with sticks but cannot strafe manually.
# User can freely control the camera pan/tilt with the left stick.
# Camera maintains constant yaw/pitch unless the user permutes it. Follow Free Look
Copter maintains an offset from the ROI and can get dragged around as
the ROI moves. User can move the copter with the roll/pitch sticks
like FLY mode. User can adjust the altitude with the controller paddle.
User can freely control the camera pan/tilt with the left stick.
Camera maintains constant yaw/pitch unless the user permutes it.
'''
FOLLOW_WAIT = 0 FOLLOW_WAIT = 0
FOLLOW_LOOKAT = 1 FOLLOW_LOOKAT = 1
@ -196,9 +203,11 @@ class FollowShot():
''' '''
Position Control Position Control
Note: All follow controllers return position and velocity of the drone in "absolute" space (as opposed to relative to the ROI) Note: All follow controllers return position and velocity of the
Pos: Lat, lon, alt. Alt is relative to home location. NEU frame, of course. drone in "absolute" space (as opposed to relative to the ROI)
Vel: Speed in the x,y, and z directions. NEU frame. vel.z needs to be inverted before passing to the autopilot. Pos: Lat, lon, alt. Alt is relative to home location. NEU frame..
Vel: Speed in the x,y, and z directions. NEU frame. vel.z needs
to be inverted before passing to the autopilot.
''' '''
# Look At Me Mode (Vehicle stays put) # Look At Me Mode (Vehicle stays put)
@ -273,7 +282,7 @@ class FollowShot():
# if we can handle the button we do # if we can handle the button we do
def handleButton(self, button, event): def handleButton(self, button, event):
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
# Allow the user to exit Look At Me mode (into the previous follow mode) with the A button # Allow the user to exit Look At Me mode (into the previous follow mode) with the A button
if self.followPreference == FOLLOW_PREF_LEASH: if self.followPreference == FOLLOW_PREF_LEASH:
@ -284,7 +293,7 @@ class FollowShot():
self.initState(FOLLOW_ORBIT) self.initState(FOLLOW_ORBIT)
# Change Follow Mode to Look At Me on Pause button press # Change Follow Mode to Look At Me on Pause button press
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
self.initState(FOLLOW_LOOKAT) self.initState(FOLLOW_LOOKAT)
self.shotmgr.notifyPause(True) self.shotmgr.notifyPause(True)
self.updateAppOptions() self.updateAppOptions()
@ -621,9 +630,24 @@ class FollowShot():
self.camPitch * 100, self.camPitch * 100,
0.0, # roll 0.0, # roll
# yaw is in centidegrees # yaw is in centidegrees
self.camYaw * 100, 0, #self.camYaw * 100, (Disabled by Matt due to ArduCopter master mount_control problem)
0 # save position 0 # save position
) )
self.vehicle.send_mavlink(msg)
# Use MAV_CMD_CONDITION_YAW since the yaw in MSG_MOUNT_CONTROL is not working in AC35
msg = self.vehicle.message_factory.command_long_encode(
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_CONDITION_YAW, #command
0, #confirmation
self.camYaw, # param 1 - target angle
YAW_SPEED, # param 2 - yaw speed
self.camDir, # param 3 - direction
0.0, # relative offset
0, 0, 0 # params 5-7 (unused)
)
self.vehicle.send_mavlink(msg)
else: else:
# if we don't have a gimbal, just set CONDITION_YAW # if we don't have a gimbal, just set CONDITION_YAW
msg = self.vehicle.message_factory.command_long_encode( msg = self.vehicle.message_factory.command_long_encode(
@ -673,3 +697,4 @@ class FollowShot():
return False return False
else: else:
return True return True

View File

@ -33,7 +33,7 @@ from orbitController import OrbitController
logger = shotLogger.logger logger = shotLogger.logger
#Path accel/decel constants #Path accel/decel constants
PATH_ACCEL = 2.5 PATH_ACCEL = 2.0
ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME
ORBIT_RAD_FOR_MIN_SPEED = 2.0 ORBIT_RAD_FOR_MIN_SPEED = 2.0

View File

@ -9,9 +9,8 @@
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -42,8 +41,8 @@ logger = shotLogger.logger
# CONSTANTS # CONSTANTS
ACCEL_LIMIT = 2.5 #m/s^2 ACCEL_LIMIT = 2.0 #m/s^2
NORM_ACCEL_LIMIT = 2.25 #m/s^2 NORM_ACCEL_LIMIT = 1.75 #m/s^2
TANGENT_ACCEL_LIMIT = math.sqrt(ACCEL_LIMIT**2-NORM_ACCEL_LIMIT**2) #m/s^2 TANGENT_ACCEL_LIMIT = math.sqrt(ACCEL_LIMIT**2-NORM_ACCEL_LIMIT**2) #m/s^2
# Yaw rate (deg/s) # Yaw rate (deg/s)
@ -290,8 +289,11 @@ class MultipointShot():
newPitch += self.yawPitchOffsetter.pitchOffset newPitch += self.yawPitchOffsetter.pitchOffset
newYaw += self.yawPitchOffsetter.yawOffset newYaw += self.yawPitchOffsetter.yawOffset
# formulate mavlink message for mount controller # Formulate mavlink message for mount controller. Use mount_control if using a gimbal. Use just condition_yaw if no gimbal.
# do we have a gimbal? # Modified by Matt 2017-05-18 for ArducCopter master compatibility
# mav_cmd_do_mount_control should handle gimbal pitch and copter yaw, but yaw is not working in master.
# So this mount_control command is only going to do the gimbal pitch for now.
if self.vehicle.mount_status[0] is not None: if self.vehicle.mount_status[0] is not None:
pointingMsg = self.vehicle.message_factory.mount_control_encode( pointingMsg = self.vehicle.message_factory.mount_control_encode(
0, 1, # target system, target component 0, 1, # target system, target component
@ -300,7 +302,23 @@ class MultipointShot():
newYaw * 100, # yaw (centidegrees) newYaw * 100, # yaw (centidegrees)
0 # save position 0 # save position
) )
# if not, assume fixed mount self.vehicle.send_mavlink(pointingMsg)
# Temporary fix while the yaw control is not working in the above mount_control command.
pointingMsg = self.vehicle.message_factory.command_long_encode(
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_CONDITION_YAW, # command
0, # confirmation
newYaw, # param 1 - target angle (degrees)
YAW_SPEED, # param 2 - yaw speed (deg/s)
0, # param 3 - direction, always shortest route for now...
0.0, # relative offset
0, 0, 0 # params 5-7 (unused)
)
self.vehicle.send_mavlink(pointingMsg)
# if no gimbal, assume fixed mount and use condition_yaw only
else: else:
# if we don't have a gimbal, just set CONDITION_YAW # if we don't have a gimbal, just set CONDITION_YAW
pointingMsg = self.vehicle.message_factory.command_long_encode( pointingMsg = self.vehicle.message_factory.command_long_encode(
@ -313,10 +331,9 @@ class MultipointShot():
0.0, # relative offset 0.0, # relative offset
0, 0, 0 # params 5-7 (unused) 0, 0, 0 # params 5-7 (unused)
) )
# send pointing command to vehicle
self.vehicle.send_mavlink(pointingMsg) self.vehicle.send_mavlink(pointingMsg)
def interpolateCamera(self): def interpolateCamera(self):
'''Interpolate (linear) pitch and yaw between cable control points''' '''Interpolate (linear) pitch and yaw between cable control points'''
@ -474,9 +491,9 @@ class MultipointShot():
def handleButton(self, button, event): def handleButton(self, button, event):
'''handle actions for button presses''' '''handle actions for button presses'''
if not self.cableCamPlaying: if not self.cableCamPlaying:
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
self.recordLocation() self.recordLocation()
if button == btn_msg.ButtonB and event == btn_msg.Press: if button == btn_msg.ButtonB and event == btn_msg.ClickRelease:
self.recordLocation() self.recordLocation()
# only try to start a cable if we have more than 2 points # only try to start a cable if we have more than 2 points
if len(self.waypoints) > 1: if len(self.waypoints) > 1:
@ -484,7 +501,7 @@ class MultipointShot():
self.enterPlayMode() self.enterPlayMode()
# handle pause button # handle pause button
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
self.setCruiseSpeed(state = PAUSED) self.setCruiseSpeed(state = PAUSED)
logger.log("[multipoint]: Pause button pressed on Artoo.") logger.log("[multipoint]: Pause button pressed on Artoo.")
@ -831,11 +848,32 @@ class MultipointShot():
if self.vehicle.mount_status[0] is not None: if self.vehicle.mount_status[0] is not None:
pointingMsg = self.vehicle.message_factory.mount_control_encode( pointingMsg = self.vehicle.message_factory.mount_control_encode(
0, 1, # target system, target component 0, 1, # target system, target component
startPitch * 100, # pitch (centidegrees) newPitch * 100, # pitch (centidegrees)
0.0, # roll (centidegrees) 0.0, # roll (centidegrees)
startYaw * 100, # yaw (centidegrees) newYaw * 100, # yaw (centidegrees)
0 # save position 0 # save position
) )
self.vehicle.send_mavlink(pointingMsg)
pointingMsg = self.vehicle.message_factory.command_long_encode(
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_CONDITION_YAW, # command
0, # confirmation
startYaw, # param 1 - target angle (degrees)
ATTACH_YAW_SPEED, # param 2 - yaw speed (deg/s)
0, # param 3 - direction, always shortest route for now...
0.0, # relative offset
0, 0, 0 # params 5-7 (unused)
)
self.vehicle.send_mavlink(pointingMsg)
# pointingMsg = self.vehicle.message_factory.mount_control_encode(
# 0, 1, # target system, target component
# startPitch * 100, # pitch (centidegrees)
# 0.0, # roll (centidegrees)
# startYaw * 100, # yaw (centidegrees)
# 0 # save position
# )
# if not, assume fixed mount # if not, assume fixed mount
else: else:
# if we don't have a gimbal, just set CONDITION_YAW # if we don't have a gimbal, just set CONDITION_YAW
@ -849,8 +887,6 @@ class MultipointShot():
0.0, # relative offset 0.0, # relative offset
0, 0, 0 # params 5-7 (unused) 0, 0, 0 # params 5-7 (unused)
) )
# send pointing command to vehicle
self.vehicle.send_mavlink(pointingMsg) self.vehicle.send_mavlink(pointingMsg)
def listenForAttach(self): def listenForAttach(self):

View File

@ -24,7 +24,6 @@ import os
from os import sys, path from os import sys, path
import math import math
import struct import struct
sys.path.append(os.path.realpath('')) sys.path.append(os.path.realpath(''))
import app_packet import app_packet
import camera import camera
@ -259,10 +258,10 @@ class OrbitShot():
def handleButton(self, button, event): def handleButton(self, button, event):
'''Handle a controller button press''' '''Handle a controller button press'''
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
if self.roi is None: if self.roi is None:
self.spotLock() self.spotLock()
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
if self.pathHandler: if self.pathHandler:
self.pathHandler.togglePause() self.pathHandler.togglePause()
self.updateAppOptions() self.updateAppOptions()

View File

@ -33,7 +33,7 @@ from vector3 import Vector3
logger = shotLogger.logger logger = shotLogger.logger
#Path accel/decel constants #Path accel/decel constants
PATH_ACCEL = 2.5 PATH_ACCEL = 2.0
ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME
ORBIT_MIN_SPEED = 3.0 ORBIT_MIN_SPEED = 3.0

View File

@ -6,19 +6,19 @@
# Runs as a DroneKit-Python script under MAVProxy. # Runs as a DroneKit-Python script under MAVProxy.
# #
# Created by Jason Short and Will Silva on 11/30/2015. # Created by Jason Short and Will Silva on 11/30/2015.
# Copyright (c) 2015 3D Robotics. # Copyright (c) 2016 3D Robotics.
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dronekit import Vehicle, LocationGlobalRelative, VehicleMode from dronekit import Vehicle, LocationGlobalRelative, VehicleMode
from pymavlink import mavutil from pymavlink import mavutil
@ -391,7 +391,7 @@ class PanoShot():
# if we can handle the button we do # if we can handle the button we do
def handleButton(self, button, event): def handleButton(self, button, event):
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
# don't use A button for video ever # don't use A button for video ever
if self.panoType != PANO_VIDEO: if self.panoType != PANO_VIDEO:
if self.state == PANO_SETUP: if self.state == PANO_SETUP:
@ -407,12 +407,12 @@ class PanoShot():
self.setButtonMappings() self.setButtonMappings()
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
if self.panoType == PANO_VIDEO: if self.panoType == PANO_VIDEO:
self.degSecondYaw = 0 self.degSecondYaw = 0
# cycle through options # cycle through options
if self.state == PANO_SETUP and button == btn_msg.ButtonB and event == btn_msg.Press: if self.state == PANO_SETUP and button == btn_msg.ButtonB and event == btn_msg.ClickRelease:
#clear Pano Video yaw speed #clear Pano Video yaw speed
self.degSecondYaw = 0 self.degSecondYaw = 0
if self.panoType == PANO_VIDEO: if self.panoType == PANO_VIDEO:
@ -474,9 +474,23 @@ class PanoShot():
self.camPitch * 100, self.camPitch * 100,
0.0, # roll 0.0, # roll
# yaw is in centidegrees # yaw is in centidegrees
self.camYaw * 100, 0, # self.camYaw * 100, (Disabled by Matt for now due to ArduCopter master mount_control bug. Using condition_yaw instead)
0 # save position 0 # save position
) )
self.vehicle.send_mavlink(msg)
msg = self.vehicle.message_factory.command_long_encode( # Using condition_yaw temporarily until mount_control yaw issue is fixed
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_CONDITION_YAW, #command
0, #confirmation
self.camYaw, # param 1 - target angle
YAW_SPEED, # param 2 - yaw speed
self.camDir, # param 3 - direction
0.0, # relative offset
0, 0, 0 # params 5-7 (unused)
)
self.vehicle.send_mavlink(msg)
else: else:
# if we don't have a gimbal, just set CONDITION_YAW # if we don't have a gimbal, just set CONDITION_YAW
msg = self.vehicle.message_factory.command_long_encode( msg = self.vehicle.message_factory.command_long_encode(

View File

@ -11,7 +11,7 @@ import shots
logger = shotLogger.logger logger = shotLogger.logger
#Path accel/decel constants #Path accel/decel constants
PATH_ACCEL = 6 PATH_ACCEL = 2
ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME ACCEL_PER_TICK = PATH_ACCEL * UPDATE_TIME

View File

@ -103,11 +103,11 @@ class SelfieShot():
# if we can handle the button we do # if we can handle the button we do
def handleButton(self, button, event): def handleButton(self, button, event):
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
self.pointAtROI() self.pointAtROI()
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
if self.pathHandler: if self.pathHandler:
self.shotmgr.notifyPause(True) self.shotmgr.notifyPause(True)
self.pathHandler.togglePause() self.pathHandler.togglePause()

View File

@ -12,8 +12,8 @@ from vector3 import Vector3
logger = shotLogger.logger logger = shotLogger.logger
#Path accel/decel constants #Path accel/decel constants
WPNAV_ACCEL = 3.4 WPNAV_ACCEL = 200
WPNAV_ACCEL_Z = 1.6 WPNAV_ACCEL_Z = 160
# for 3D max speed # for 3D max speed
HIGH_PATH_SPEED = 5.0 HIGH_PATH_SPEED = 5.0

View File

@ -10,15 +10,15 @@
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dronekit import Vehicle, LocationGlobalRelative, VehicleMode from dronekit import Vehicle, LocationGlobalRelative, VehicleMode
from pymavlink import mavutil from pymavlink import mavutil
import os import os
@ -160,17 +160,17 @@ class ZiplineShot():
def handleButton(self, button, event): def handleButton(self, button, event):
if button == btn_msg.ButtonA and event == btn_msg.Press: if button == btn_msg.ButtonA and event == btn_msg.ClickRelease:
self.setupZipline() self.setupZipline()
if button == btn_msg.ButtonB and event == btn_msg.Press: if button == btn_msg.ButtonB and event == btn_msg.ClickRelease:
# Toggle between free look and spot lock # Toggle between free look and spot lock
if self.camPointing is FREE_LOOK: if self.camPointing is FREE_LOOK:
self.initCam(SPOT_LOCK) self.initCam(SPOT_LOCK)
else: else:
self.initCam(FREE_LOOK) self.initCam(FREE_LOOK)
if button == btn_msg.ButtonLoiter and event == btn_msg.Press: if button == btn_msg.ButtonLoiter and event == btn_msg.ClickRelease:
if self.pathHandler: if self.pathHandler:
self.pathHandler.togglePause() self.pathHandler.togglePause()
self.cruiseSpeed = self.pathHandler.cruiseSpeed self.cruiseSpeed = self.pathHandler.cruiseSpeed
@ -321,10 +321,24 @@ class ZiplineShot():
# pitch is in centidegrees # pitch is in centidegrees
self.camPitch * 100.0, self.camPitch * 100.0,
0.0, # roll 0.0, # roll
# yaw is in centidegrees 0, # self.camYaw * 100.0, # yaw is in centidegrees (Disabled by Matt for now due to ArduCopter master mount_control bug. Using condition_yaw instead)
self.camYaw * 100.0,
0 # save position 0 # save position
) )
self.vehicle.send_mavlink(msg)
msg = self.vehicle.message_factory.command_long_encode( # Using condition_yaw temporarily until mount_control yaw issue is fixed
0, 0, # target system, target component
mavutil.mavlink.MAV_CMD_CONDITION_YAW, # command
0, # confirmation
self.camYaw, # param 1 - target angle
YAW_SPEED, # param 2 - yaw speed
self.camDir, # param 3 - direction XXX
0.0, # relative offset
0, 0, 0 # params 5-7 (unused)
)
self.vehicle.send_mavlink(msg)
else: else:
# if we don't have a gimbal, just set CONDITION_YAW # if we don't have a gimbal, just set CONDITION_YAW
msg = self.vehicle.message_factory.command_long_encode( msg = self.vehicle.message_factory.command_long_encode(