Xbox Controller both thumb sticks not changing value, using Xinput - c++

I am using the Xinput API, but I am having trouble with the following bit of code. My assumption is that the definition of R/LX and R/LY, should dynamically change as its called again and again, but the value for the position of the thumb stick is arbitrarily set to -13108, so the normalized magnitude of X and Y is -.707, and the normalized magnitude is ~.428. I keep trying to move the control stick but the values won't change. Any ideas? Am I misunderstanding the Xinput API? Does the struct controller state make sense? The code is below is just for the left stick, but the right stick is very similar.
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
struct CONTROLLER_STATE
{
XINPUT_STATE state;
bool bConnected;
};
CONTROLLER_STATE g_Controllers[4];
while(1)
{
//...
XINPUT_STATE state = g_Controllers[1].state;
float LX = state.Gamepad.sThumbLX;
float LY = state.Gamepad.sThumbLY;
//determine how far the controller is pushed
float magnitude = sqrt(LX*LX + LY*LY);
//determine the direction the controller is pushed
float normalizedLX = LX / magnitude;
float normalizedLY = LY / magnitude;
cout << " Y " << LY << endl;
float normalizedMagnitude = 0;
//check if the controller is outside a circular dead zone
if (magnitude > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
//clip the magnitude at its expected maximum value
if (magnitude > 32767) magnitude = 32767;
//adjust magnitude relative to the end of the dead zone
magnitude -= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
//optionally normalize the magnitude with respect to its expected range
//giving a magnitude value of 0.0 to 1.0
normalizedMagnitude = magnitude / (32767 - XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
cout << "normalizedMagnitude " << normalizedMagnitude;
}
else //if the controller is in the deadzone zero out the magnitude
{
magnitude = 0.0;
normalizedMagnitude = 0.0;
}
}

You have normalised a state, and it is rather empty. I would assume that you are atleast calling XInputGetState() in your bool function bConnected, however this would probably be called once and hence values would remain the same. Therefore, either in your main, or in your associated function displayed above, you should call the getstate function once, first line in the while loop, so as it runs, the state is updated continously.

Related

Performing a cubic fit to a set of four points to extrapolate a "local" path, Or working alternatives?

Problem: Generate a extrapolated local path which provides path points ahead of the max FOV.
Situation: Having a car move round an unknown looped track of varying shape using a field of view which is limited so can only provide reliably 3 points ahead of the car and the car's current position. Note for more information the tack is defined by cone gates and the information provided about the locations of said gates is 2D (x,y).
Background: I have successfully generated a vector of mid points between gates however wish to generate an extrapolated path for the motion control algorithm to use. the format of this path needs to be a sequence of PathPoint (s) which contain (x,y velocity, gravity). note that gravity is just used to cap the maximum acceleration and is not important to the situation nor is velocity as the post is only concerned about generating respective (x,y) co-ordinates.
Attempted Solution Methodology: To fit two cubic functions for X positions and Y positions using the set of four points i.e f(x) and g(y). These functions should then be provided as the desired (f(x),g(y)) positions as we vary the look ahead distance to supply 20 path points.
Question: I do not believe this method to be correct both in theory and in implementation can anyone think of an easy/simple methodology to achieve the out come of having position in x axis and position in y axis to be the functions from the argument of overall distance from the car?
double PathPlanningClass::squared(double arg)
{
return arg*arg;
}
double PathPlanningClass::cubed(double arg)
{
return arg*arg*arg;
}
//https://eigen.tuxfamily.org/dox/group__TutorialLinearAlgebra.html
void PathPlanningClass::Coeffs()
{
Eigen::Matrix4f Aone;
Eigen::Vector4f bone;
Aone << _x, squared(_x), cubed(_x), _midpoints[0].getX(), squared(_midpoints[0].getX()), cubed(_midpoints[0].getX()), _midpoints[1].getX(), squared(_midpoints[1].getX()), cubed(_midpoints[1].getX()), _midpoints[_midpoints.size()-1].getX(), squared(_midpoints[_midpoints.size()-1].getX()), cubed(_midpoints[_midpoints.size()-1].getX());
bone << _y, _midpoints[0].getY(), _midpoints[1].getY(), _midpoints[_midpoints.size()-1].getY();
Eigen::Vector4f x = Aone.colPivHouseholderQr().solve(bone);
_Ax = x(1);
_Bx = x(2);
_Cx = x(3);
_Dx = x(4);
Eigen::Matrix4f Atwo;
Eigen::Vector4f btwo;
Atwo << _y, squared(_y), cubed(_y), _midpoints[0].getY(), squared(_midpoints[0].getY()), cubed(_midpoints[0].getY()), _midpoints[1].getY(), squared(_midpoints[1].getY()), cubed(_midpoints[1].getY()), _midpoints[_midpoints.size()-1].getY(), squared(_midpoints[_midpoints.size()-1].getY()), cubed(_midpoints[_midpoints.size()-1].getY());
btwo << _x, _midpoints[0].getX(), _midpoints[1].getX(), _midpoints[_midpoints.size()-1].getX();
Eigen::Vector4f y = Aone.colPivHouseholderQr().solve(bone);
_Ay = y(1);
_By = y(2);
_Cy = y(3);
_Dx = y(4);
return;
}
void PathPlanningClass::extrapolate()
{
// number of desired points
int numOfpoints = 20;
// distance to be extrapolated from car's location
double distance = 10;
// the argument for g(y) and f(x)
double arg = distance/numOfpoints;
for (int i = 0 ; i < numOfpoints; i++)
{
double farg = _Ax + _Bx*arg*i + _Cx*squared(arg*i) + _Dx*cubed(arg*i);
double garg = _Ay + _By*arg*i + _Cy*squared(arg*i) + _Dy*cubed(arg*i);
PathPoint newPoint(farg, garg, velocity(_x, _y, _yaw), 9.8);
_path.push_back(newPoint);
}
return;
}

2D Projectile - Updating my x and y values?

I'm building a small physics engine that launches a projectile with a given angle and velocity, and tracks and displays the velocity/position vectors at each time interval. At the moment, my position value vars.posNew seems to be updating, but I can't get my vars.x and vars.y values to update.
Here's my code:
#include <iostream>
using namespace std;
#define PI 3.14159265359
struct vecVariables {
float v = 0, a = -9.81;
float posNew = 0, posOld = 0;
float x, y;
float theta = 45; // our start angle is 45
float u = 20; // our start velocity is 20
};
int main() {
float deltaT = 0.01;
vecVariables vars; // creates an object for Variables to be used
while (deltaT <= 1) {
deltaT += 0.01;
vars.v = vars.u + vars.a * deltaT; // gets the velocity V
vars.posNew = vars.posOld + vars.v * deltaT; // gets position D
vars.x = vars.u * cos(vars.theta * PI / 180); // <-- I'm going wrong somewhere here
vars.y = vars.u * sin(vars.theta* PI / 180);
cout << "velocity vec = [" << vars.x << " , " << vars.y << "]" << endl; // velocity on x,y
cout << "pos = "<< vars.posNew << endl; // display position
vars.posOld = vars.posNew;
getchar();
}
}
I'm aware that the values being put into vars.x and vars.y are constant values, which leads me to simply believe that I have applied the wrong formula to calculate these values, or am I just missing one thing?
Well vars.x and vars.y are calculated using vars.u that never changes. Try using v(new velocity if I understand right):
vars.x = vars.v * cos(vars.theta * PI / 180);
vars.y = vars.v * sin(vars.theta* PI / 180);
I think you want to use v instead of u, since v is new velocity. Not sure about vars.theta, should it change over time? Also is it correct that first time you calculate vars.x and vars.y it is done with new velocity or should it be done with the starting value at first run. Perhaps consider adding one more variable so you can store values from one run earlier. If I tangled my answer to much let me know ;)

C++ Logic Issue

I'm trying to write a simple c++ program that outputs an objects current height once it hits a specific point. The object I'm trying to accomplish is that you have an object that starts at a varied position a moves off under a random velocity with gravity attached. If the ball collides with a wall or another object, it should move backward, with no energy loss, but still continue to fall due to gravity. Once the ball has reached a specific height, output that value.
Now, all I'm trying to do right now is check to see if my ball has gone beyond my width bounds. But for the life of me I can't see why my last if statement at the bottom wont call.
Am I missing / doing something really stupid?
int _tmain(int argc, _TCHAR* argv[])
{
float velocity;
float height, targetHeight;
float gravity;
float time;
float angle;
float width;
float move;
float distance;
gravity = 9.80f;
time = 0;
distance = 0;
cout << "Set Height\n";
cin >> height;
cout << "Set target height\n";
cin >> targetHeight;
cout << "Set Angle ( 0 - 90 ): \n";
cin >> angle;
angle *= 3.14 * 180; // convert to radians
cout << "Set velocity (0 - 100): \n";
cin >> velocity;
cout << "Set Play field Width: \n";
cin >> width;
while( height >= target )
{
time++;
distance += velocity * cos(angle) * time;
height += (velocity * sin(angle) * time) - (gravity * pow(time, 2) ) / 2;
}
if( distance == width)
{
cout << "You've hit the wall\n";
}
return 0;
}
Your final if statement if( distance == width ) does not test if the distance has gone beyond the width. You probably want if( distance >= width ). There doesn't appear to be any testing of distance traveled within your movement loop so distance could easily be greater than the width and thus cause your if to not be true.
Move backwards at the same speed: velocity = -velocity;. Of course, if it's moving backwards, it may hit the other wall, so you probably want to check the distance == 0; as well. (Since it's floating point, I would also suggest you use >= and <= instead of exact comparisons, or you may find that the ball was one micrometer PAST the wall and then continues until it hits the sun, or you run out of math, or whatever else happens if you keep going forever).
I would further suggest that you would need the width and breadth of the "room" the ball is bouncing around in. So, in total you need X, Y, and Z coordinates of the ball.
Note: your time ever increases, which implies a direct formula for height and distance (one saying distance = f(time);), but you're accumulating.
So probably you want to assign instead of increment your distance and height variables:
distance = velocity * cos(angle) * time;
height = (velocity * sin(angle) * time) - (gravity * pow(time, 2) ) / 2;
Next to that, you probably want to check whether the travelled distance exceeds the distance to the wall (equality with floats is very improbable, plus inaccurate).
Some stylistic advice: put those equations in functions of their own.

Help with Inverse Kinematics Algorithm

I'm trying to implement CCD Inverse Kinematics in 2D
This function is supposed to do 1 iteration of CCD
Right now as a test case I start it on a left foot and have it stop at the pelvis.
every time this function is called, the skeleton's bones are updated.
The way my bones work is:
getFrameX,Y,Angle return the absolute positions of the end of the bone / effector. These are updated every iteraton of CCD.
getAngle,X, Y returns the relative values.
Same for setters.
Right now it never stays in one spot, every time I giggle the mouse a bit it moves the bones randomly counterclockwise.
I was wondering if there was something bluntly obviously wrong that could point me in the right direction for debugging.
void inverseKinematics(float targetX, float targetY, skl::Bone* targetBone)
{
std::string stopBone = "Pelvis";
//===
// Track the end effector position (the final bone)
double endX = targetBone->getFrameX();
double endY = targetBone->getFrameY();
//===
// Perform CCD on the bones by optimizing each bone in a loop
// from the final bone to the root bone
bool modifiedBones = false;
targetBone = targetBone->getParent();
while(targetBone->getName() != stopBone)
{
// Get the vector from the current bone to the end effector position.
double curToEndX = endX - targetBone->getFrameX();
double curToEndY = endY - targetBone->getFrameY();
double curToEndMag = sqrt( curToEndX*curToEndX + curToEndY*curToEndY );
// Get the vector from the current bone to the target position.
double curToTargetX = targetX - targetBone->getFrameX();
double curToTargetY = targetY - targetBone->getFrameY();
double curToTargetMag = sqrt( curToTargetX*curToTargetX
+ curToTargetY*curToTargetY );
// Get rotation to place the end effector on the line from the current
// joint position to the target position.
double cosRotAng;
double sinRotAng;
double endTargetMag = (curToEndMag*curToTargetMag);
if( endTargetMag <= 0.1f )
{
cosRotAng = 1.0f;
sinRotAng = 0.0f;
}
else
{
cosRotAng = (curToEndX*curToTargetX + curToEndY*curToTargetY) / endTargetMag;
sinRotAng = (curToEndX*curToTargetY - curToEndY*curToTargetX) / endTargetMag;
}
// Clamp the cosine into range when computing the angle (might be out of range
// due to floating point error).
double rotAng = acosf( max(-1.0f, min(1.0f,cosRotAng) ) );
if( sinRotAng < 0.0f )
rotAng = -rotAng;
// Rotate the end effector position.
endX = targetBone->getFrameX() + cosRotAng*curToEndX - sinRotAng*curToEndY;
endY = targetBone->getFrameY() + sinRotAng*curToEndX + cosRotAng*curToEndY;
// Rotate the current bone in local space (this value is output to the user)
targetBone->setAngle(SimplifyAngle(targetBone->getAngle() + rotAng));
// Check for termination
double endToTargetX = (targetX-endX);
double endToTargetY = (targetY-endY);
if( endToTargetX*endToTargetX + endToTargetY*endToTargetY <= 1.0f )
{
// We found a valid solution.
return;
}
// Track if the arc length that we moved the end effector was
// a nontrivial distance.
if( !modifiedBones && fabs(rotAng)*curToEndMag > 0.0001f )
{
modifiedBones = true;
}
targetBone = targetBone->getParent();
}
Thanks
No, there is nothing obviously wrong in the program listing you have given. You are correctly computing the change of angle rotAng and the new position (endX, endY) of the end-effector.
You can compute rotAng more simply as
double rotAng =
atan2(curToTargetY, curToTargetX) - atan2(curToEndY, curToEndX);
which gives identical results (assuming the vectors are non-zero).
I suspect the error is somewhere outside of the program listing you have given. Maybe there is a discrepancy between the forward kinematics assumed in inverseKinematics() and the actual forward kinematics used in the display routines and elsewhere. Try recomputing the forward kinematics at the end of the procedure to see if the rest of the system agrees that the end-effector is at (endX, endY).

Sporadic Collision Detection

I've been working on detecting collision between to object in my game. Right now everything tavels vertically, but would like to keep the option for other movement open. It's classic 2d vertical space shooter.
Right now I loop through every object, checking for collisions:
for(std::list<Object*>::iterator iter = mObjectList.begin(); iter != mObjectList.end();) {
Object *m = (*iter);
for(std::list<Object*>::iterator innerIter = ++iter; innerIter != mObjectList.end(); innerIter++ ) {
Object *s = (*innerIter);
if(m->getType() == s->getType()) {
break;
}
if(m->checkCollision(s)) {
m->onCollision(s);
s->onCollision(m);
}
}
}
Here is how I check for a collision:
bool checkCollision(Object *other) {
float radius = mDiameter / 2.f;
float theirRadius = other->getDiameter() / 2.f;
Vector<float> ourMidPoint = getAbsoluteMidPoint();
Vector<float> theirMidPoint = other->getAbsoluteMidPoint();
// If the other object is in between our path on the y axis
if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y &&
theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius)) {
// Get the distance between the midpoints on the x axis
float xd = abs(ourMidPoint.x - theirMidPoint.x);
// If the distance between the two midpoints
// is greater than both of their radii together
// then they are too far away to collide
if(xd > radius+theirRadius) {
return false;
} else {
return true;
}
}
return false;
}
The problem is it will randomly detect collisions correctly, but other times does not detect it at all. It's not the if statement breaking away from the object loop because the objects do have different types. The closer the object is to the top of the screen, the better chance it has of collision getting detected correctly. Closer to the bottom of the screen, the less chance it has of getting detected correctly or even at all. However, these situations don't always occur. The diameter for the objects are massive (10 and 20) to see if that was the problem, but it doesn't help much at all.
EDIT - Updated Code
bool checkCollision(Object *other) {
float radius = mDiameter / 2.f;
float theirRadius = other->getDiameter() / 2.f;
Vector<float> ourMidPoint = getAbsoluteMidPoint();
Vector<float> theirMidPoint = other->getAbsoluteMidPoint();
// Find the distance between the two points from the center of the object
float a = theirMidPoint.x - ourMidPoint.x;
float b = theirMidPoint.y - ourMidPoint.y;
// Find the hypotenues
double c = (a*a)+(b*b);
double radii = pow(radius+theirRadius, 2.f);
// If the distance between the points is less than or equal to the radius
// then the circles intersect
if(c <= radii*radii) {
return true;
} else {
return false;
}
}
Two circular objects collide when the distance between their centers is small enough. You can use the following code to check this:
double distanceSquared =
pow(ourMidPoint.x - theirMidPoint.x, 2.0) +
pow(ourMidPoint.x - theirMidPoint.x, 2.0);
bool haveCollided = (distanceSquared <= pow(radius + theirRadius, 2.0));
In order to check whether there was a collision between two points in time, you can check for collision at the start of the time interval and at the end of it; however, if the objects move very fast, the collision detection can fail (i guess you have encountered this problem for falling objects that have the fastest speed at the bottom of the screen).
The following might make the collision detection more reliable (though still not perfect). Suppose the objects move with constant speed; then, their position is a linear function of time:
our_x(t) = our_x0 + our_vx * t;
our_y(t) = our_y0 + our_vy * t;
their_x(t) = their_x0 + their_vx * t;
their_y(t) = their_y0 + their_vy * t;
Now you can define the (squared) distance between them as a quadratic function of time. Find at which time it assumes its minimum value (i.e. its derivative is 0); if this time belongs to current time interval, calculate the minimum value and check it for collision.
This must be enough to detect collisions almost perfectly; if your application works heavily with free-falling objects, you might want to refine the movement functions to be quadratic:
our_x(t) = our_x0 + our_v0x * t;
our_y(t) = our_y0 + our_v0y * t + g/2 * t^2;
This logic is wrong:
if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y &&
theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius))
{
// then a collision is possible, check x
}
(The logic inside the braces is wrong too, but that should produce false positives, not false negatives.) Checking whether a collision has occurred during a time interval can be tricky; I'd suggest checking for a collision at the present time, and getting that to work first. When you check for a collision (now) you can't check x and y independently, you must look at the distance between the object centers.
EDIT:
The edited code is still not quite right.
// Find the hypotenues
double c = (a*a)+(b*b); // actual hypotenuse squared
double radii = pow(radius+theirRadius, 2.f); // critical hypotenuse squared
if(c <= radii*radii) { // now you compare a distance^2 to a distance^4
return true; // collision
}
It should be either this:
double c2 = (a*a)+(b*b); // actual hypotenuse squared
double r2 = pow(radius+theirRadius, 2.f); // critical hypotenuse squared
if(c2 <= r2) {
return true; // collision
}
or this:
double c2 = (a*a)+(b*b); // actual hypotenuse squared
double c = pow(c2, 0.5); // actual hypotenuse
double r = radius + theirRadius; // critical hypotenuse
if(c <= r) {
return true; // collision
}
Your inner loop needs to start at mObjectList.begin() instead of iter.
The inner loop needs to iterate over the entire list otherwise you miss collision candidates the further you progress in the outer loop.