Currently, I have three potentially targetable lines visible to the pixy2. I have a ‘for’ loop that iterates through all visible vectors, selects the one with m_x0 that is closest to the center, gets the index of that vector, and then calls setVector() with the selected index when it is finished.
Now my questions/problems.
One: How do I get the m_x0 and m_y0 of that vector after I have already cycled? Can I get it based on the index?
Two: The pixy does not appear to refresh which vector is selected when there is a different vector closer to the center unless I open the config menu in pixymon
Three: Despite repeatedly calling the setVector method, sometimes there is no vector (visibly) selected on pixymon
Here is the code, but be warned, it’s a mess. This is the closest I could get to a functioning system.
#include <PIDLoop.h>
#include <Pixy2.h>
#include <Pixy2Line.h>
#include <Pixy2UART.h>
#include <Pixy2I2C.h>
#include <Pixy2SPI_SS.h>
/**
* Communication code from the pixys to the arduino and from the duino to the rio
* The highPixy is the pixy placed high on the robot, which will be used for pathing to the white line
* The lowPixy is the pixy placed low on the robot used for shorter range tracking of the reflective tape
*/
// Declares the Pixys
Pixy2SPI_SS highPixy;
Pixy2I2C lowPixy;
// Declares variables for the low pixy
int leftX;
int rightX;
int leftWidth;
int rightWidth;
int xLOne;
int xROne;
int xLTwo;
int xRTwo;
int centerPoint;
int absoluteCenter = 158;
int distToCenter;
double angleToCenter;
double tempDistCenter;
double selectedDistCenter = 39;
double targetIndex;
// Value of pi for calculations
double pi = 3.1415926535;
// Height and angle of the pixy (in)
double cameraHeight = 47.375;
double cameraAngle = 30;
// Coordinates of the origin point (p)
double originX = 39;
double originY = 51;
// Constants for the pixy
double thirtyDegInRad = ((pi / 180) * 30);
double degPerVertPix = (40.0 / 51.0);
double degPerHorizPix = (60.0 / 78.0);
// Values for calculating position later [RECOMMENT]
// Degrees from vertical to the end of the blindspot
double blindspotDeg = (cameraAngle - 20);
// Pixel distance from the base to the target point
double xDist;
double yDist;
// Diagonal distance from the camera to the target point
double hypToCamera;
double yDistDeg;
double xDistDeg;
// Y Distance in inches from the robot to the target
double distRobotToTarget;
double xDistRobotToTarget;
// Width of the projection at the given y value
double xWidth;
// Inches per pixel in the x direction
double xInPerPix;
// Distance from midline to the target on the floor in Inches
double xDistIn;
// Degrees from the base of the robot to the target point
double degToTarget;
double distToTarget;
// Command char recieved from the rio, where 2 is degToTarget, 1 is distToTarget, 3 is angleToCenter, and 4 is lowPosition
char incCommand = '0';
// Commands we are comparing incCommand to
const char GET_DEG_TO_TARGET = '2';
const char GET_DIST_TO_TARGET = '1';
const char GET_ANGLE_TO_CENTER = '3';
const char GET_LOW_POSITION = '4';
// This is the return for the position according to the lowPixy, where 1 is left, 2 is center, and 3 is right. -1 is no blocks
int lowPosition = -1;
// Convert degrees to radians
double degToRad(double degInput)
{
double radOutput = degInput * (pi / 180);
return radOutput;
}
// Calculate the inches per x pixel on a given y value in order to calulate angle to the robot
void calcInPerPix(double height, double angle, double tailX, double tailY)
{
xDist = (tailX - originX);
yDist = (originY - tailY);
yDistDeg = (blindspotDeg + (yDist * degPerVertPix));
distRobotToTarget = 11+(height * tan(degToRad(yDistDeg)));
hypToCamera = sqrt(sq(height) + sq(distRobotToTarget));
xDistDeg = (xDist * degPerHorizPix);
xDistRobotToTarget = hypToCamera * tan(degToRad(abs(xDistDeg)));
}
//void calcDistToCenterLow()
//{
// if (lowPixy.ccc.blocks[0].m_x < lowPixy.ccc.blocks[1].m_x)
// {
// leftX = lowPixy.ccc.blocks[0].m_x;
// rightX = lowPixy.ccc.blocks[1].m_x;
// leftWidth = lowPixy.ccc.blocks[0].m_width;
// rightWidth = lowPixy.ccc.blocks[1].m_width;
// }
// else if (lowPixy.ccc.blocks[0].m_x > lowPixy.ccc.blocks[1].m_x)
// {
// leftX = lowPixy.ccc.blocks[1].m_x;
// rightX = lowPixy.ccc.blocks[0].m_x;
// leftWidth = lowPixy.ccc.blocks[1].m_width;
// rightWidth = lowPixy.ccc.blocks[0].m_width;
// }
//
// xLOne = leftX - (leftWidth / 2);
// xROne = rightX + (leftWidth / 2);
// xLTwo = leftX - (rightWidth / 2);
// xRTwo = rightX + (rightWidth / 2);
// centerPoint = ((xLTwo - xROne) / 2) + xROne;
// distToCenter = absoluteCenter - centerPoint;
// angleToCenter = distToCenter * 0.189873;
//}
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
// Initializes the Pixy
// Hexadecimal values passed in correspond to address set on the pixy
highPixy.init(0x54);
//// lowPixy.init(0x53);
// highPixy.changeProg("line");
// highPixy.line.setMode(LINE_MODE_MANUAL_SELECT_VECTOR);
}
// Reads command off of the wire and converts it to a usable char
void receiveCommand()
{
incCommand = (char)Serial.read();
}
// Flushes excess data off after we read the command
void serialFlush()
{
while (Serial.available() > 0)
{
char t = Serial.read();
}
}
// Writes data down the wire based on command passed in
void sendData(char command)
{
if (command == GET_DEG_TO_TARGET)
{
if (String(degToTarget) == ("-34.36"))
{
degToTarget = -180;
}
Serial.println(degToTarget);
}
else if (command == GET_DIST_TO_TARGET)
{
Serial.println(distToTarget);
}
// else if (command == GET_ANGLE_TO_CENTER)
// {
// Serial.println(angleToCenter);
// }
// else if (command == GET_LOW_POSITION)
// {
// Serial.println(lowPosition);
// }
}
void loop()
{
int indexindex = 0;
targetIndex = -500;
// Gets data from the highPixy
highPixy.line.getAllFeatures(1, false);
selectedDistCenter = 39;
tempDistCenter = 39;
for(indexindex = 0; indexindex < highPixy.line.numVectors; indexindex++)
{
tempDistCenter = abs(originX - highPixy.line.vectors[indexindex].m_x0);
if (tempDistCenter < selectedDistCenter)
{
selectedDistCenter = tempDistCenter;
targetIndex = highPixy.line.vectors[indexindex].m_index;
}
}
highPixy.line.setVector(targetIndex);
highPixy.line.getMainFeatures();
// Calculates return values for the highPixy
calcInPerPix(cameraHeight, cameraAngle, highPixy.line.vectors->m_x0, highPixy.line.vectors->m_y0);
degToTarget = (atan(xDistRobotToTarget / distRobotToTarget) * (180 / pi)) * (abs(xDist)/xDist);
distToTarget = sqrt(sq(distRobotToTarget) + sq(xDistRobotToTarget));
// Gets data from the lowPixy
// lowPixy.ccc.getBlocks(true, 255, 2);
// Calculates return values for the lowPixy
// if (lowPixy.ccc.numBlocks)
// {
// calcDistToCenterLow();
//
// if (absoluteCenter - centerPoint < 2)
// {
// lowPosition = 1;
// }
// else if (absoluteCenter - centerPoint > 2)
// {
// lowPosition = 3;
// }
// else
// {
// lowPosition = 2;
// }
// }
// else
// {
// lowPosition = -1;
// }
// Runs the communication code if a command is available
if (Serial.available() > 0)
{
receiveCommand();
serialFlush();
sendData(incCommand);
Serial.flush();
incCommand = 0;
}
}