[英]Python-ONVIF PTZ control -- Absolute and Relative Move
I am developing an application in Python to control ONVIF-compatible cameras.我正在用 Python 开发一个应用程序来控制兼容 ONVIF 的相机。
Software: Debian Wheezy, Python 2.7, Quatanium python-onvif client软件:Debian Wheezy、Python 2.7、Quatanium python-onvif 客户端
Hardware: Raspberry Pi 2 B, IP camera on local router, wifi/VNC for development硬件:Raspberry Pi 2 B,本地路由器上的 IP 摄像头,用于开发的 wifi/VNC
The required PTZ functions include Absolute Move, Relative Move, Continuous Move, Stop and using Preset positions.所需的 PTZ 功能包括绝对移动、相对移动、连续移动、停止和使用预设位置。 With the extracted test code below, I have all of that working except Absolute and Relative Moves.
使用下面提取的测试代码,除了绝对和相对移动之外,我可以完成所有工作。 All of this code executes without any errors but the camera does not move for the Absolute or Relative Moves.
所有这些代码都没有任何错误地执行,但相机不会因绝对或相对移动而移动。 I hope someone can suggest the problem with those two functions.
我希望有人可以提出这两个功能的问题。 The example is a bit long but I have tried to include enough code to show the contrast between working and non-working (with upper-case comments) portions for reference and test.
这个例子有点长,但我试图包含足够的代码来显示工作和非工作(带有大写注释)部分之间的对比,以供参考和测试。
A test sketch:测试草图:
#!/usr/bin/python
#-------------------------------------------------------------------------------
#Test of Python and Quatanium Python-ONVIF with NETCAT camera PT-PTZ2087
#ONVIF Client implementation is in Python
#For IP control of PTZ, the camera should be compliant with ONVIF Profile S
#The PTZ2087 reports it is ONVIF 2.04 but is actually 2.4 (Netcat said text not changed after upgrade)
#------------------------------------------------------------------------------
import onvifconfig
if __name__ == '__main__':
#Do all setup initializations
ptz = onvifconfig.ptzcam()
#*****************************************************************************
# IP camera motion tests
#*****************************************************************************
print 'Starting tests...'
#Set preset
ptz.move_pan(1.0, 1) #move to a new home position
ptz.set_preset('home')
# move right -- (velocity, duration of move)
ptz.move_pan(1.0, 2)
# move left
ptz.move_pan(-1.0, 2)
# move down
ptz.move_tilt(-1.0, 2)
# Move up
ptz.move_tilt(1.0, 2)
# zoom in
ptz.zoom(8.0, 2)
# zoom out
ptz.zoom(-8.0, 2)
#Absolute pan-tilt (pan position, tilt position, velocity)
#DOES NOT RESULT IN CAMERA MOVEMENT
ptz.move_abspantilt(-1.0, 1.0, 1.0)
ptz.move_abspantilt(1.0, -1.0, 1.0)
#Relative move (pan increment, tilt increment, velocity)
#DOES NOT RESULT IN CAMERA MOVEMENT
ptz.move_relative(0.5, 0.5, 8.0)
#Get presets
ptz.get_preset()
#Go back to preset
ptz.goto_preset('home')
exit()
The referenced class:引用的类:
#*****************************************************************************
#IP Camera control
#Control methods:
# rtsp video streaming via OpenCV for frame capture
# ONVIF for PTZ control
# ONVIF for setup selections
#
# Starting point for this code was from:
# https://github.com/quatanium/python-onvif
#*****************************************************************************
import sys
sys.path.append('/usr/local/lib/python2.7/dist-packages/onvif')
from onvif import ONVIFCamera
from time import sleep
class ptzcam():
def __init__(self):
print 'IP camera initialization'
#Several cameras that have been tried -------------------------------------
#Netcat camera (on my local network) Port 8899
self.mycam = ONVIFCamera('192.168.1.10', 8899, 'admin', 'admin', '/etc/onvif/wsdl/')
#This is a demo camera that anyone can use for testing
#Toshiba IKS-WP816R
#self.mycam = ONVIFCamera('67.137.21.190', 80, 'toshiba', 'security', '/etc/onvif/wsdl/')
print 'Connected to ONVIF camera'
# Create media service object
self.media = self.mycam.create_media_service()
print 'Created media service object'
print
# Get target profile
self.media_profile = self.media.GetProfiles()[0]
# Use the first profile and Profiles have at least one
token = self.media_profile._token
#PTZ controls -------------------------------------------------------------
print
# Create ptz service object
print 'Creating PTZ object'
self.ptz = self.mycam.create_ptz_service()
print 'Created PTZ service object'
print
#Get available PTZ services
request = self.ptz.create_type('GetServiceCapabilities')
Service_Capabilities = self.ptz.GetServiceCapabilities(request)
print 'PTZ service capabilities:'
print Service_Capabilities
print
#Get PTZ status
status = self.ptz.GetStatus({'ProfileToken':token})
print 'PTZ status:'
print status
print 'Pan position:', status.Position.PanTilt._x
print 'Tilt position:', status.Position.PanTilt._y
print 'Zoom position:', status.Position.Zoom._x
print 'Pan/Tilt Moving?:', status.MoveStatus.PanTilt
print
# Get PTZ configuration options for getting option ranges
request = self.ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = self.media_profile.PTZConfiguration._token
ptz_configuration_options = self.ptz.GetConfigurationOptions(request)
print 'PTZ configuration options:'
print ptz_configuration_options
print
self.requestc = self.ptz.create_type('ContinuousMove')
self.requestc.ProfileToken = self.media_profile._token
self.requesta = self.ptz.create_type('AbsoluteMove')
self.requesta.ProfileToken = self.media_profile._token
print 'Absolute move options'
print self.requesta
print
self.requestr = self.ptz.create_type('RelativeMove')
self.requestr.ProfileToken = self.media_profile._token
print 'Relative move options'
print self.requestr
print
self.requests = self.ptz.create_type('Stop')
self.requests.ProfileToken = self.media_profile._token
self.requestp = self.ptz.create_type('SetPreset')
self.requestp.ProfileToken = self.media_profile._token
self.requestg = self.ptz.create_type('GotoPreset')
self.requestg.ProfileToken = self.media_profile._token
print 'Initial PTZ stop'
print
self.stop()
#Stop pan, tilt and zoom
def stop(self):
self.requests.PanTilt = True
self.requests.Zoom = True
print 'Stop:'
#print self.requests
print
self.ptz.Stop(self.requests)
print 'Stopped'
#Continuous move functions
def perform_move(self, timeout):
# Start continuous move
ret = self.ptz.ContinuousMove(self.requestc)
print 'Continuous move completed', ret
# Wait a certain time
sleep(timeout)
# Stop continuous move
self.stop()
sleep(2)
print
def move_tilt(self, velocity, timeout):
print 'Move tilt...', velocity
self.requestc.Velocity.PanTilt._x = 0.0
self.requestc.Velocity.PanTilt._y = velocity
self.perform_move(timeout)
def move_pan(self, velocity, timeout):
print 'Move pan...', velocity
self.requestc.Velocity.PanTilt._x = velocity
self.requestc.Velocity.PanTilt._y = 0.0
self.perform_move(timeout)
def zoom(self, velocity, timeout):
print 'Zoom...', velocity
self.requestc.Velocity.Zoom._x = velocity
self.perform_move(timeout)
#Absolute move functions --NO ERRORS BUT CAMERA DOES NOT MOVE
def move_abspantilt(self, pan, tilt, velocity):
self.requesta.Position.PanTilt._x = pan
self.requesta.Position.PanTilt._y = tilt
self.requesta.Speed.PanTilt._x = velocity
self.requesta.Speed.PanTilt._y = velocity
print 'Absolute move to:', self.requesta.Position
print 'Absolute speed:',self.requesta.Speed
ret = self.ptz.AbsoluteMove(self.requesta)
print 'Absolute move pan-tilt requested:', pan, tilt, velocity
sleep(2.0)
print 'Absolute move completed', ret
print
#Relative move functions --NO ERRORS BUT CAMERA DOES NOT MOVE
def move_relative(self, pan, tilt, velocity):
self.requestr.Translation.PanTilt._x = pan
self.requestr.Translation.PanTilt._y = tilt
self.requestr.Speed.PanTilt._x = velocity
ret = self.requestr.Speed.PanTilt._y = velocity
self.ptz.RelativeMove(self.requestr)
print 'Relative move pan-tilt', pan, tilt, velocity
sleep(2.0)
print 'Relative move completed', ret
print
#Sets preset set, query and and go to
def set_preset(self, name):
self.requestp.PresetName = name
self.requestp.PresetToken = '1'
self.preset = self.ptz.SetPreset(self.requestp) #returns the PresetToken
print 'Set Preset:'
print self.preset
print
def get_preset(self):
self.ptzPresetsList = self.ptz.GetPresets(self.requestc)
print 'Got preset:'
print self.ptzPresetsList[0]
print
def goto_preset(self, name):
self.requestg.PresetToken = '1'
self.ptz.GotoPreset(self.requestg)
print 'Going to Preset:'
print name
print
@Ottavio, Sorry that I did not make it clear that the camera I used for this test, a Netcat PT-PTZ2084XM-A reported via ONVIF query that it did support Absolute and Relative moves. @Ottavio,抱歉,我没有明确说明我用于此测试的摄像头 Netcat PT-PTZ2084XM-A 通过 ONVIF 查询报告它确实支持绝对和相对移动。 I have subsequently verified via the onvif.org site that this camera has not been tested and verified to meet onvif standards.
我随后通过 onvif.org 网站确认该相机尚未经过测试和验证,符合 onvif 标准。 I also have verified that the above code does work correctly with a Amcrest IP2M-841B ptz camera.
我还验证了上述代码与 Amcrest IP2M-841B ptz 摄像机一起正常工作。 The upshot of all of this is to never trust the claim that a camera is ONVIF 2.x compatible without testing it.
所有这一切的结果是永远不要相信未经测试的相机与 ONVIF 2.x 兼容的说法。 Even the Amcrest has problems with both ONVIF and cgi commands for zoom.
即使是 Amcrest 也有 ONVIF 和 cgi 命令的缩放问题。 Neither Netcat nor Amcrest have been very helpful in resolving these technical problems.
Netcat 和 Amcrest 在解决这些技术问题方面都没有很大帮助。
AbsoluteMake
and RelativeMove
in the Profile S specifications are CONDITIONAL MANDATORY
, thus it is not guaranteed a-priori that they are supported. Profile S 规范中的
AbsoluteMake
和RelativeMove
是CONDITIONAL MANDATORY
,因此不能保证先验地支持它们。
You need to check the camera's features.您需要检查相机的功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.