3 Commits

Author SHA1 Message Date
Tristan McGinnis
0d239698fa one more attempt at manual zoom 2025-05-29 18:51:41 -06:00
Tristan McGinnis
998f3af33a attempting manual zoom functionality 2025-05-29 18:39:06 -06:00
Tristan McGinnis
b4ef261737 Merge pull request #14 from SHC-ASTRA/main
merge main into ptz-zoom
2025-05-29 18:30:07 -06:00
2 changed files with 50 additions and 3 deletions

View File

@@ -202,9 +202,14 @@ class PtzNode(Node):
await self.camera.send_single_axis_attitude_command(angle, axis) await self.camera.send_single_axis_attitude_command(angle, axis)
elif msg.control_mode == 3: elif msg.control_mode == 3:
zoom_level = msg.zoom_level zoom_direction = 0
self.get_logger().debug(f"Attempting absolute zoom: level={zoom_level}x") if msg.zoom_level > 0:
await self.camera.send_absolute_zoom_command(zoom_level) zoom_direction = 1 # Zoom in
elif msg.zoom_level < 0:
zoom_direction = -1 # Zoom out
self.get_logger().debug(f"Attempting manual zoom: direction={zoom_direction}")
await self.camera.send_manual_zoom_command(zoom_direction)
if hasattr(msg, 'stream_type') and hasattr(msg, 'stream_freq'): if hasattr(msg, 'stream_type') and hasattr(msg, 'stream_freq'):
if msg.stream_type > 0 and msg.stream_freq >= 0: if msg.stream_type > 0 and msg.stream_freq >= 0:

View File

@@ -64,6 +64,7 @@ class CommandID(Enum):
""" """
ROTATION_CONTROL = 0x07 ROTATION_CONTROL = 0x07
MANUAL_ZOOM = 0x05 # Added manual zoom command
ABSOLUTE_ZOOM = 0x08 ABSOLUTE_ZOOM = 0x08
ATTITUDE_ANGLES = 0x0E ATTITUDE_ANGLES = 0x0E
SINGLE_AXIS_CONTROL = 0x41 SINGLE_AXIS_CONTROL = 0x41
@@ -320,6 +321,47 @@ class SiyiGimbalCamera:
f"Sent absolute zoom command with level {zoom_level:.1f}x (original request: {original_requested_zoom:.1f}x)" f"Sent absolute zoom command with level {zoom_level:.1f}x (original request: {original_requested_zoom:.1f}x)"
) )
def _build_manual_zoom_packet(self, zoom_direction: int) -> bytes:
"""
Helper to build a manual zoom command packet.
:param zoom_direction: Direction to zoom: 1 for in, -1 for out, 0 for stop.
:return: Complete packet bytes ready to send.
"""
data_len = 1
packet = self._build_packet_header(CommandID.MANUAL_ZOOM, data_len)
# Convert the direction to a valid byte value:
# -1 (zoom out) -> 2
# 0 (stop zoom) -> 0
# 1 (zoom in) -> 1
if zoom_direction < 0:
direction_byte = 2 # Zoom out
elif zoom_direction > 0:
direction_byte = 1 # Zoom in
else:
direction_byte = 0 # Stop zoom
logger.debug(f"Manual zoom: input direction={zoom_direction}, mapped to byte={direction_byte}")
packet.append(direction_byte)
return self._finalize_packet(packet)
async def send_manual_zoom_command(self, zoom_direction: int) -> None:
"""
Send a manual zoom command (0x05) to the gimbal.
:param zoom_direction: 1 to zoom in, -1 to zoom out, 0 to stop zooming.
"""
if not self.is_connected or not self.writer:
raise RuntimeError(
"Socket is not connected or writer is None, cannot send manual zoom command."
)
packet = self._build_manual_zoom_packet(zoom_direction)
logger.debug(f"Manual zoom packet: {packet.hex()}")
self.writer.write(packet)
await self.writer.drain()
logger.debug(f"Sent manual zoom command with direction {zoom_direction}")
async def _read_packet(self): async def _read_packet(self):
if not self.reader: if not self.reader:
raise RuntimeError("Reader is not initialized.") raise RuntimeError("Reader is not initialized.")