Onvif PTZControl troubles - c#

I am using ONVIF protocol to control IP-cameras. Currently got stuck on zoom controlls with different cameras. I am using PTZBinding wsdl [https://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl], tried ContinuousMove and RelativeMove fucntions, but it apperars to work in different ways on different cameras.
ContinuousMove function takes velocity and timeout, RelativeMove function takes vector and velocity.
I. e., first camera works perfect with ContinousMove, but with RelativeMove it always apply maximum/minimus zoom, and vice versa with second camera.
Didn't try AbsoluteMove because I can't find way to get current zoom value.
Can't find universal method to control zoom on multiple cameras, asking for your help.
Any advices will be helpful, I will provide source code if needed.

Solved this problem by getting current zoom value with GetStatus and then controlling using AbsoluteMove. There is a source code:
public void StartZoom (Direction direction)
{
if (zoomEnabled_)
{
var ptzStatus_ = ptzClient_.GetStatus(profile_.token);
moveVector_.PanTilt = ptzStatus_.Position.PanTilt;
moveVector_.Zoom = ptzStatus_.Position.Zoom;
var zoomSpace = options_.Spaces.AbsoluteZoomPositionSpace;
var minZoom = zoomSpace[0].XRange.Min;
var maxZoom = zoomSpace[0].XRange.Max;
moveVelocity_.Zoom.x = 0;
if (direction.HasFlag(Direction.ZoomIn))
{
if (ptzStatus_.Position.Zoom.x + 1 / 20F <= maxZoom)
{
moveVelocity_.Zoom.x = velocityZoomIn_;
moveVector_.Zoom.x += 1 / 20F;
}
else
{
moveVector_.Zoom.x = maxZoom;
}
}
else if (direction.HasFlag(Direction.ZoomOut))
{
if (ptzStatus_.Position.Zoom.x - 1 / 20F >= minZoom)
{
moveVelocity_.Zoom.x = velocityZoomOut_;
moveVector_.Zoom.x -= 1 / 20F;
}
else
{
moveVector_.Zoom.x = minZoom;
}
}
ptzClient_.AbsoluteMove(profile_.token, moveVector_, moveVelocity_);
}
}

Related

Mouse.current.WarpCursorPosition only seems to be working correctly if moving left or up (not right or down)?

Here is a simple script to demonstrate the issue. This script should move the cursor to the left for 1 second and then back to the right for 1 second. However you'll see it just moves it to the left then stops. You can flip the order and try to move right first, but you'll notice that still won't work. I've also tested with moving up / down, moving up works as expected, moving down does not.
public class dumbtestscript : MonoBehaviour
{
void Start()
{
Mouse.current.WarpCursorPosition(new Vector3(123, 123));
StartCoroutine(MoveCursorLeftThenRightCoroutine());
}
IEnumerator MoveCursorLeftThenRightCoroutine()
{
float startTime = Time.time;
while (Time.time < startTime + 1)
{
Mouse.current.WarpCursorPosition(Input.mousePosition +
(Time.deltaTime * new Vector3(-0.1f, 0)));
yield return null;
}
while (Time.time < startTime + 2)
{
Mouse.current.WarpCursorPosition(Input.mousePosition +
(Time.deltaTime * new Vector3(0.1f, 0)));
yield return null;
}
}
}
Am I misunderstanding something about how WarpCursorPosition is supposed to work?
Any advice appreciated. Thanks.
Edit: Upon further inspection it may have to do with the vector being passed to WarpCursorPosition. For example regardless of whether we use this to move left:
Mouse.current.WarpCursorPosition(Input.mousePosition + new Vector3(-0.1f, 0));
or this:
Mouse.current.WarpCursorPosition(Input.mousePosition + new Vector3(-1f, 0));
it moves to the left at the same speed. So it seems anything between -0.1 and -1 is being rounded to -1. Conversely for going right everything between 0.1 and just under 1 is being rounded to 0 which would explain why it wasn't moving in the original.
So everything is getting round down to the nearest integer for some reason? Both Input.mousePosition and the Vector3 we are adding are both Vector3 and I thought could handle float numbers so not sure why things are being rounded down to ints, if thats whats happening?
The issue
So everything is getting round down to the nearest integer for some reason?
Most probably Yes!
WarpCursorPosition makes your actual system cursor jump to the given pixel coordinates.
While inside Unity the pixel space is always provided as float for many things and mainly for making direct calculations with it, the actual system cursor uses pixels (like everything that is actually happening on the screen) which are always full int values!
So, yes, it will always (not round but rather) floor your given input to the next int (full pixel). Basically what happens if you simply use
var x = (int) (Input.mousePosition.x - 0.1f);
=> You will see that x will be exactly Input.mousePosition.x - 1 since if e.g. the current Input.mousePosition.x was 230 then you get (int) 229.9f which is 229.
In the other direction though you get e.g. 230 + 0.1f so (int) 230.1f again simply is 230.
=> Your steps would need to at least be one full pixel!
Solution
So instead of constantly read the current Input.mousePosition which underlies the afore mentioned pixel coordinates rather use and update a local vector that does not:
IEnumerator MoveCursorLeftThenRightCoroutine()
{
// Store the current mousePosition as a Vector2
// This uses floats and is not restricted to full pixel jumps
var currentPosition = Input.mousePosition;
for(var passedTime = 0f; passedTime < 1; passedTime += Time.deltaTime)
{
// simply continously add to the float vector
currentPosition += Vector2.left * speedInPixelsPerSecond * Time.deltaTime;
// Using that float vector as input may in some frames cause no movement where the clamp results
// still in the same pixel but it will catch up as soon as the vector was increased/reduced enough
Mouse.current.WarpCursorPosition(currentPosition);
yield return nnull;
}
for(var passedTime = 0f; passedTime < 1; passedTime += Time.deltaTime)
{
currentPosition += Vector2.right * speedInPixelsPerSecond * Time.deltaTime;
Mouse.current.WarpCursorPosition(currentPosition);
yield return null;
}
}
In general for the new Input system I would rather use Mouse.current.position instead of Input.mousePosition.
I don't have any experience using WarpCursorPosition but when I was experimenting to answer this thread, I felt it's not consistent & would like to advice not to use it.
Code
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
public class Q69189325 : MonoBehaviour
{
private void Start()
{
Mouse.current.WarpCursorPosition(Input.mousePosition);
StartCoroutine(MoveLogicCrt());
}
IEnumerator MoveLogicCrt()
{
yield return MoveCursorToDirectionCrt(Vector3.left, 150, 5);
yield return null;
yield return MoveCursorToDirectionCrt(Vector3.right, 350, 5);
}
private IEnumerator MoveCursorToDirectionCrt(Vector3 direction, float speed, float movementTime)
{
float startTime = Time.time;
while(Time.time < startTime + movementTime)
{
Vector2 newMousePosition = Input.mousePosition + (Time.deltaTime * direction * speed);
Mouse.current.WarpCursorPosition(newMousePosition);
yield return null;
}
}
}
Note:
For some reason when I put the same speed to both left & right it doesn't move right which was weird.
Execution Overview
https://gfycat.com/eventhriftyannelida
Happy coding!

Why is my Unity CharController Dash function not propelling me in the correct direction, despite seemingly correct values..?

I've been adding some extra movement techniques to a Character Controller in Unity3D. Currently, I'm working on a dash function, but currently, it's behaving very weirdly.
Dashing Backwards, Works as I want it to
Dashing Forwards, Doesn't work as I want it to...
As you can see in the first Image, the silhouttes being essentially where I've dashed, I'm moving in a straight line backwards, as represented by the Green Arrows. However in the second Image, the silhouttes go diagonally to the top left, instead of straight ahead. As represented by the yellow arrows, this time green showing where I want and expect it to go.
private void DashFuncW()
{
if (Time.realtimeSinceStartup - timeOfFirstButton < DoublePressSpan && Input.GetKeyDown(KeyCode.W) && firstButtonPressed)
{
Dash(transform.forward);
firstButtonPressed = false;
timeOfFirstButton = 0f;
}
if (Input.GetKeyDown(KeyCode.W))
{
timeOfFirstButton = Time.realtimeSinceStartup;
firstButtonPressed = true;
}
}
private void DashFuncS()
{
if (Time.realtimeSinceStartup - timeOfFirstButton < DoublePressSpan && Input.GetKeyDown(KeyCode.S) && firstButtonPressed)
{
Dash(-transform.forward);
firstButtonPressed = false;
timeOfFirstButton = 0f;
}
if (Input.GetKeyDown(KeyCode.S))
{
timeOfFirstButton = Time.realtimeSinceStartup;
firstButtonPressed = true;
}
}
These 2 Functions get the double-tap style input and call the actual Dash function while passing it the Direction it needs to go to. As you can see, both use 'transform.forward', just the S key function uses '-transform.forward'. This is what confuses me the most. If it can go one way fine, why can't it go the other way, especially when they're the exact mirror values of one another.
private void Dash(Vector3 Direction)
{
GameObject WarpClone = Instantiate(gameObject);
WarpClone.transform.position = transform.position;
Destroy(WarpClone.GetComponent<CharacterMovement>());
Destroy(WarpClone.GetComponent<CharacterController>());
Destroy(WarpClone.GetComponent<Animator>());
foreach (Transform child in WarpClone.GetComponentsInChildren<Transform>())
{
Destroy(child.GetComponent<Collider>());
SkinnedMeshRenderer[] SMRs = WarpClone.GetComponentsInChildren<SkinnedMeshRenderer>();
MeshRenderer[] MRs = WarpClone.GetComponentsInChildren<MeshRenderer>();
foreach (SkinnedMeshRenderer SMR in SMRs)
{
SMR.material = warpMaterial;
}
foreach (MeshRenderer MR in MRs)
{
MR.material = warpMaterial;
}
}
Destroy(WarpClone, 100f); //100 Seconds for testing
CC.Move(Direction * dashStrength);
}
And this function is the one that creates the silhouettes and actually moves the player. If it matters any, 'dashStrength' is equal to 3, and all 3 of these functions are in a bigger 'Movement' function which moves the character based on Axis input, which runs in the Update() call, as FixedUpdate makes for jittery movement. I cannot for the life of me find out why it won't work properly. I'd appreciate any help :/
Well, if anyone ends up with the same problem somehow, I ended up fixing it by disabling the character controller and changing transform.position like so:
CC.enabled = false;
transform.position = transform.position + (Direction * dashStrength);
CC.enabled = true;

Unity: How do I restrict the character's position or velocity to an exact number, making it unable to go past that point?

I'm still working on "perfect" ladder movement, and what I was able to come up with is a way to calculate the exact, specific distance the character needs to move while it is on the ladder to reach the point with which it will collide perfectly with the ground above the ladder.
I know this value is exactly specific because I allow my character to land on the ladder landing when the game starts (position.y = 3.6235), and when I print the movement value in the console I get exactly 3.6235.
I'm not sure that I'm implementing this correctly in code, though, as I've noticed that this value is still barely above "0" in the console once my character is all the way up the ladder. Is Mathf.Clamp() not the correct function to limit movement, or maybe I'm using it incorrectly?
public void ClimbUpLadder(ref Vector3 deltaMovement)
{
float rayLength = raycastOrigins.centerRayLength * 2;
RaycastHit2D[] hits = Physics2D.RaycastAll(new Vector2(raycastOrigins.center.x + deltaMovement.x,
(raycastOrigins.center.y - raycastOrigins.centerRayLength + skinWidth) + deltaMovement.y), Vector2.up,
rayLength, climbMask);
Debug.DrawRay(new Vector2(raycastOrigins.center.x + deltaMovement.x,
(raycastOrigins.center.y - raycastOrigins.centerRayLength + skinWidth) + deltaMovement.y), Vector2.up * rayLength, Color.green);
for (int i = 0; i < hits.Length; i++)
{
if (hits[i])
{
if (hits[i].collider.tag == "Ladder")
{
IsClimbingLadder = true;
}
if (i >= 1 && hits[i].collider.tag == "platformOneWay")
{
//This gives us the exact distance needed to finish climbing
GameObject platform = hits[i].collider.gameObject;
Transform platformTransform = platform.GetComponent<Transform>();
float finalMoveDistance = (platformTransform.position.y - characterTransform.position.y) + platformTransform.position.y;
deltaMovement.y = Mathf.Clamp(deltaMovement.y, 0, finalMoveDistance);
print(finalMoveDistance);
}
}
}
}
Unfortunately, after I set deltaMovement.y to this value it says that finalMoveDistance is around .9 or 1.0, so I still move slightly too far up the ladder. Do you think setting the character's transform.position.y directly is the best way to smooth out the movement? My goal is to eliminate any bounce when transitioning from climbing the ladder to walking on the ground again.
I think you're making a mistake here:
float finalMoveDistance = (platformTransform.position.y - characterTransform.position.y) + platformTransform.position.y;
Why do you add the platformTransform twice?
Try this:
float finalMoveDistance = (platformTransform.position.y - characterTransform.position.y);

How to draw a 2D graph on Canvas in Unity 5

I need to draw a graph for my decibel app that I am making with Unity. The solution below works but is not as exact as my employer would like. Could I make this graph look more professional and exact? Basically I want the lines to be of equal width and prevent the line from going almost invisible like in the following pic: http://puu.sh/qjSvO/a51c11cef5.png
I was thinking about making a 2D texture and using SetPixel, but I am not sure if that is the correct way.
The graph is drawn on a canvas as part of an scalable UI.
public class Graph : MonoBehaviour {
public float graphWidth;
public float graphHeight;
LineRenderer newLineRenderer;
List<int> decibels;
int vertexAmount = 50;
float xInterval;
GameObject parentCanvas;
// Use this for initialization
void Start ()
{
parentCanvas = GameObject.Find("Canvas");
graphWidth = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.width;
graphHeight = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.height;
newLineRenderer = GetComponentInChildren<LineRenderer>();
newLineRenderer.SetVertexCount(vertexAmount);
xInterval = graphWidth / vertexAmount;
}
//Display 1 minute of data or as much as there is.
public void Draw(List<int> decibels)
{
if (decibels.Count == 0)
return;
float x = 0;
for (int i = 0; i < vertexAmount && i < decibels.Count; i++)
{
int _index = decibels.Count - i - 1;
float y = decibels[_index] * (graphHeight/130); //(Divide grapheight with the maximum value of decibels.
x = i * xInterval;
newLineRenderer.SetPosition(i, new Vector3(x - graphWidth / 2 , y - graphHeight / 2 , 0));
}
}
}
Using the editor, you can "cut" sprites into nine pieces, so that there is a texture for each side, a texture for each corner and a texture to fill it in. I would recommend using that to make it look good if you want it so. It is some time since i used it myself, but maybe you can find information on the Unity manual.

How to do image collision in C# for Windows Phone 8 using Windows Phone App?

I have 2 images(bar and greenBall1). bar can be move up and down depends on the user response. While, greenBall1 is moving around the screen. I want to do an image collision if both the images touch each other, greenBall1 will change its velocity. The codes that I have for greenBall1 are as below.
private void OnUpdate(object sender, object e)
{
Canvas.SetLeft(this.GreenBall1, this.greenBallVelocityX + Canvas.GetLeft(this.GreenBall1));
Canvas.SetTop(this.GreenBall1, this.greenBallVelocityY + Canvas.GetTop(this.GreenBall1));
var greenBallPositionX1 = Canvas.GetLeft(this.GreenBall1);
var greenBallPositionY1 = Canvas.GetTop(this.GreenBall1);
var maximumGreenBallX = ActualWidth - this.GreenBall1.ActualWidth;
var maximumGreenBallY = 400 - this.GreenBall1.ActualHeight; //Improvise: Instead of 360, get maximum height of canvas
if (greenBallPositionX1 > maximumGreenBallX || greenBallPositionX1 < 0)
{
this.greenBallVelocityX *= -1;
}
if (greenBallPositionY1 > maximumGreenBallY || greenBallPositionY1 < 0)
{
this.greenBallVelocityY *= -1;
}
}
I don't see a reference to the bar object in your code. But the detection of the collision is much easier than the physics of handling the collision. There are several schools of thought to something as simple as Pong collision, and the way you choose to handle it depends on the gameplay you want.
Here is an easy way to detect and handle the collision, simply by negating the X velocity just as you are handling the wall collisions:
if(greenBallPositionX1 < leftBar.X || greenBallPositionX1 > rightBar.X)
{
this.greenBallVelocityX *= -1;
}
Keep in mind you might also have to take into account the width of the bar or the ball depending on where the coordinate is in relation to the image. For example:
if(greenBallPositionX1 < (leftBar.X + leftBar.Width) || greenBallPositionX1 > rightBar.X)
{
this.greenBallVelocityX *= -1;
}
You may also want to at this point move the ball away from the paddle one step to avoid the collision being detected more than once.
Hopefully this answers what you were asking, but if you were looking for a more complex reaction to the collision detection, then you may want to check out the following discussion on Pong type collisions here.
i think this might help you ....
.
Rectangle ballRect = new Rectangle((int)ballposition.X, (int)ballposition.Y, ballsprite.Width, ballsprite.Height);
Rectangle handRect = new Rectangle((int)paddlePosition.X, (int)paddlePosition.Y, paddleSprite.Width, paddleSprite.Height/2);
if (ballRect.Intersects(handRect))
{
// Increase ball speed
ballSpeed.Y += 50;
if (ballSpeed.X < 0)
ballSpeed.X -= 50;
else
ballSpeed.X += 50;
// Send ball back up the screen
ballSpeed.Y *= -1;
}
in this whenever the ball will collide with hand it will increase its speed and change its direction i think that is the think you are looking for as it is also a rectangular collision.
make a class which will give you value that wether two rects will collide or not
public bool Intersects(Rect r1,Rect r2)
{
r1.Intersect(r2);
if(r1.IsEmpty)
{
return false;
}
else
{
return true;
}
}
then you can use
if(Intersects(r1,r2))
{
MessageBox.Show("Collison Detected");
}

Categories