Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Modify pan tilt function by getting pan/tilt range dynamically #181

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type CameraManagementApp struct {
config *ServiceConfig
pipelinesMap map[string]PipelineInfo
pipelinesMutex sync.RWMutex
panTiltMap map[string]PanTiltRange
panTiltMutex sync.RWMutex
fileServer http.Handler
}

Expand All @@ -28,6 +30,7 @@ func NewCameraManagementApp(service interfaces.ApplicationService) *CameraManage
lc: service.LoggingClient(),
config: &ServiceConfig{},
pipelinesMap: make(map[string]PipelineInfo),
panTiltMap: make(map[string]PanTiltRange),
}
}

Expand Down
39 changes: 28 additions & 11 deletions application-services/custom/camera-management/appcamera/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ import (
)

const (
relativeMoveCommand = "RelativeMove"
gotoPresetCommand = "GotoPreset"
streamUriCommand = "StreamUri"
profilesCommand = "Profiles"
getPresetsCommand = "GetPresets"

moveScaleX = 10
moveScaleY = 5
zoomScale = 1
relativeMoveCommand = "RelativeMove"
gotoPresetCommand = "GotoPreset"
streamUriCommand = "StreamUri"
profilesCommand = "Profiles"
getPresetsCommand = "GetPresets"
getConfigurationsCommand = "GetConfigurations"

zoomScale = 1
)

func (app *CameraManagementApp) getProfiles(deviceName string) (ProfilesResponse, error) {
Expand Down Expand Up @@ -60,8 +59,8 @@ func (app *CameraManagementApp) queryStreamUri(deviceName, profileToken string)
func (app *CameraManagementApp) doPTZ(deviceName, profileToken string, x, y, zoom float64) (dtosCommon.BaseResponse, error) {
trans := ptz.Vector{
PanTilt: &onvif.Vector2D{
X: x * moveScaleX,
Y: y * moveScaleY,
X: x,
Y: y,
},
}
if zoom != 0 {
Expand Down Expand Up @@ -97,6 +96,24 @@ func (app *CameraManagementApp) getPresets(deviceName string, profileToken strin
return pr, err
}

func (app *CameraManagementApp) getPTZConfiguration(deviceName string) (GetPTZConfigurationsResponse, error) {
cmd := &ptz.GetConfigurations{}

config, err := app.issueGetCommand(context.Background(), deviceName, getConfigurationsCommand, cmd)
if err != nil {
return GetPTZConfigurationsResponse{}, errors.Wrapf(err, "failed to issue get configurations command")
}

val := config.Event.Readings[0].ObjectValue
js, err := json.Marshal(val)
if err != nil {
return GetPTZConfigurationsResponse{}, errors.Wrapf(err, "failed to marshal configurations json object")
}
pr := GetPTZConfigurationsResponse{}
err = json.Unmarshal(js, &pr)
return pr, err
}

func (app *CameraManagementApp) gotoPreset(deviceName string, profile string, preset string) (dtosCommon.BaseResponse, error) {
cmd := &ptz.GotoPreset{
ProfileToken: (*onvif.ReferenceToken)(&profile),
Expand Down
42 changes: 36 additions & 6 deletions application-services/custom/camera-management/appcamera/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@ import (
)

const (
left = -1
right = 1
up = 1
down = -1
zoomIn = 1
zoomOut = -1
panTiltOffset = 0.05
zoomIn = 1
zoomOut = -1

webUIDistDir = "./web-ui/dist"

Expand Down Expand Up @@ -257,6 +254,18 @@ func (app *CameraManagementApp) ptzRoute(w http.ResponseWriter, req *http.Reques
var res dtosCommon.BaseResponse
var err error

panTiltRange, err := app.getPanTiltRange(deviceName)
if err != nil {
respondError(app.lc, w, http.StatusInternalServerError,
fmt.Sprintf("Failed to get PTZ configuration for the device %s: %v", deviceName, err))
return
}

right := panTiltOffset * panTiltRange.XRange
left := -right
up := panTiltOffset * panTiltRange.YRange
down := -up

switch action {
case "left":
res, err = app.doPTZ(deviceName, profileToken, left, 0, 0)
Expand Down Expand Up @@ -296,3 +305,24 @@ func (app *CameraManagementApp) ptzRoute(w http.ResponseWriter, req *http.Reques
app.lc.Error(err.Error())
}
}

func (app *CameraManagementApp) getPanTiltRange(deviceName string) (PanTiltRange, error) {
app.panTiltMutex.Lock()
defer app.panTiltMutex.Unlock()
panTiltRange, exists := app.panTiltMap[deviceName]
if !exists {
ptzConfigs, err := app.getPTZConfiguration(deviceName)
if err != nil {
return PanTiltRange{}, err
}

xRange := ptzConfigs.PTZConfiguration[0].PanTiltLimits.Range.XRange.Max - ptzConfigs.PTZConfiguration[0].PanTiltLimits.Range.XRange.Min
yRange := ptzConfigs.PTZConfiguration[0].PanTiltLimits.Range.YRange.Max - ptzConfigs.PTZConfiguration[0].PanTiltLimits.Range.YRange.Min
panTiltRange = PanTiltRange{
XRange: xRange,
YRange: yRange,
}
app.panTiltMap[deviceName] = panTiltRange
}
return panTiltRange, nil
}
48 changes: 45 additions & 3 deletions application-services/custom/camera-management/appcamera/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,59 @@ type GetPresetsResponse struct {
Name string `json:"Name"`
PTZPosition struct {
PanTilt struct {
Space string `json:"Space"`
X int `json:"X"`
Y int `json:"Y"`
Space string `json:"Space"`
X float64 `json:"X"`
Y float64 `json:"Y"`
} `json:"PanTilt"`
} `json:"PTZPosition"`
Token string `json:"Token"`
} `json:"Preset"`
}

type GetPTZConfigurationsResponse struct {
PTZConfiguration []struct {
DefaultAbsolutePantTiltPositionSpace string `json:"DefaultAbsolutePantTiltPositionSpace"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be 'DefaultAbsolutePanTiltPositionSpace'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a typo from the onvif specification end - https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah there are actually a decent amount of typos in the specs. its suprising.

DefaultAbsoluteZoomPositionSpace string `json:"DefaultAbsoluteZoomPositionSpace"`
DefaultContinuousPanTiltVelocitySpace string `json:"DefaultContinuousPanTiltVelocitySpace"`
DefaultContinuousZoomVelocitySpace string `json:"DefaultContinuousZoomVelocitySpace"`
DefaultPTZSpeed struct {
} `json:"DefaultPTZSpeed"`
DefaultPTZTimeout string `json:"DefaultPTZTimeout"`
DefaultRelativePanTiltTranslationSpace string `json:"DefaultRelativePanTiltTranslationSpace"`
DefaultRelativeZoomTranslationSpace string `json:"DefaultRelativeZoomTranslationSpace"`
PanTiltLimits struct {
Range struct {
URI string `json:"URI"`
XRange struct {
Max float64 `json:"Max"`
Min float64 `json:"Min"`
} `json:"XRange"`
YRange struct {
Max float64 `json:"Max"`
Min float64 `json:"Min"`
} `json:"YRange"`
} `json:"Range"`
} `json:"PanTiltLimits"`
Token string `json:"Token"`
ZoomLimits struct {
Range struct {
URI string `json:"URI"`
XRange struct {
Max float64 `json:"Max"`
Min float64 `json:"Min"`
} `json:"XRange"`
} `json:"Range"`
} `json:"ZoomLimits"`
} `json:"PTZConfiguration"`
}

type StartPipelineRequest struct {
ProfileToken string `json:"profile_token"`
PipelineName string `json:"pipeline_name"`
PipelineVersion string `json:"pipeline_version"`
}

type PanTiltRange struct {
XRange float64 `json:"XRange"`
YRange float64 `json:"YRange"`
}