Skip to content

Commit

Permalink
Merge pull request #307 from mavlink/pr-update-proto-and-version
Browse files Browse the repository at this point in the history
Update proto and mavsdk_server version
  • Loading branch information
julianoes authored Feb 11, 2021
2 parents e026f87 + bb0e0ed commit 5c2845a
Show file tree
Hide file tree
Showing 7 changed files with 1,050 additions and 96 deletions.
2 changes: 1 addition & 1 deletion MAVSDK_SERVER_VERSION
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
v0.35.1
v0.36.0



289 changes: 288 additions & 1 deletion mavsdk/gimbal.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,172 @@ def __str__(self):
return self.name


class ControlMode(Enum):
"""
Control mode
Values
------
NONE
Indicates that the component does not have control over the gimbal
PRIMARY
To take primary control over the gimbal
SECONDARY
To take secondary control over the gimbal
"""


NONE = 0
PRIMARY = 1
SECONDARY = 2

def translate_to_rpc(self):
if self == ControlMode.NONE:
return gimbal_pb2.CONTROL_MODE_NONE
if self == ControlMode.PRIMARY:
return gimbal_pb2.CONTROL_MODE_PRIMARY
if self == ControlMode.SECONDARY:
return gimbal_pb2.CONTROL_MODE_SECONDARY

@staticmethod
def translate_from_rpc(rpc_enum_value):
""" Parses a gRPC response """
if rpc_enum_value == gimbal_pb2.CONTROL_MODE_NONE:
return ControlMode.NONE
if rpc_enum_value == gimbal_pb2.CONTROL_MODE_PRIMARY:
return ControlMode.PRIMARY
if rpc_enum_value == gimbal_pb2.CONTROL_MODE_SECONDARY:
return ControlMode.SECONDARY

def __str__(self):
return self.name


class ControlStatus:
"""
Control status
Parameters
----------
control_mode : ControlMode
Control mode (none, primary or secondary)
sysid_primary_control : int32_t
Sysid of the component that has primary control over the gimbal (0 if no one is in control)
compid_primary_control : int32_t
Compid of the component that has primary control over the gimbal (0 if no one is in control)
sysid_secondary_control : int32_t
Sysid of the component that has secondary control over the gimbal (0 if no one is in control)
compid_secondary_control : int32_t
Compid of the component that has secondary control over the gimbal (0 if no one is in control)
"""



def __init__(
self,
control_mode,
sysid_primary_control,
compid_primary_control,
sysid_secondary_control,
compid_secondary_control):
""" Initializes the ControlStatus object """
self.control_mode = control_mode
self.sysid_primary_control = sysid_primary_control
self.compid_primary_control = compid_primary_control
self.sysid_secondary_control = sysid_secondary_control
self.compid_secondary_control = compid_secondary_control

def __equals__(self, to_compare):
""" Checks if two ControlStatus are the same """
try:
# Try to compare - this likely fails when it is compared to a non
# ControlStatus object
return \
(self.control_mode == to_compare.control_mode) and \
(self.sysid_primary_control == to_compare.sysid_primary_control) and \
(self.compid_primary_control == to_compare.compid_primary_control) and \
(self.sysid_secondary_control == to_compare.sysid_secondary_control) and \
(self.compid_secondary_control == to_compare.compid_secondary_control)

except AttributeError:
return False

def __str__(self):
""" ControlStatus in string representation """
struct_repr = ", ".join([
"control_mode: " + str(self.control_mode),
"sysid_primary_control: " + str(self.sysid_primary_control),
"compid_primary_control: " + str(self.compid_primary_control),
"sysid_secondary_control: " + str(self.sysid_secondary_control),
"compid_secondary_control: " + str(self.compid_secondary_control)
])

return f"ControlStatus: [{struct_repr}]"

@staticmethod
def translate_from_rpc(rpcControlStatus):
""" Translates a gRPC struct to the SDK equivalent """
return ControlStatus(

ControlMode.translate_from_rpc(rpcControlStatus.control_mode),


rpcControlStatus.sysid_primary_control,


rpcControlStatus.compid_primary_control,


rpcControlStatus.sysid_secondary_control,


rpcControlStatus.compid_secondary_control
)

def translate_to_rpc(self, rpcControlStatus):
""" Translates this SDK object into its gRPC equivalent """




rpcControlStatus.control_mode = self.control_mode.translate_to_rpc()





rpcControlStatus.sysid_primary_control = self.sysid_primary_control





rpcControlStatus.compid_primary_control = self.compid_primary_control





rpcControlStatus.sysid_secondary_control = self.sysid_secondary_control





rpcControlStatus.compid_secondary_control = self.compid_secondary_control





class GimbalResult:
"""
Result type.
Expand Down Expand Up @@ -243,6 +409,40 @@ async def set_pitch_and_yaw(self, pitch_deg, yaw_deg):
raise GimbalError(result, "set_pitch_and_yaw()", pitch_deg, yaw_deg)


async def set_pitch_rate_and_yaw_rate(self, pitch_rate_deg_s, yaw_rate_deg_s):
"""
Set gimbal angular rates around pitch and yaw axes.
This sets the desired angular rates around pitch and yaw axes of a gimbal.
Will return when the command is accepted, however, it might
take the gimbal longer to actually reach the angular rate.
Parameters
----------
pitch_rate_deg_s : float
Angular rate around pitch axis in degrees/second (negative downward)
yaw_rate_deg_s : float
Angular rate around yaw axis in degrees/second (positive is clock-wise)
Raises
------
GimbalError
If the request fails. The error contains the reason for the failure.
"""

request = gimbal_pb2.SetPitchRateAndYawRateRequest()
request.pitch_rate_deg_s = pitch_rate_deg_s
request.yaw_rate_deg_s = yaw_rate_deg_s
response = await self._stub.SetPitchRateAndYawRate(request)


result = self._extract_result(response)

if result.result is not GimbalResult.Result.SUCCESS:
raise GimbalError(result, "set_pitch_rate_and_yaw_rate()", pitch_rate_deg_s, yaw_rate_deg_s)


async def set_mode(self, gimbal_mode):
"""
Set gimbal mode.
Expand Down Expand Up @@ -314,4 +514,91 @@ async def set_roi_location(self, latitude_deg, longitude_deg, altitude_m):

if result.result is not GimbalResult.Result.SUCCESS:
raise GimbalError(result, "set_roi_location()", latitude_deg, longitude_deg, altitude_m)



async def take_control(self, control_mode):
"""
Take control.
There can be only two components in control of a gimbal at any given time.
One with "primary" control, and one with "secondary" control. The way the
secondary control is implemented is not specified and hence depends on the
vehicle.
Components are expected to be cooperative, which means that they can
override each other and should therefore do it carefully.
Parameters
----------
control_mode : ControlMode
Control mode (primary or secondary)
Raises
------
GimbalError
If the request fails. The error contains the reason for the failure.
"""

request = gimbal_pb2.TakeControlRequest()

request.control_mode = control_mode.translate_to_rpc()


response = await self._stub.TakeControl(request)


result = self._extract_result(response)

if result.result is not GimbalResult.Result.SUCCESS:
raise GimbalError(result, "take_control()", control_mode)


async def release_control(self):
"""
Release control.
Release control, such that other components can control the gimbal.
Raises
------
GimbalError
If the request fails. The error contains the reason for the failure.
"""

request = gimbal_pb2.ReleaseControlRequest()
response = await self._stub.ReleaseControl(request)


result = self._extract_result(response)

if result.result is not GimbalResult.Result.SUCCESS:
raise GimbalError(result, "release_control()")


async def control(self):
"""
Subscribe to control status updates.
This allows a component to know if it has primary, secondary or
no control over the gimbal. Also, it gives the system and component ids
of the other components in control (if any).
Yields
-------
control_status : ControlStatus
Control status
"""

request = gimbal_pb2.SubscribeControlRequest()
control_stream = self._stub.SubscribeControl(request)

try:
async for response in control_stream:



yield ControlStatus.translate_from_rpc(response.control_status)
finally:
control_stream.cancel()
Loading

0 comments on commit 5c2845a

Please sign in to comment.