mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-04 03:11:43 +00:00
Compare commits
44 Commits
jenkins-re
...
jenkins-re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
359a155915 | ||
|
|
fb7f5e9de8 | ||
|
|
7db63055f6 | ||
|
|
b94341a23e | ||
|
|
afbd70d393 | ||
|
|
ceccd95084 | ||
|
|
91b9812482 | ||
|
|
0dbc40e515 | ||
|
|
5ce89b3382 | ||
|
|
8ccf3d9c14 | ||
|
|
230fa2d168 | ||
|
|
d165f57e6e | ||
|
|
2d15b6b03e | ||
|
|
5d9baa44ee | ||
|
|
822416d2f7 | ||
|
|
3fe726d851 | ||
|
|
4c0b2c18ab | ||
|
|
b4c5a3af77 | ||
|
|
eddb0b20b0 | ||
|
|
6d8e782f53 | ||
|
|
0368322385 | ||
|
|
19e05ff52b | ||
|
|
a6aef54ef4 | ||
|
|
32f3bea465 | ||
|
|
9aacf5eb29 | ||
|
|
f3484686c9 | ||
|
|
b78b14bf5f | ||
|
|
c08dc98650 | ||
|
|
9fbffd88cb | ||
|
|
6c15a3600a | ||
|
|
548941dd99 | ||
|
|
9d8418c14e | ||
|
|
326bf4fc9c | ||
|
|
3c4a1d9a1a | ||
|
|
7687028269 | ||
|
|
a55f34646d | ||
|
|
53473e21be | ||
|
|
b4097fbd58 | ||
|
|
3b72114555 | ||
|
|
cc36454b90 | ||
|
|
aae20ddbff | ||
|
|
ffd9061766 | ||
|
|
9ffdea188b | ||
|
|
198e2eed14 |
@@ -0,0 +1,37 @@
|
||||
#include "WPILib.h"
|
||||
|
||||
/**
|
||||
* Uses AxisCamera class to manually acquire a new image each frame, and annotate the image by drawing
|
||||
* a circle on it, and show it on the FRC Dashboard.
|
||||
*/
|
||||
class AxisCameraSample : public SampleRobot
|
||||
{
|
||||
IMAQdxSession session;
|
||||
Image *frame;
|
||||
IMAQdxError imaqError;
|
||||
AxisCamera *camera;
|
||||
|
||||
public:
|
||||
void RobotInit() override {
|
||||
// create an image
|
||||
frame = imaqCreateImage(IMAQ_IMAGE_RGB, 0);
|
||||
|
||||
// open the camera at the IP address assigned. This is the IP address that the camera
|
||||
// can be accessed through the web interface.
|
||||
camera = new AxisCamera("10.1.91.103");
|
||||
}
|
||||
|
||||
void OperatorControl() override {
|
||||
// grab an image, draw the circle, and provide it for the camera server which will
|
||||
// in turn send it to the dashboard.
|
||||
while(IsOperatorControl() && IsEnabled()) {
|
||||
camera->GetImage(frame);
|
||||
imaqDrawShapeOnImage(frame, frame, { 10, 10, 100, 100 }, DrawMode::IMAQ_DRAW_VALUE, ShapeMode::IMAQ_SHAPE_OVAL, 0.0f);
|
||||
CameraServer::GetInstance()->SetImage(frame);
|
||||
Wait(0.05);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
START_ROBOT_CLASS(AxisCameraSample);
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
void RobotInit() override {
|
||||
// create an image
|
||||
frame = imaqCreateImage(IMAQ_IMAGE_RGB, 0);
|
||||
// open the camera
|
||||
//the camera name (ex "cam0") can be found through the roborio web interface
|
||||
imaqError = IMAQdxOpenCamera("cam0", IMAQdxCameraControlModeController, &session);
|
||||
if(imaqError != IMAQdxErrorSuccess) {
|
||||
DriverStation::ReportError("IMAQdxOpenCamera error: " + std::to_string((long)imaqError) + "\n");
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
imaqDrawShapeOnImage(frame, frame, { 10, 10, 100, 100 }, DrawMode::IMAQ_DRAW_VALUE, ShapeMode::IMAQ_SHAPE_OVAL, 0.0f);
|
||||
CameraServer::GetInstance()->SetImage(frame);
|
||||
}
|
||||
Wait(0.005); // wait for a motor update time
|
||||
}
|
||||
// stop image acquisition
|
||||
IMAQdxStopAcquisition(session);
|
||||
|
||||
@@ -10,11 +10,18 @@ class QuickVisionRobot : public SampleRobot
|
||||
{
|
||||
public:
|
||||
void RobotInit() override {
|
||||
CameraServer::GetInstance()->SetQuality(75);
|
||||
CameraServer::GetInstance()->StartAutomaticCapture();
|
||||
CameraServer::GetInstance()->SetQuality(50);
|
||||
//the camera name (ex "cam0") can be found through the roborio web interface
|
||||
CameraServer::GetInstance()->StartAutomaticCapture("cam0");
|
||||
}
|
||||
|
||||
void OperatorControl() override {
|
||||
void OperatorControl()
|
||||
{
|
||||
while (IsOperatorControl() && IsEnabled())
|
||||
{
|
||||
/** robot code here! **/
|
||||
Wait(0.005); // wait for a motor update time
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Simple vision program</name>
|
||||
<name>Simple Vision</name>
|
||||
<description>The minimal program to acquire images from an attached USB camera on the robot
|
||||
and send them to the dashboard.</description>
|
||||
<tags>
|
||||
@@ -298,7 +298,7 @@
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Intermediate vision</name>
|
||||
<name>Intermediate Vision</name>
|
||||
<description>An example program that acquires images from an attached USB camera and adds some
|
||||
annotation to the image as you might do for showing operators the result of some image
|
||||
recognition, and sends it to the dashboard for display.
|
||||
@@ -316,6 +316,26 @@
|
||||
</files>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Axis Camera Sample</name>
|
||||
<description>An example program that acquires images from an Axis network camera and adds some
|
||||
annotation to the image as you might do for showing operators the result of some image
|
||||
recognition, and sends it to the dashboard for display. This demonstrates the use of the
|
||||
AxisCamera class.
|
||||
</description>
|
||||
<tags>
|
||||
<tag>Vision</tag>
|
||||
<tag>Complete List</tag>
|
||||
</tags>
|
||||
<packages>
|
||||
<package>src</package>
|
||||
</packages>
|
||||
<files>
|
||||
<file source="examples/AxisCameraSample/src/Robot.cpp"
|
||||
destination="src/Robot.cpp"></file>
|
||||
</files>
|
||||
</example>
|
||||
|
||||
|
||||
<example>
|
||||
<name>GearsBot</name>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package $package;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
import com.ni.vision.NIVision.DrawMode;
|
||||
import com.ni.vision.NIVision.Image;
|
||||
import com.ni.vision.NIVision.ShapeMode;
|
||||
|
||||
import edu.wpi.first.wpilibj.CameraServer;
|
||||
import edu.wpi.first.wpilibj.SampleRobot;
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
import edu.wpi.first.wpilibj.vision.AxisCamera;
|
||||
|
||||
/**
|
||||
* This demo shows the use of the AxisCamera class.
|
||||
* Uses AxisCamera class to manually acquire a new image each frame, and annotate the image by drawing
|
||||
* a circle on it, and show it on the FRC Dashboard.
|
||||
*/
|
||||
|
||||
public class Robot extends SampleRobot {
|
||||
int session;
|
||||
Image frame;
|
||||
AxisCamera camera;
|
||||
|
||||
public void robotInit() {
|
||||
|
||||
frame = NIVision.imaqCreateImage(NIVision.ImageType.IMAGE_RGB, 0);
|
||||
|
||||
// open the camera at the IP address assigned. This is the IP address that the camera
|
||||
// can be accessed through the web interface.
|
||||
camera = new AxisCamera("10.1.91.100");
|
||||
}
|
||||
|
||||
public void operatorControl() {
|
||||
|
||||
/**
|
||||
* grab an image from the camera, draw the circle, and provide it for the camera server
|
||||
* which will in turn send it to the dashboard.
|
||||
*/
|
||||
NIVision.Rect rect = new NIVision.Rect(10, 10, 100, 100);
|
||||
|
||||
while (isOperatorControl() && isEnabled()) {
|
||||
camera.getImage(frame);
|
||||
NIVision.imaqDrawShapeOnImage(frame, frame, rect,
|
||||
DrawMode.DRAW_VALUE, ShapeMode.SHAPE_OVAL, 0.0f);
|
||||
|
||||
CameraServer.getInstance().setImage(frame);
|
||||
|
||||
/** robot code here! **/
|
||||
Timer.delay(0.005); // wait for a motor update time
|
||||
}
|
||||
}
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,10 @@ import com.ni.vision.NIVision;
|
||||
import com.ni.vision.NIVision.DrawMode;
|
||||
import com.ni.vision.NIVision.Image;
|
||||
import com.ni.vision.NIVision.ShapeMode;
|
||||
|
||||
import edu.wpi.first.wpilibj.CameraServer;
|
||||
import edu.wpi.first.wpilibj.SampleRobot;
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
|
||||
/**
|
||||
* This is a demo program showing the use of the NIVision class to do vision processing.
|
||||
@@ -20,10 +23,8 @@ public class Robot extends SampleRobot {
|
||||
|
||||
frame = NIVision.imaqCreateImage(NIVision.ImageType.IMAGE_RGB, 0);
|
||||
|
||||
/**
|
||||
* the camera name (ex "cam1") can be found through the roborio web interface
|
||||
*/
|
||||
session = NIVision.IMAQdxOpenCamera("cam1",
|
||||
// the camera name (ex "cam0") can be found through the roborio web interface
|
||||
session = NIVision.IMAQdxOpenCamera("cam0",
|
||||
NIVision.IMAQdxCameraControlMode.CameraControlModeController);
|
||||
NIVision.IMAQdxConfigureGrab(session);
|
||||
}
|
||||
@@ -44,6 +45,9 @@ public class Robot extends SampleRobot {
|
||||
DrawMode.DRAW_VALUE, ShapeMode.SHAPE_OVAL, 0.0f);
|
||||
|
||||
CameraServer.getInstance().setImage(frame);
|
||||
|
||||
/** robot code here! **/
|
||||
Timer.delay(0.005); // wait for a motor update time
|
||||
}
|
||||
NIVision.IMAQdxStopAcquisition(session);
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
package $package;
|
||||
|
||||
import edu.wpi.first.wpilibj.CameraServer;
|
||||
import edu.wpi.first.wpilibj.SampleRobot;
|
||||
import edu.wpi.first.wpilibj.RobotDrive;
|
||||
import edu.wpi.first.wpilibj.Joystick;
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
|
||||
/**
|
||||
* This is a demo program showing the use of the CameraServer class.
|
||||
* With start automatic capture, there is no opertunity to process the image.
|
||||
* Look at the AdvancedVision sample for how to process the image before sending it to the FRC PC Dashboard.
|
||||
* With start automatic capture, there is no opportunity to process the image.
|
||||
* Look at the IntermediateVision sample for how to process the image before sending it to the FRC PC Dashboard.
|
||||
*/
|
||||
public class Robot extends SampleRobot {
|
||||
|
||||
@@ -17,6 +16,8 @@ public class Robot extends SampleRobot {
|
||||
public Robot() {
|
||||
server = CameraServer.getInstance();
|
||||
server.setQuality(50);
|
||||
//the camera name (ex "cam0") can be found through the roborio web interface
|
||||
server.startAutomaticCapture("cam0");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,10 +26,9 @@ public class Robot extends SampleRobot {
|
||||
*/
|
||||
public void operatorControl() {
|
||||
|
||||
server.startAutomaticCapture("cam1");
|
||||
|
||||
while (isOperatorControl() && isEnabled()) {
|
||||
/** robot code here! **/
|
||||
Timer.delay(0.005); // wait for a motor update time
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
teleoperated routines.</description>
|
||||
<tags>
|
||||
<tag>Getting Started with Java</tag>
|
||||
<tag>Complete List</tag>
|
||||
</tags>
|
||||
<packages>
|
||||
<package>src/$package-dir</package>
|
||||
@@ -294,10 +295,11 @@
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Quick Vision</name>
|
||||
<name>Simple Vision</name>
|
||||
<description>Demonstrate the use of the CameraServer class to stream from a USB Webcam without processing the images.</description>
|
||||
<tags>
|
||||
<tag>Vision</tag>
|
||||
<tag>Complete List</tag>
|
||||
</tags>
|
||||
<packages>
|
||||
<package>src/$package-dir</package>
|
||||
@@ -309,18 +311,39 @@
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Advanced Vision</name>
|
||||
<name>Intermediate Vision</name>
|
||||
<description>Demonstrate the use of the NIVision class to capture image from a Webcam, process them, and then send them to the dashboard.</description>
|
||||
<tags>
|
||||
<tag>Vision</tag>
|
||||
<tag>Complete List</tag>
|
||||
</tags>
|
||||
<packages>
|
||||
<package>src/$package-dir</package>
|
||||
</packages>
|
||||
<files>
|
||||
<file source="examples/AdvancedVision/src/org/usfirst/frc/team190/robot/Robot.java"
|
||||
<file source="examples/IntermediateVision/src/org/usfirst/frc/team190/robot/Robot.java"
|
||||
destination="src/$package-dir/Robot.java"></file>
|
||||
</files>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<name>Axis Camera Sample</name>
|
||||
<description>An example program that acquires images from an Axis network camera and adds some
|
||||
annotation to the image as you might do for showing operators the result of some image
|
||||
recognition, and sends it to the dashboard for display. This demonstrates the use of the
|
||||
AxisCamera class.
|
||||
</description>
|
||||
<tags>
|
||||
<tag>Vision</tag>
|
||||
<tag>Complete List</tag>
|
||||
</tags>
|
||||
<packages>
|
||||
<package>src/$package-dir</package>
|
||||
</packages>
|
||||
<files>
|
||||
<file source="examples/AxisCameraSample/src/org/usfirst/frc/team190/robot/Robot.java"
|
||||
destination="src/$package-dir/Robot.java"></file>
|
||||
</files>
|
||||
</example>
|
||||
|
||||
</examples>
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
</bool>
|
||||
</assert>
|
||||
<echo>roboRIO image version validated</echo>
|
||||
<echo>Checking for JRE. If this fails install the JRE using these instructions: http://wpilib.screenstepslive.com/s/4485/m/13809/l/243933-installing-java-8-on-the-roborio-java-only</echo>
|
||||
<echo>Checking for JRE. If this fails install the JRE using these instructions: https://wpilib.screenstepslive.com/s/4485/m/13503/l/288822-installing-java-8-on-the-roborio-using-the-frc-roborio-java-installer-java-only</echo>
|
||||
<sshexec host="${target}"
|
||||
username="${username}"
|
||||
password="${password}"
|
||||
|
||||
@@ -23,6 +23,14 @@ extern "C" {
|
||||
|
||||
bool getPressureSwitch(void *pcm_pointer, int32_t *status);
|
||||
float getCompressorCurrent(void *pcm_pointer, int32_t *status);
|
||||
|
||||
bool getCompressorCurrentTooHighFault(void *pcm_pointer, int32_t *status);
|
||||
bool getCompressorCurrentTooHighStickyFault(void *pcm_pointer, int32_t *status);
|
||||
bool getCompressorShortedStickyFault(void *pcm_pointer, int32_t *status);
|
||||
bool getCompressorShortedFault(void *pcm_pointer, int32_t *status);
|
||||
bool getCompressorNotConnectedStickyFault(void *pcm_pointer, int32_t *status);
|
||||
bool getCompressorNotConnectedFault(void *pcm_pointer, int32_t *status);
|
||||
void clearAllPCMStickyFaults(void *pcm_pointer, int32_t *status);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,4 +13,9 @@ extern "C"
|
||||
|
||||
bool getSolenoid(void* solenoid_port_pointer, int32_t *status);
|
||||
void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status);
|
||||
|
||||
int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t *status);
|
||||
bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, int32_t *status);
|
||||
bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t *status);
|
||||
void clearAllPCMStickyFaults_sol(void *solenoid_port_pointer, int32_t *status);
|
||||
}
|
||||
|
||||
@@ -61,4 +61,56 @@ float getCompressorCurrent(void *pcm_pointer, int32_t *status) {
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool getCompressorCurrentTooHighFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorCurrentTooHighFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getCompressorCurrentTooHighStickyFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorCurrentTooHighStickyFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getCompressorShortedStickyFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorShortedStickyFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getCompressorShortedFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorShortedFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getCompressorNotConnectedStickyFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorNotConnectedStickyFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getCompressorNotConnectedFault(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
bool value;
|
||||
|
||||
*status = module->GetCompressorNotConnectedFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
void clearAllPCMStickyFaults(void *pcm_pointer, int32_t *status) {
|
||||
PCM *module = (PCM *)pcm_pointer;
|
||||
|
||||
*status = module->ClearStickyFaults();
|
||||
}
|
||||
|
||||
@@ -838,7 +838,7 @@ double getCounterPeriod(void* counter_pointer, int32_t *status) {
|
||||
// output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
|
||||
period = (double)(output.Period << 1) / (double)output.Count;
|
||||
}
|
||||
return period * 1.0e-6;
|
||||
return period * 2.5e-8; // result * timebase (currently 40ns)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -850,7 +850,7 @@ double getCounterPeriod(void* counter_pointer, int32_t *status) {
|
||||
*/
|
||||
void setCounterMaxPeriod(void* counter_pointer, double maxPeriod, int32_t *status) {
|
||||
Counter* counter = (Counter*) counter_pointer;
|
||||
counter->counter->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 1.0e6), status);
|
||||
counter->counter->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 4.0e8), status);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1000,7 +1000,7 @@ double getEncoderPeriod(void* encoder_pointer, int32_t *status) {
|
||||
// output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
|
||||
value = (double)(output.Period << 1) / (double)output.Count;
|
||||
}
|
||||
double measuredPeriod = value * 1.0e-6;
|
||||
double measuredPeriod = value * 2.5e-8;
|
||||
return measuredPeriod / DECODING_SCALING_FACTOR;
|
||||
}
|
||||
|
||||
@@ -1018,7 +1018,7 @@ double getEncoderPeriod(void* encoder_pointer, int32_t *status) {
|
||||
*/
|
||||
void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, int32_t *status) {
|
||||
Encoder* encoder = (Encoder*) encoder_pointer;
|
||||
encoder->encoder->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 1.0e6 * DECODING_SCALING_FACTOR), status);
|
||||
encoder->encoder->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,3 +52,33 @@ void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status) {
|
||||
|
||||
port->module->SetSolenoid(port->pin, value);
|
||||
}
|
||||
|
||||
int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t *status){
|
||||
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
|
||||
UINT8 value;
|
||||
|
||||
*status = port->module->GetSolenoidBlackList(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, int32_t *status){
|
||||
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
|
||||
bool value;
|
||||
|
||||
*status = port->module->GetSolenoidStickyFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t *status){
|
||||
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
|
||||
bool value;
|
||||
|
||||
*status = port->module->GetSolenoidFault(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
void clearAllPCMStickyFaults_sol(void *solenoid_port_pointer, int32_t *status){
|
||||
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
|
||||
|
||||
*status = port->module->ClearStickyFaults();
|
||||
}
|
||||
|
||||
@@ -1222,6 +1222,10 @@ CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param)
|
||||
{
|
||||
return ((CanTalonSRX*)handle)->SetModeSelect(param);
|
||||
}
|
||||
CTR_Code c_TalonSRX_SetModeSelect2(void *handle, int modeSelect, int demand)
|
||||
{
|
||||
return ((CanTalonSRX*)handle)->SetModeSelect(modeSelect, demand);
|
||||
}
|
||||
CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param)
|
||||
{
|
||||
return ((CanTalonSRX*)handle)->SetProfileSlotSelect(param);
|
||||
|
||||
@@ -366,6 +366,7 @@ extern "C" {
|
||||
CTR_Code c_TalonSRX_SetRevMotDuringCloseLoopEn(void *handle, int param);
|
||||
CTR_Code c_TalonSRX_SetOverrideBrakeType(void *handle, int param);
|
||||
CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param);
|
||||
CTR_Code c_TalonSRX_SetModeSelect2(void *handle, int modeSelect, int demand);
|
||||
CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param);
|
||||
CTR_Code c_TalonSRX_SetRampThrottle(void *handle, int param);
|
||||
CTR_Code c_TalonSRX_SetRevFeedbackSensor(void *handle, int param);
|
||||
|
||||
@@ -17,7 +17,9 @@ static const INT32 kCANPeriod = 20;
|
||||
#define GET_PCM_SOL_FAULTS() CtreCanNode::recMsg<PcmStatusFault_t> rx = GetRx<PcmStatusFault_t> (STATUS_SOL_FAULTS,EXPECTED_RESPONSE_TIMEOUT_MS)
|
||||
#define GET_PCM_DEBUG() CtreCanNode::recMsg<PcmDebug_t> rx = GetRx<PcmDebug_t> (STATUS_DEBUG,EXPECTED_RESPONSE_TIMEOUT_MS)
|
||||
|
||||
#define CONTROL_1 0x09041C00
|
||||
#define CONTROL_1 0x09041C00 /* PCM_Control */
|
||||
#define CONTROL_2 0x09041C40 /* PCM_SupplemControl */
|
||||
#define CONTROL_3 0x09041C80 /* PcmControlSetOneShotDur_t */
|
||||
|
||||
/* encoder/decoders */
|
||||
typedef struct _PcmStatus_t{
|
||||
@@ -27,8 +29,8 @@ typedef struct _PcmStatus_t{
|
||||
unsigned compressorOn:1;
|
||||
unsigned stickyFaultFuseTripped:1;
|
||||
unsigned stickyFaultCompCurrentTooHigh:1;
|
||||
unsigned faultCompCurrentTooHigh:1;
|
||||
unsigned faultFuseTripped:1;
|
||||
unsigned faultCompCurrentTooHigh:1;
|
||||
unsigned faultHardwareFailure:1;
|
||||
unsigned isCloseloopEnabled:1;
|
||||
unsigned pressureSwitchEn:1;
|
||||
@@ -40,7 +42,8 @@ typedef struct _PcmStatus_t{
|
||||
unsigned compressorCurrentTop6:6;
|
||||
unsigned solenoidVoltageBtm2:2;
|
||||
/* Byte 5 */
|
||||
unsigned reserved:2;
|
||||
unsigned StickyFault_dItooHigh :1;
|
||||
unsigned Fault_dItooHigh :1;
|
||||
unsigned moduleEnabled:1;
|
||||
unsigned closedLoopOutput:1;
|
||||
unsigned compressorCurrentBtm4:4;
|
||||
@@ -63,19 +66,28 @@ typedef struct _PcmControl_t{
|
||||
unsigned compressorOn:1;
|
||||
unsigned closedLoopEnable:1;
|
||||
unsigned clearStickyFaults:1;
|
||||
/* Byte 4 */
|
||||
unsigned OneShotField_h8:8;
|
||||
/* Byte 5 */
|
||||
unsigned OneShotField_l8:8;
|
||||
}PcmControl_t;
|
||||
|
||||
typedef struct _PcmControlSetOneShotDur_t{
|
||||
uint8_t sol10MsPerUnit[8];
|
||||
}PcmControlSetOneShotDur_t;
|
||||
|
||||
typedef struct _PcmStatusFault_t{
|
||||
/* Byte 0 */
|
||||
unsigned SolenoidBlacklist:8;
|
||||
/* Byte 1 */
|
||||
unsigned reserved1:8;
|
||||
unsigned reserved2:8;
|
||||
unsigned reserved3:8;
|
||||
unsigned reserved4:8;
|
||||
unsigned reserved5:8;
|
||||
unsigned reserved6:8;
|
||||
unsigned reserved7:8;
|
||||
unsigned reserved_bit0 :1;
|
||||
unsigned reserved_bit1 :1;
|
||||
unsigned reserved_bit2 :1;
|
||||
unsigned reserved_bit3 :1;
|
||||
unsigned StickyFault_CompNoCurrent :1;
|
||||
unsigned Fault_CompNoCurrent :1;
|
||||
unsigned StickyFault_SolenoidJumper :1;
|
||||
unsigned Fault_SolenoidJumper :1;
|
||||
}PcmStatusFault_t;
|
||||
|
||||
typedef struct _PcmDebug_t{
|
||||
@@ -135,12 +147,13 @@ CTR_Code PCM::SetSolenoid(unsigned char idx, bool en)
|
||||
*
|
||||
* @Param - clr - Clear / do not clear faults
|
||||
*/
|
||||
CTR_Code PCM::ClearStickyFaults(bool clr)
|
||||
CTR_Code PCM::ClearStickyFaults()
|
||||
{
|
||||
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
|
||||
if(toFill.IsEmpty())return CTR_UnexpectedArbId;
|
||||
toFill->clearStickyFaults = clr;
|
||||
FlushTx(toFill);
|
||||
int32_t status = 0;
|
||||
uint8_t pcmSupplemControl[] = { 0, 0, 0, 0x80 }; /* only bit set is ClearStickyFaults */
|
||||
FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_2 | GetDeviceNumber(), pcmSupplemControl, sizeof(pcmSupplemControl), 0, &status);
|
||||
if(status)
|
||||
return CTR_TxFailed;
|
||||
return CTR_OKAY;
|
||||
}
|
||||
|
||||
@@ -158,6 +171,59 @@ CTR_Code PCM::SetClosedLoopControl(bool en)
|
||||
FlushTx(toFill);
|
||||
return CTR_OKAY;
|
||||
}
|
||||
/* Get solenoid Blacklist status
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - idx - ID of solenoid [0,7] to fire one shot pulse.
|
||||
*/
|
||||
CTR_Code PCM::FireOneShotSolenoid(UINT8 idx)
|
||||
{
|
||||
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
|
||||
if(toFill.IsEmpty())return CTR_UnexpectedArbId;
|
||||
/* grab field as it is now */
|
||||
uint16_t oneShotField;
|
||||
oneShotField = toFill->OneShotField_h8;
|
||||
oneShotField <<= 8;
|
||||
oneShotField |= toFill->OneShotField_l8;
|
||||
/* get the caller's channel */
|
||||
uint16_t shift = 2*idx;
|
||||
uint16_t mask = 3; /* two bits wide */
|
||||
uint8_t chBits = (oneShotField >> shift) & mask;
|
||||
/* flip it */
|
||||
chBits = (chBits)%3 + 1;
|
||||
/* clear out 2bits for this channel*/
|
||||
oneShotField &= ~(mask << shift);
|
||||
/* put new field in */
|
||||
oneShotField |= chBits << shift;
|
||||
/* apply field as it is now */
|
||||
toFill->OneShotField_h8 = oneShotField >> 8;
|
||||
toFill->OneShotField_l8 = oneShotField;
|
||||
FlushTx(toFill);
|
||||
return CTR_OKAY;
|
||||
}
|
||||
/* Configure the pulse width of a solenoid channel for one-shot pulse.
|
||||
* Preprogrammed pulsewidth is 10ms resolute and can be between 20ms and 5.1s.
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - idx - ID of solenoid [0,7] to configure.
|
||||
* @Param - durMs - pulse width in ms.
|
||||
*/
|
||||
CTR_Code PCM::SetOneShotDurationMs(UINT8 idx,uint32_t durMs)
|
||||
{
|
||||
/* sanity check caller's param */
|
||||
if(idx > 8)
|
||||
return CTR_InvalidParamValue;
|
||||
/* get latest tx frame */
|
||||
CtreCanNode::txTask<PcmControlSetOneShotDur_t> toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());
|
||||
if(toFill.IsEmpty()){
|
||||
/* only send this out if caller wants to do one-shots */
|
||||
RegisterTx(CONTROL_3 | _deviceNumber, kCANPeriod);
|
||||
/* grab it */
|
||||
toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());
|
||||
}
|
||||
toFill->sol10MsPerUnit[idx] = std::min(durMs/10,(uint32_t)0xFF);
|
||||
/* apply the new data bytes */
|
||||
FlushTx(toFill);
|
||||
return CTR_OKAY;
|
||||
}
|
||||
|
||||
/* Get solenoid state
|
||||
*
|
||||
@@ -248,12 +314,36 @@ CTR_Code PCM::GetHardwareFault(bool &status)
|
||||
*
|
||||
* @Return - True/False - True if shorted compressor detected, false if otherwise
|
||||
*/
|
||||
CTR_Code PCM::GetCompressorFault(bool &status)
|
||||
CTR_Code PCM::GetCompressorCurrentTooHighFault(bool &status)
|
||||
{
|
||||
GET_PCM_STATUS();
|
||||
status = rx->faultCompCurrentTooHigh;
|
||||
return rx.err;
|
||||
}
|
||||
CTR_Code PCM::GetCompressorShortedStickyFault(bool &status)
|
||||
{
|
||||
GET_PCM_STATUS();
|
||||
status = rx->StickyFault_dItooHigh;
|
||||
return rx.err;
|
||||
}
|
||||
CTR_Code PCM::GetCompressorShortedFault(bool &status)
|
||||
{
|
||||
GET_PCM_STATUS();
|
||||
status = rx->Fault_dItooHigh;
|
||||
return rx.err;
|
||||
}
|
||||
CTR_Code PCM::GetCompressorNotConnectedStickyFault(bool &status)
|
||||
{
|
||||
GET_PCM_SOL_FAULTS();
|
||||
status = rx->StickyFault_CompNoCurrent;
|
||||
return rx.err;
|
||||
}
|
||||
CTR_Code PCM::GetCompressorNotConnectedFault(bool &status)
|
||||
{
|
||||
GET_PCM_SOL_FAULTS();
|
||||
status = rx->Fault_CompNoCurrent;
|
||||
return rx.err;
|
||||
}
|
||||
|
||||
/* Get solenoid fault value
|
||||
*
|
||||
@@ -271,7 +361,7 @@ CTR_Code PCM::GetSolenoidFault(bool &status)
|
||||
* @Return - True/False - True if solenoid had previously been shorted
|
||||
* (and sticky fault was not cleared), false if otherwise
|
||||
*/
|
||||
CTR_Code PCM::GetCompressorStickyFault(bool &status)
|
||||
CTR_Code PCM::GetCompressorCurrentTooHighStickyFault(bool &status)
|
||||
{
|
||||
GET_PCM_STATUS();
|
||||
status = rx->stickyFaultCompCurrentTooHigh;
|
||||
@@ -369,7 +459,7 @@ extern "C" {
|
||||
return ((PCM*) handle)->SetClosedLoopControl(param);
|
||||
}
|
||||
CTR_Code c_ClearStickyFaults(void * handle, INT8 param) {
|
||||
return ((PCM*) handle)->ClearStickyFaults(param);
|
||||
return ((PCM*) handle)->ClearStickyFaults();
|
||||
}
|
||||
CTR_Code c_GetSolenoid(void * handle, UINT8 idx, INT8 * status) {
|
||||
bool bstatus;
|
||||
@@ -410,7 +500,7 @@ extern "C" {
|
||||
}
|
||||
CTR_Code c_GetCompressorFault(void * handle, INT8*status) {
|
||||
bool bstatus;
|
||||
CTR_Code retval = ((PCM*) handle)->GetCompressorFault(bstatus);
|
||||
CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighFault(bstatus);
|
||||
*status = bstatus;
|
||||
return retval;
|
||||
}
|
||||
@@ -422,7 +512,7 @@ extern "C" {
|
||||
}
|
||||
CTR_Code c_GetCompressorStickyFault(void * handle, INT8*status) {
|
||||
bool bstatus;
|
||||
CTR_Code retval = ((PCM*) handle)->GetCompressorStickyFault(bstatus);
|
||||
CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighStickyFault(bstatus);
|
||||
*status = bstatus;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@ public:
|
||||
|
||||
/* Clears PCM sticky faults (indicators of past faults
|
||||
* @Return - CTR_Code - Error code (if any) for setting solenoid
|
||||
* @Param - clr - Clear / do not clear faults
|
||||
*/
|
||||
CTR_Code ClearStickyFaults(bool clr);
|
||||
CTR_Code ClearStickyFaults();
|
||||
|
||||
/* Get solenoid state
|
||||
*
|
||||
@@ -76,9 +75,9 @@ public:
|
||||
|
||||
/* Get compressor fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - status - True if shorted compressor detected, false if otherwise
|
||||
* @Param - status - True if abnormally high compressor current detected, false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorFault(bool &status);
|
||||
CTR_Code GetCompressorCurrentTooHighFault(bool &status);
|
||||
|
||||
/* Get solenoid fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
@@ -91,7 +90,29 @@ public:
|
||||
* @Param - status - True if solenoid had previously been shorted
|
||||
* (and sticky fault was not cleared), false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorStickyFault(bool &status);
|
||||
CTR_Code GetCompressorCurrentTooHighStickyFault(bool &status);
|
||||
/* Get compressor shorted sticky fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - status - True if compressor output is shorted, false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorShortedStickyFault(bool &status);
|
||||
/* Get compressor shorted fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - status - True if compressor output is shorted, false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorShortedFault(bool &status);
|
||||
/* Get compressor is not connected sticky fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - status - True if compressor current is too low,
|
||||
* indicating compressor is not connected, false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorNotConnectedStickyFault(bool &status);
|
||||
/* Get compressor is not connected fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - status - True if compressor current is too low,
|
||||
* indicating compressor is not connected, false if otherwise
|
||||
*/
|
||||
CTR_Code GetCompressorNotConnectedFault(bool &status);
|
||||
|
||||
/* Get solenoid sticky fault value
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
@@ -146,6 +167,21 @@ public:
|
||||
* @Param - status - Returns TRUE if PCM is enabled, FALSE if disabled
|
||||
*/
|
||||
CTR_Code isModuleEnabled(bool &status);
|
||||
|
||||
/* Get solenoid Blacklist status
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - idx - ID of solenoid [0,7] to fire one shot pulse.
|
||||
*/
|
||||
CTR_Code FireOneShotSolenoid(UINT8 idx);
|
||||
|
||||
/* Configure the pulse width of a solenoid channel for one-shot pulse.
|
||||
* Preprogrammed pulsewidth is 10ms resolute and can be between 20ms and 5.1s.
|
||||
* @Return - CTR_Code - Error code (if any)
|
||||
* @Param - idx - ID of solenoid [0,7] to configure.
|
||||
* @Param - durMs - pulse width in ms.
|
||||
*/
|
||||
CTR_Code SetOneShotDurationMs(UINT8 idx,uint32_t durMs);
|
||||
|
||||
};
|
||||
//------------------ C interface --------------------------------------------//
|
||||
extern "C" {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "interfaces/Accelerometer.h"
|
||||
#include "I2C.h"
|
||||
#include "LiveWindow/LiveWindowSendable.h"
|
||||
|
||||
/**
|
||||
* ADXL345 Accelerometer on I2C.
|
||||
@@ -14,7 +15,7 @@
|
||||
* This class allows access to a Analog Devices ADXL345 3-axis accelerometer on an I2C bus.
|
||||
* This class assumes the default (not alternate) sensor address of 0x1D (7-bit address).
|
||||
*/
|
||||
class ADXL345_I2C : public Accelerometer, public I2C
|
||||
class ADXL345_I2C : public Accelerometer, public I2C, public LiveWindowSendable
|
||||
{
|
||||
protected:
|
||||
static const uint8_t kAddress = 0x1D;
|
||||
@@ -48,6 +49,15 @@ public:
|
||||
virtual double GetAcceleration(Axes axis);
|
||||
virtual AllAxes GetAccelerations();
|
||||
|
||||
virtual std::string GetSmartDashboardType();
|
||||
virtual void InitTable(ITable *subtable);
|
||||
virtual void UpdateTable();
|
||||
virtual ITable* GetTable();
|
||||
virtual void StartLiveWindowMode() {}
|
||||
virtual void StopLiveWindowMode() {}
|
||||
|
||||
protected:
|
||||
//I2C* m_i2c;
|
||||
private:
|
||||
ITable *m_table;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "interfaces/Accelerometer.h"
|
||||
#include "SensorBase.h"
|
||||
#include "SPI.h"
|
||||
#include "LiveWindow/LiveWindowSendable.h"
|
||||
|
||||
class DigitalInput;
|
||||
class DigitalOutput;
|
||||
@@ -18,7 +19,7 @@ class DigitalOutput;
|
||||
* This class allows access to an Analog Devices ADXL345 3-axis accelerometer via SPI.
|
||||
* This class assumes the sensor is wired in 4-wire SPI mode.
|
||||
*/
|
||||
class ADXL345_SPI : public Accelerometer, public SensorBase
|
||||
class ADXL345_SPI : public Accelerometer, public SensorBase, public LiveWindowSendable
|
||||
{
|
||||
protected:
|
||||
static const uint8_t kPowerCtlRegister = 0x2D;
|
||||
@@ -52,9 +53,18 @@ public:
|
||||
virtual double GetAcceleration(Axes axis);
|
||||
virtual AllAxes GetAccelerations();
|
||||
|
||||
virtual std::string GetSmartDashboardType();
|
||||
virtual void InitTable(ITable *subtable);
|
||||
virtual void UpdateTable();
|
||||
virtual ITable* GetTable();
|
||||
virtual void StartLiveWindowMode() {}
|
||||
virtual void StopLiveWindowMode() {}
|
||||
|
||||
protected:
|
||||
void Init(Range range);
|
||||
|
||||
SPI* m_spi;
|
||||
SPI::Port m_port;
|
||||
private:
|
||||
ITable *m_table;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,14 @@ public:
|
||||
void SetClosedLoopControl(bool on);
|
||||
bool GetClosedLoopControl();
|
||||
|
||||
bool GetCompressorCurrentTooHighFault();
|
||||
bool GetCompressorCurrentTooHighStickyFault();
|
||||
bool GetCompressorShortedStickyFault();
|
||||
bool GetCompressorShortedFault();
|
||||
bool GetCompressorNotConnectedStickyFault();
|
||||
bool GetCompressorNotConnectedFault();
|
||||
void ClearAllPCMStickyFaults();
|
||||
|
||||
void UpdateTable();
|
||||
void StartLiveWindowMode();
|
||||
void StopLiveWindowMode();
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
bool GetDirection();
|
||||
void SetSamplesToAverage(int samplesToAverage);
|
||||
int GetSamplesToAverage();
|
||||
uint32_t GetIndex()
|
||||
uint32_t GetFPGAIndex()
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ public:
|
||||
virtual ~DoubleSolenoid();
|
||||
virtual void Set(Value value);
|
||||
virtual Value Get();
|
||||
bool IsFwdSolenoidBlackListed();
|
||||
bool IsRevSolenoidBlackListed();
|
||||
|
||||
void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew);
|
||||
void UpdateTable();
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
// CounterBase interface
|
||||
int32_t Get();
|
||||
int32_t GetRaw();
|
||||
int32_t GetEncodingScale();
|
||||
void Reset();
|
||||
double GetPeriod();
|
||||
void SetMaxPeriod(double maxPeriod);
|
||||
@@ -63,6 +64,11 @@ public:
|
||||
void InitTable(ITable *subTable);
|
||||
ITable * GetTable();
|
||||
|
||||
int32_t GetFPGAIndex()
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitEncoder(bool _reverseDirection, EncodingType encodingType);
|
||||
double DecodingScaleFactor();
|
||||
@@ -72,9 +78,11 @@ private:
|
||||
bool m_allocatedASource; // was the A source allocated locally?
|
||||
bool m_allocatedBSource; // was the B source allocated locally?
|
||||
void* m_encoder;
|
||||
int32_t m_index; // The encoder's FPGA index.
|
||||
double m_distancePerPulse; // distance of travel for each encoder tick
|
||||
Counter *m_counter; // Counter object for 1x and 2x encoding
|
||||
EncodingType m_encodingType; // Encoding type
|
||||
int32_t m_encodingScale; // 1x, 2x, or 4x, per the encodingType
|
||||
PIDSourceParameter m_pidSource; // Encoder parameter that sources a PID controller
|
||||
|
||||
ITable *m_table;
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
* Class implements the PWM generation in the FPGA.
|
||||
*
|
||||
* The values supplied as arguments for PWM outputs range from -1.0 to 1.0. They are mapped
|
||||
* to the hardware dependent values, in this case 0-255 for the FPGA.
|
||||
* to the hardware dependent values, in this case 0-2000 for the FPGA.
|
||||
* Changes are immediately sent to the FPGA, and the update occurs at the next
|
||||
* FPGA cycle. There is no delay.
|
||||
*
|
||||
* As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-255 values as follows:
|
||||
* - 255 = full "forward"
|
||||
* - 254 to 129 = linear scaling from "full forward" to "center"
|
||||
* - 128 = center value
|
||||
* - 127 to 2 = linear scaling from "center" to "full reverse"
|
||||
* - 1 = full "reverse"
|
||||
* As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-2000 values as follows:
|
||||
* - 2000 = maximum pulse width
|
||||
* - 1999 to 1001 = linear scaling from "full forward" to "center"
|
||||
* - 1000 = center value
|
||||
* - 999 to 2 = linear scaling from "center" to "full reverse"
|
||||
* - 1 = minimum pulse width (currently .5ms)
|
||||
* - 0 = disabled (i.e. PWM output is held low)
|
||||
*/
|
||||
class PWM : public SensorBase, public ITableListener, public LiveWindowSendable
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
#define __WPILIB_POWER_DISTRIBUTION_PANEL_H__
|
||||
|
||||
#include "SensorBase.h"
|
||||
#include "LiveWindow/LiveWindowSendable.h"
|
||||
|
||||
/**
|
||||
* Class for getting voltage, current, and temperature from the CAN PDP
|
||||
* @author Thomas Clark
|
||||
*/
|
||||
class PowerDistributionPanel : public SensorBase {
|
||||
class PowerDistributionPanel : public SensorBase, public LiveWindowSendable {
|
||||
public:
|
||||
PowerDistributionPanel();
|
||||
|
||||
@@ -26,6 +27,16 @@ class PowerDistributionPanel : public SensorBase {
|
||||
double GetTotalEnergy();
|
||||
void ResetTotalEnergy();
|
||||
void ClearStickyFaults();
|
||||
|
||||
void UpdateTable();
|
||||
void StartLiveWindowMode();
|
||||
void StopLiveWindowMode();
|
||||
std::string GetSmartDashboardType();
|
||||
void InitTable(ITable *subTable);
|
||||
ITable * GetTable();
|
||||
|
||||
private:
|
||||
ITable *m_table;
|
||||
};
|
||||
|
||||
#endif /* __WPILIB_POWER_DISTRIBUTION_PANEL_H__ */
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
virtual ~Solenoid();
|
||||
virtual void Set(bool on);
|
||||
virtual bool Get();
|
||||
bool IsBlackListed();
|
||||
|
||||
void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew);
|
||||
void UpdateTable();
|
||||
|
||||
@@ -20,6 +20,10 @@ public:
|
||||
virtual ~SolenoidBase();
|
||||
uint8_t GetAll();
|
||||
|
||||
uint8_t GetPCMSolenoidBlackList();
|
||||
bool GetPCMSolenoidVoltageStickyFault();
|
||||
bool GetPCMSolenoidVoltageFault();
|
||||
void ClearAllPCMStickyFaults();
|
||||
protected:
|
||||
explicit SolenoidBase(uint8_t pcmID);
|
||||
void Set(uint8_t value, uint8_t mask);
|
||||
|
||||
127
wpilibc/wpilibC++Devices/include/Vision/AxisCamera.h
Normal file
127
wpilibc/wpilibC++Devices/include/Vision/AxisCamera.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "Vision/ColorImage.h"
|
||||
#include "Vision/HSLImage.h"
|
||||
#include "nivision.h"
|
||||
|
||||
/**
|
||||
* Axis M1011 network camera
|
||||
*/
|
||||
class AxisCamera: public ErrorBase
|
||||
{
|
||||
public:
|
||||
enum WhiteBalance
|
||||
{
|
||||
kWhiteBalance_Automatic,
|
||||
kWhiteBalance_Hold,
|
||||
kWhiteBalance_FixedOutdoor1,
|
||||
kWhiteBalance_FixedOutdoor2,
|
||||
kWhiteBalance_FixedIndoor,
|
||||
kWhiteBalance_FixedFluorescent1,
|
||||
kWhiteBalance_FixedFluorescent2
|
||||
};
|
||||
|
||||
enum ExposureControl
|
||||
{
|
||||
kExposureControl_Automatic,
|
||||
kExposureControl_Hold,
|
||||
kExposureControl_FlickerFree50Hz,
|
||||
kExposureControl_FlickerFree60Hz
|
||||
};
|
||||
|
||||
enum Resolution
|
||||
{
|
||||
kResolution_640x480,
|
||||
kResolution_480x360,
|
||||
kResolution_320x240,
|
||||
kResolution_240x180,
|
||||
kResolution_176x144,
|
||||
kResolution_160x120,
|
||||
};
|
||||
|
||||
enum Rotation
|
||||
{
|
||||
kRotation_0, kRotation_180
|
||||
};
|
||||
|
||||
explicit AxisCamera(std::string const& cameraHost);
|
||||
virtual ~AxisCamera();
|
||||
|
||||
bool IsFreshImage() const;
|
||||
|
||||
int GetImage(Image *image);
|
||||
int GetImage(ColorImage *image);
|
||||
HSLImage *GetImage();
|
||||
int CopyJPEG(char **destImage, unsigned int &destImageSize, unsigned int &destImageBufferSize);
|
||||
|
||||
void WriteBrightness(int brightness);
|
||||
int GetBrightness();
|
||||
|
||||
void WriteWhiteBalance(WhiteBalance whiteBalance);
|
||||
WhiteBalance GetWhiteBalance();
|
||||
|
||||
void WriteColorLevel(int colorLevel);
|
||||
int GetColorLevel();
|
||||
|
||||
void WriteExposureControl(ExposureControl exposureControl);
|
||||
ExposureControl GetExposureControl();
|
||||
|
||||
void WriteExposurePriority(int exposurePriority);
|
||||
int GetExposurePriority();
|
||||
|
||||
void WriteMaxFPS(int maxFPS);
|
||||
int GetMaxFPS();
|
||||
|
||||
void WriteResolution(Resolution resolution);
|
||||
Resolution GetResolution();
|
||||
|
||||
void WriteCompression(int compression);
|
||||
int GetCompression();
|
||||
|
||||
void WriteRotation(Rotation rotation);
|
||||
Rotation GetRotation();
|
||||
|
||||
private:
|
||||
std::thread m_captureThread;
|
||||
std::string m_cameraHost;
|
||||
int m_cameraSocket;
|
||||
std::mutex m_captureMutex;
|
||||
|
||||
std::mutex m_imageDataMutex;
|
||||
std::vector<uint8_t> m_imageData;
|
||||
bool m_freshImage;
|
||||
|
||||
int m_brightness;
|
||||
WhiteBalance m_whiteBalance;
|
||||
int m_colorLevel;
|
||||
ExposureControl m_exposureControl;
|
||||
int m_exposurePriority;
|
||||
int m_maxFPS;
|
||||
Resolution m_resolution;
|
||||
int m_compression;
|
||||
Rotation m_rotation;
|
||||
bool m_parametersDirty;
|
||||
bool m_streamDirty;
|
||||
std::mutex m_parametersMutex;
|
||||
|
||||
bool m_done;
|
||||
|
||||
void Capture();
|
||||
void ReadImagesFromCamera();
|
||||
bool WriteParameters();
|
||||
|
||||
int CreateCameraSocket(std::string const& requestString, bool setError);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AxisCamera);
|
||||
};
|
||||
57
wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h
Normal file
57
wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Constants */
|
||||
#define LOG_DEBUG __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE
|
||||
#define LOG_INFO __FILE__,__FUNCTION__,__LINE__,INFO_TYPE
|
||||
#define LOG_ERROR __FILE__,__FUNCTION__,__LINE__,ERROR_TYPE
|
||||
#define LOG_CRITICAL __FILE__,__FUNCTION__,__LINE__,CRITICAL_TYPE
|
||||
#define LOG_FATAL __FILE__,__FUNCTION__,__LINE__,FATAL_TYPE
|
||||
#define LOG_DEBUG __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE
|
||||
|
||||
/* Enumerated Types */
|
||||
|
||||
/** debug levels */
|
||||
enum dprint_type {DEBUG_TYPE, INFO_TYPE, ERROR_TYPE, CRITICAL_TYPE, FATAL_TYPE};
|
||||
|
||||
/** debug output setting */
|
||||
typedef enum DebugOutputType_enum {
|
||||
DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE
|
||||
}DebugOutputType;
|
||||
|
||||
/* Enumerated Types */
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
/* debug */
|
||||
void SetDebugFlag ( DebugOutputType flag );
|
||||
void dprintf ( const char * tempString, ... ); /* Variable argument list */
|
||||
|
||||
/* set FRC ranges for drive */
|
||||
double RangeToNormalized(double pixel, int range);
|
||||
/* change normalized value to any range - used for servo */
|
||||
float NormalizeToRange(float normalizedValue, float minRange, float maxRange);
|
||||
float NormalizeToRange(float normalizedValue);
|
||||
|
||||
/* system utilities */
|
||||
void ShowActivity (char *fmt, ...);
|
||||
double ElapsedTime (double startTime);
|
||||
|
||||
/* servo panning utilities */
|
||||
class Servo;
|
||||
double SinPosition (double *period, double sinStart);
|
||||
void panInit();
|
||||
void panInit(double period);
|
||||
void panForTarget(Servo *panServo);
|
||||
void panForTarget(Servo *panServo, double sinStart);
|
||||
|
||||
/* config file read utilities */
|
||||
int processFile(char *inputFile, char *outputString, int lineNumber);
|
||||
int emptyString(char *string);
|
||||
void stripString(char *string);
|
||||
|
||||
39
wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h
Normal file
39
wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MonoImage.h"
|
||||
/**
|
||||
* Included for ParticleAnalysisReport definition
|
||||
* TODO: Eliminate this dependency!
|
||||
*/
|
||||
#include "Vision/VisionAPI.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class BinaryImage : public MonoImage
|
||||
{
|
||||
public:
|
||||
BinaryImage();
|
||||
virtual ~BinaryImage();
|
||||
int GetNumberParticles();
|
||||
ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber);
|
||||
void GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par);
|
||||
std::vector<ParticleAnalysisReport>* GetOrderedParticleAnalysisReports();
|
||||
BinaryImage *RemoveSmallObjects(bool connectivity8, int erosions);
|
||||
BinaryImage *RemoveLargeObjects(bool connectivity8, int erosions);
|
||||
BinaryImage *ConvexHull(bool connectivity8);
|
||||
BinaryImage *ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount);
|
||||
virtual void Write(const char *fileName);
|
||||
private:
|
||||
bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result);
|
||||
bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result);
|
||||
static double NormalizeFromRange(double position, int range);
|
||||
static bool CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2);
|
||||
};
|
||||
|
||||
65
wpilibc/wpilibC++Devices/include/Vision/ColorImage.h
Normal file
65
wpilibc/wpilibC++Devices/include/Vision/ColorImage.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ImageBase.h"
|
||||
#include "BinaryImage.h"
|
||||
#include "Threshold.h"
|
||||
|
||||
class ColorImage : public ImageBase
|
||||
{
|
||||
public:
|
||||
ColorImage(ImageType type);
|
||||
virtual ~ColorImage();
|
||||
BinaryImage *ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh);
|
||||
BinaryImage *ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh);
|
||||
BinaryImage *ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueHigh, int valueLow);
|
||||
BinaryImage *ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh);
|
||||
BinaryImage *ThresholdRGB(Threshold &threshold);
|
||||
BinaryImage *ThresholdHSL(Threshold &threshold);
|
||||
BinaryImage *ThresholdHSV(Threshold &threshold);
|
||||
BinaryImage *ThresholdHSI(Threshold &threshold);
|
||||
MonoImage *GetRedPlane();
|
||||
MonoImage *GetGreenPlane();
|
||||
MonoImage *GetBluePlane();
|
||||
MonoImage *GetHSLHuePlane();
|
||||
MonoImage *GetHSVHuePlane();
|
||||
MonoImage *GetHSIHuePlane();
|
||||
MonoImage *GetHSLSaturationPlane();
|
||||
MonoImage *GetHSVSaturationPlane();
|
||||
MonoImage *GetHSISaturationPlane();
|
||||
MonoImage *GetLuminancePlane();
|
||||
MonoImage *GetValuePlane();
|
||||
MonoImage *GetIntensityPlane();
|
||||
void ReplaceRedPlane(MonoImage *plane);
|
||||
void ReplaceGreenPlane(MonoImage *plane);
|
||||
void ReplaceBluePlane(MonoImage *plane);
|
||||
void ReplaceHSLHuePlane(MonoImage *plane);
|
||||
void ReplaceHSVHuePlane(MonoImage *plane);
|
||||
void ReplaceHSIHuePlane(MonoImage *plane);
|
||||
void ReplaceHSLSaturationPlane(MonoImage *plane);
|
||||
void ReplaceHSVSaturationPlane(MonoImage *plane);
|
||||
void ReplaceHSISaturationPlane(MonoImage *plane);
|
||||
void ReplaceLuminancePlane(MonoImage *plane);
|
||||
void ReplaceValuePlane(MonoImage *plane);
|
||||
void ReplaceIntensityPlane(MonoImage *plane);
|
||||
void ColorEqualize();
|
||||
void LuminanceEqualize();
|
||||
|
||||
private:
|
||||
BinaryImage *ComputeThreshold(ColorMode colorMode, int low1, int high1, int low2, int high2, int low3, int high3);
|
||||
void Equalize(bool allPlanes);
|
||||
MonoImage * ExtractColorPlane(ColorMode mode, int planeNumber);
|
||||
MonoImage * ExtractFirstColorPlane(ColorMode mode);
|
||||
MonoImage * ExtractSecondColorPlane(ColorMode mode);
|
||||
MonoImage * ExtractThirdColorPlane(ColorMode mode);
|
||||
void ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber);
|
||||
void ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane);
|
||||
void ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane);
|
||||
void ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane);
|
||||
};
|
||||
|
||||
30
wpilibc/wpilibC++Devices/include/Vision/FrcError.h
Normal file
30
wpilibc/wpilibC++Devices/include/Vision/FrcError.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Error Codes */
|
||||
#define ERR_VISION_GENERAL_ERROR 166000 //
|
||||
#define ERR_COLOR_NOT_FOUND 166100 // TrackAPI.cpp
|
||||
#define ERR_PARTICLE_TOO_SMALL 166101 // TrackAPI.cpp
|
||||
|
||||
#define ERR_CAMERA_FAILURE 166200 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_SOCKET_CREATE_FAILED 166201 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_CONNECT_FAILED 166202 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_STALE_IMAGE 166203 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_NOT_INITIALIZED 166204 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_NO_BUFFER_AVAILABLE 166205 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_HEADER_ERROR 166206 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_BLOCKING_TIMEOUT 166207 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_AUTHORIZATION_FAILED 166208 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_TASK_SPAWN_FAILED 166209 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE 166210 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_COMMAND_FAILURE 166211 // AxisCamera.cpp
|
||||
|
||||
/* error handling functions */
|
||||
int GetLastVisionError();
|
||||
const char* GetVisionErrorText(int errorCode);
|
||||
|
||||
22
wpilibc/wpilibC++Devices/include/Vision/HSLImage.h
Normal file
22
wpilibc/wpilibC++Devices/include/Vision/HSLImage.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorImage.h"
|
||||
|
||||
/**
|
||||
* A color image represented in HSL color space at 3 bytes per pixel.
|
||||
*/
|
||||
class HSLImage : public ColorImage
|
||||
{
|
||||
public:
|
||||
HSLImage();
|
||||
HSLImage(const char *fileName);
|
||||
virtual ~HSLImage();
|
||||
};
|
||||
|
||||
|
||||
27
wpilibc/wpilibC++Devices/include/Vision/ImageBase.h
Normal file
27
wpilibc/wpilibC++Devices/include/Vision/ImageBase.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nivision.h"
|
||||
#include "ErrorBase.h"
|
||||
|
||||
#define DEFAULT_BORDER_SIZE 3
|
||||
|
||||
class ImageBase : public ErrorBase
|
||||
{
|
||||
public:
|
||||
ImageBase(ImageType type);
|
||||
virtual ~ImageBase();
|
||||
virtual void Write(const char *fileName);
|
||||
int GetHeight();
|
||||
int GetWidth();
|
||||
Image *GetImaqImage();
|
||||
protected:
|
||||
Image *m_imaqImage;
|
||||
};
|
||||
|
||||
25
wpilibc/wpilibC++Devices/include/Vision/MonoImage.h
Normal file
25
wpilibc/wpilibC++Devices/include/Vision/MonoImage.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ImageBase.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class MonoImage : public ImageBase
|
||||
{
|
||||
public:
|
||||
MonoImage();
|
||||
virtual ~MonoImage();
|
||||
|
||||
std::vector<EllipseMatch> *DetectEllipses(EllipseDescriptor *ellipseDescriptor,
|
||||
CurveOptions *curveOptions,
|
||||
ShapeDetectionOptions *shapeDetectionOptions,
|
||||
ROI *roi);
|
||||
std::vector<EllipseMatch> * DetectEllipses(EllipseDescriptor *ellipseDescriptor);
|
||||
};
|
||||
|
||||
21
wpilibc/wpilibC++Devices/include/Vision/RGBImage.h
Normal file
21
wpilibc/wpilibC++Devices/include/Vision/RGBImage.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorImage.h"
|
||||
|
||||
/**
|
||||
* A color image represented in RGB color space at 3 bytes per pixel.
|
||||
*/
|
||||
class RGBImage : public ColorImage
|
||||
{
|
||||
public:
|
||||
RGBImage();
|
||||
RGBImage(const char *fileName);
|
||||
virtual ~RGBImage();
|
||||
};
|
||||
|
||||
28
wpilibc/wpilibC++Devices/include/Vision/Threshold.h
Normal file
28
wpilibc/wpilibC++Devices/include/Vision/Threshold.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Color threshold values.
|
||||
* This object represnts the threshold values for any type of color object
|
||||
* that is used in a threshhold operation. It simplifies passing values
|
||||
* around in a program for color detection.
|
||||
*/
|
||||
class Threshold
|
||||
{
|
||||
public:
|
||||
int plane1Low;
|
||||
int plane1High;
|
||||
int plane2Low;
|
||||
int plane2High;
|
||||
int plane3Low;
|
||||
int plane3High;
|
||||
Threshold(int plane1Low, int plane1High,
|
||||
int plane2Low, int plane2High,
|
||||
int plane3Low, int plane3High);
|
||||
};
|
||||
|
||||
148
wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h
Normal file
148
wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nivision.h"
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define DEFAULT_BORDER_SIZE 3 //VisionAPI.frcCreateImage
|
||||
#define DEFAULT_SATURATION_THRESHOLD 40 //TrackAPI.FindColor
|
||||
|
||||
/* Forward Declare Data Structures */
|
||||
typedef struct FindEdgeOptions_struct FindEdgeOptions;
|
||||
typedef struct CircularEdgeReport_struct CircularEdgeReport;
|
||||
|
||||
/* Data Structures */
|
||||
|
||||
/** frcParticleAnalysis returns this structure */
|
||||
typedef struct ParticleAnalysisReport_struct {
|
||||
int imageHeight;
|
||||
int imageWidth;
|
||||
double imageTimestamp;
|
||||
int particleIndex; // the particle index analyzed
|
||||
/* X-coordinate of the point representing the average position of the
|
||||
* total particle mass, assuming every point in the particle has a constant density */
|
||||
int center_mass_x; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_X
|
||||
/* Y-coordinate of the point representing the average position of the
|
||||
* total particle mass, assuming every point in the particle has a constant density */
|
||||
int center_mass_y; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_Y
|
||||
double center_mass_x_normalized; //Center of mass x value normalized to -1.0 to +1.0 range
|
||||
double center_mass_y_normalized; //Center of mass y value normalized to -1.0 to +1.0 range
|
||||
/* Area of the particle */
|
||||
double particleArea; // MeasurementType: IMAQ_MT_AREA
|
||||
/* Bounding Rectangle */
|
||||
Rect boundingRect; // left/top/width/height
|
||||
/* Percentage of the particle Area covering the Image Area. */
|
||||
double particleToImagePercent; // MeasurementType: IMAQ_MT_AREA_BY_IMAGE_AREA
|
||||
/* Percentage of the particle Area in relation to its Particle and Holes Area */
|
||||
double particleQuality; // MeasurementType: IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA
|
||||
} ParticleAnalysisReport;
|
||||
|
||||
/** Tracking functions return this structure */
|
||||
typedef struct ColorReport_struct {
|
||||
int numberParticlesFound; // Number of particles found for this color
|
||||
int largestParticleNumber; // The particle index of the largest particle
|
||||
/* Color information */
|
||||
float particleHueMax; // HistogramReport: hue max
|
||||
float particleHueMin; // HistogramReport: hue max
|
||||
float particleHueMean; // HistogramReport: hue mean
|
||||
float particleSatMax; // HistogramReport: saturation max
|
||||
float particleSatMin; // HistogramReport: saturation max
|
||||
float particleSatMean; // HistogramReport: saturation mean
|
||||
float particleLumMax; // HistogramReport: luminance max
|
||||
float particleLumMin; // HistogramReport: luminance max
|
||||
float particleLumMean; // HistogramReport: luminance mean
|
||||
} ColorReport;
|
||||
|
||||
|
||||
/* Image Management functions */
|
||||
|
||||
/* Create: calls imaqCreateImage. Border size is set to some default value */
|
||||
Image* frcCreateImage( ImageType type );
|
||||
|
||||
/* Dispose: calls imaqDispose */
|
||||
int frcDispose( void* object );
|
||||
int frcDispose( const char* filename, ... ) ;
|
||||
|
||||
/* Copy: calls imaqDuplicateImage */
|
||||
int frcCopyImage( Image* dest, const Image* source );
|
||||
|
||||
/* Image Extraction: Crop: calls imaqScale */
|
||||
int frcCrop( Image* dest, const Image* source, Rect rect );
|
||||
|
||||
/* Image Extraction: Scale: calls imaqScale. Scales entire image */
|
||||
int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode );
|
||||
|
||||
/* Read Image : calls imaqReadFile */
|
||||
int frcReadImage( Image* image, const char* fileName );
|
||||
/* Write Image : calls imaqWriteFile */
|
||||
int frcWriteImage( const Image* image, const char* fileName);
|
||||
|
||||
/* Measure Intensity functions */
|
||||
|
||||
/* Histogram: calls imaqHistogram */
|
||||
HistogramReport* frcHistogram( const Image* image, int numClasses, float min, float max, Rect rect );
|
||||
/* Color Histogram: calls imaqColorHistogram2 */
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask);
|
||||
|
||||
/* Get Pixel Value: calls imaqGetPixel */
|
||||
int frcGetPixelValue( const Image* image, Point pixel, PixelValue* value );
|
||||
|
||||
/* Particle Analysis functions */
|
||||
|
||||
/* Particle Filter: calls imaqParticleFilter3 */
|
||||
int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles);
|
||||
int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options, int* numParticles);
|
||||
/* Morphology: calls imaqMorphology */
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method);
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement);
|
||||
/* Reject Border: calls imaqRejectBorder */
|
||||
int frcRejectBorder(Image* dest, Image* source);
|
||||
int frcRejectBorder(Image* dest, Image* source, int connectivity8);
|
||||
/* Count Particles: calls imaqCountParticles */
|
||||
int frcCountParticles(Image* image, int* numParticles);
|
||||
/* Particle Analysis Report: calls imaqMeasureParticle */
|
||||
int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par);
|
||||
|
||||
/* Image Enhancement functions */
|
||||
|
||||
/* Equalize: calls imaqEqualize */
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max);
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask);
|
||||
|
||||
/* Color Equalize: calls imaqColorEqualize */
|
||||
int frcColorEqualize(Image* dest, const Image* source);
|
||||
int frcColorEqualize(Image* dest, const Image* source, int colorEqualization);
|
||||
|
||||
/* Image Thresholding & Conversion functions */
|
||||
|
||||
/* Smart Threshold: calls imaqLocalThreshold */
|
||||
int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight,
|
||||
LocalThresholdMethod method, double deviationWeight, ObjectType type);
|
||||
int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight,
|
||||
LocalThresholdMethod method, double deviationWeight, ObjectType type, float replaceValue);
|
||||
|
||||
/* Simple Threshold: calls imaqThreshold */
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue);
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax);
|
||||
|
||||
/* Color/Hue Threshold: calls imaqColorThreshold */
|
||||
int frcColorThreshold(Image* dest, const Image* source, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range, const Range* plane3Range);
|
||||
int frcColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range, const Range* plane3Range);
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange);
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation);
|
||||
|
||||
/* Extract ColorHue Plane: calls imaqExtractColorPlanes */
|
||||
int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3);
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane);
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation);
|
||||
|
||||
@@ -85,5 +85,13 @@
|
||||
#include "Utility.h"
|
||||
#include "Victor.h"
|
||||
#include "VictorSP.h"
|
||||
#include "Vision/AxisCamera.h"
|
||||
#include "Vision/BinaryImage.h"
|
||||
#include "Vision/ColorImage.h"
|
||||
#include "Vision/HSLImage.h"
|
||||
#include "Vision/ImageBase.h"
|
||||
#include "Vision/MonoImage.h"
|
||||
#include "Vision/RGBImage.h"
|
||||
#include "Vision/Threshold.h"
|
||||
// XXX: #include "Vision/AxisCamera.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
@@ -5339,5 +5339,7 @@ IMAQ_FUNC ReadTextReport* IMAQ_STDCALL imaqReadText(const Image* image, c
|
||||
IMAQ_FUNC ThresholdData* IMAQ_STDCALL imaqAutoThreshold(Image* dest, Image* source, int numClasses, ThresholdMethod method);
|
||||
IMAQ_FUNC ColorHistogramReport* IMAQ_STDCALL imaqColorHistogram(Image* image, int numClasses, ColorMode mode, const Image* mask);
|
||||
IMAQ_FUNC RakeReport* IMAQ_STDCALL imaqRake(const Image* image, const ROI* roi, RakeDirection direction, EdgeProcess process, const RakeOptions* options);
|
||||
|
||||
IMAQ_FUNC int IMAQ_STDCALL Priv_ReadJPEGString_C(Image* image, const unsigned char* string, unsigned int stringLength);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "ADXL345_I2C.h"
|
||||
#include "I2C.h"
|
||||
#include "HAL/HAL.hpp"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
const uint8_t ADXL345_I2C::kAddress;
|
||||
const uint8_t ADXL345_I2C::kPowerCtlRegister;
|
||||
@@ -17,6 +18,7 @@ constexpr double ADXL345_I2C::kGsPerLSB;
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param port The I2C port the accelerometer is attached to
|
||||
* @param range The range (+ or -) that the accelerometer will measure.
|
||||
*/
|
||||
ADXL345_I2C::ADXL345_I2C(Port port, Range range):
|
||||
@@ -30,6 +32,7 @@ ADXL345_I2C::ADXL345_I2C(Port port, Range range):
|
||||
SetRange(range);
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_ADXL345, HALUsageReporting::kADXL345_I2C, 0);
|
||||
LiveWindow::GetInstance()->AddSensor("ADXL345_I2C", port, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +87,7 @@ double ADXL345_I2C::GetAcceleration(ADXL345_I2C::Axes axis)
|
||||
/**
|
||||
* Get the acceleration of all axes in Gs.
|
||||
*
|
||||
* @return Acceleration measured on all axes of the ADXL345 in Gs.
|
||||
* @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
|
||||
*/
|
||||
ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations()
|
||||
{
|
||||
@@ -100,3 +103,24 @@ ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations()
|
||||
//}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ADXL345_I2C::GetSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void ADXL345_I2C::InitTable(ITable *subtable) {
|
||||
m_table = subtable;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
void ADXL345_I2C::UpdateTable() {
|
||||
if (m_table != NULL) {
|
||||
m_table->PutNumber("X", GetX());
|
||||
m_table->PutNumber("Y", GetY());
|
||||
m_table->PutNumber("Z", GetZ());
|
||||
}
|
||||
}
|
||||
|
||||
ITable* ADXL345_I2C::GetTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,25 @@
|
||||
#include "DigitalInput.h"
|
||||
#include "DigitalOutput.h"
|
||||
#include "SPI.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
const uint8_t ADXL345_SPI::kPowerCtlRegister;
|
||||
const uint8_t ADXL345_SPI::kDataFormatRegister;
|
||||
const uint8_t ADXL345_SPI::kDataRegister;
|
||||
constexpr double ADXL345_SPI::kGsPerLSB;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param port The SPI port the accelerometer is attached to
|
||||
* @param range The range (+ or -) that the accelerometer will measure.
|
||||
*/
|
||||
ADXL345_SPI::ADXL345_SPI(SPI::Port port, ADXL345_SPI::Range range)
|
||||
{
|
||||
m_port = port;
|
||||
Init(range);
|
||||
LiveWindow::GetInstance()->AddSensor("ADXL345_SPI", port, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +115,7 @@ double ADXL345_SPI::GetAcceleration(ADXL345_SPI::Axes axis)
|
||||
/**
|
||||
* Get the acceleration of all axes in Gs.
|
||||
*
|
||||
* @return Acceleration measured on all axes of the ADXL345 in Gs.
|
||||
* @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
|
||||
*/
|
||||
ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations()
|
||||
{
|
||||
@@ -131,3 +140,24 @@ ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations()
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ADXL345_SPI::GetSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void ADXL345_SPI::InitTable(ITable *subtable) {
|
||||
m_table = subtable;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
void ADXL345_SPI::UpdateTable() {
|
||||
if (m_table != NULL) {
|
||||
m_table->PutNumber("X", GetX());
|
||||
m_table->PutNumber("Y", GetY());
|
||||
m_table->PutNumber("Z", GetZ());
|
||||
}
|
||||
}
|
||||
|
||||
ITable* ADXL345_SPI::GetTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ void AnalogAccelerometer::InitAccelerometer()
|
||||
|
||||
/**
|
||||
* Create a new instance of an accelerometer.
|
||||
*
|
||||
* The constructor allocates desired analog input.
|
||||
* @param channel The channel number for the analog input the accelerometer is connected to
|
||||
*/
|
||||
AnalogAccelerometer::AnalogAccelerometer(int32_t channel)
|
||||
{
|
||||
@@ -38,6 +38,7 @@ AnalogAccelerometer::AnalogAccelerometer(int32_t channel)
|
||||
* Make a new instance of accelerometer given an AnalogInput. This is particularly
|
||||
* useful if the port is going to be read as an analog channel as well as through
|
||||
* the Accelerometer class.
|
||||
* @param channel The existing AnalogInput object for the analog input the accelerometer is connected to
|
||||
*/
|
||||
AnalogAccelerometer::AnalogAccelerometer(AnalogInput *channel)
|
||||
{
|
||||
@@ -80,7 +81,7 @@ float AnalogAccelerometer::GetAcceleration()
|
||||
* Set the accelerometer sensitivity.
|
||||
*
|
||||
* This sets the sensitivity of the accelerometer used for calculating the acceleration.
|
||||
* The sensitivity varys by accelerometer model. There are constants defined for various models.
|
||||
* The sensitivity varies by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param sensitivity The sensitivity of accelerometer in Volts per G.
|
||||
*/
|
||||
@@ -92,7 +93,7 @@ void AnalogAccelerometer::SetSensitivity(float sensitivity)
|
||||
/**
|
||||
* Set the voltage that corresponds to 0 G.
|
||||
*
|
||||
* The zero G voltage varys by accelerometer model. There are constants defined for various models.
|
||||
* The zero G voltage varies by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param zero The zero G voltage.
|
||||
*/
|
||||
|
||||
@@ -54,7 +54,7 @@ void AnalogInput::InitAnalogInput(uint32_t channel)
|
||||
/**
|
||||
* Construct an analog input.
|
||||
*
|
||||
* @param channel The channel number to represent.
|
||||
* @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
|
||||
*/
|
||||
AnalogInput::AnalogInput(uint32_t channel)
|
||||
{
|
||||
@@ -86,9 +86,9 @@ int16_t AnalogInput::GetValue()
|
||||
|
||||
/**
|
||||
* Get a sample from the output of the oversample and average engine for this channel.
|
||||
* The sample is 12-bit + the value configured in SetOversampleBits().
|
||||
* The sample is 12-bit + the bits configured in SetOversampleBits().
|
||||
* The value configured in SetAverageBits() will cause this value to be averaged 2**bits number of samples.
|
||||
* This is not a sliding window. The sample will not change until 2**(OversamplBits + AverageBits) samples
|
||||
* This is not a sliding window. The sample will not change until 2**(OversampleBits + AverageBits) samples
|
||||
* have been acquired from the module on this channel.
|
||||
* Use GetAverageVoltage() to get the analog value in calibrated units.
|
||||
* @return A sample from the oversample and average engine for this channel.
|
||||
@@ -176,7 +176,7 @@ uint32_t AnalogInput::GetChannel()
|
||||
|
||||
/**
|
||||
* Set the number of averaging bits.
|
||||
* This sets the number of averaging bits. The actual number of averaged samples is 2**bits.
|
||||
* This sets the number of averaging bits. The actual number of averaged samples is 2^bits.
|
||||
* Use averaging to improve the stability of your measurement at the expense of sampling rate.
|
||||
* The averaging is done automatically in the FPGA.
|
||||
*
|
||||
@@ -192,7 +192,7 @@ void AnalogInput::SetAverageBits(uint32_t bits)
|
||||
|
||||
/**
|
||||
* Get the number of averaging bits previously configured.
|
||||
* This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2**bits.
|
||||
* This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2^bits.
|
||||
* The averaging is done automatically in the FPGA.
|
||||
*
|
||||
* @return Number of bits of averaging previously configured.
|
||||
@@ -207,7 +207,7 @@ uint32_t AnalogInput::GetAverageBits()
|
||||
|
||||
/**
|
||||
* Set the number of oversample bits.
|
||||
* This sets the number of oversample bits. The actual number of oversampled values is 2**bits.
|
||||
* This sets the number of oversample bits. The actual number of oversampled values is 2^bits.
|
||||
* Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
|
||||
* The oversampling is done automatically in the FPGA.
|
||||
*
|
||||
@@ -224,7 +224,7 @@ void AnalogInput::SetOversampleBits(uint32_t bits)
|
||||
/**
|
||||
* Get the number of oversample bits previously configured.
|
||||
* This gets the number of oversample bits from the FPGA. The actual number of oversampled values is
|
||||
* 2**bits. The oversampling is done automatically in the FPGA.
|
||||
* 2^bits. The oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @return Number of bits of oversampling previously configured.
|
||||
*/
|
||||
@@ -265,7 +265,7 @@ void AnalogInput::InitAccumulator()
|
||||
|
||||
|
||||
/**
|
||||
* Set an inital value for the accumulator.
|
||||
* Set an initial value for the accumulator.
|
||||
*
|
||||
* This will be added to all values returned to the user.
|
||||
* @param initialValue The value that the accumulator should start from when reset.
|
||||
@@ -301,11 +301,11 @@ void AnalogInput::ResetAccumulator()
|
||||
* Set the center value of the accumulator.
|
||||
*
|
||||
* The center value is subtracted from each A/D value before it is added to the accumulator. This
|
||||
* is used for the center value of devices like gyros and accelerometers to make integration work
|
||||
* and to take the device offset into account when integrating.
|
||||
* is used for the center value of devices like gyros and accelerometers to
|
||||
* take the device offset into account when integrating.
|
||||
*
|
||||
* This center value is based on the output of the oversampled and averaged source from channel 1.
|
||||
* Because of this, any non-zero oversample bits will affect the size of the value for this field.
|
||||
* This center value is based on the output of the oversampled and averaged source from the accumulator
|
||||
* channel. Because of this, any non-zero oversample bits will affect the size of the value for this field.
|
||||
*/
|
||||
void AnalogInput::SetAccumulatorCenter(int32_t center)
|
||||
{
|
||||
@@ -317,6 +317,7 @@ void AnalogInput::SetAccumulatorCenter(int32_t center)
|
||||
|
||||
/**
|
||||
* Set the accumulator's deadband.
|
||||
* @param
|
||||
*/
|
||||
void AnalogInput::SetAccumulatorDeadband(int32_t deadband)
|
||||
{
|
||||
@@ -329,7 +330,7 @@ void AnalogInput::SetAccumulatorDeadband(int32_t deadband)
|
||||
/**
|
||||
* Read the accumulated value.
|
||||
*
|
||||
* Read the value that has been accumulating on channel 1.
|
||||
* Read the value that has been accumulating.
|
||||
* The accumulator is attached after the oversample and average engine.
|
||||
*
|
||||
* @return The 64-bit value accumulated since the last Reset().
|
||||
@@ -379,8 +380,9 @@ void AnalogInput::GetAccumulatorOutput(int64_t *value, uint32_t *count)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sample rate for all analog channels.
|
||||
*
|
||||
* Set the sample rate per channel for all analog channels.
|
||||
* The maximum rate is 500kS/s divided by the number of channels in use.
|
||||
* This is 62500 samples/s per channel.
|
||||
* @param samplesPerSecond The number of samples per second.
|
||||
*/
|
||||
void AnalogInput::SetSampleRate(float samplesPerSecond)
|
||||
|
||||
@@ -44,12 +44,17 @@ void AnalogOutput::InitAnalogOutput(uint32_t channel) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an anlog output on the given channel
|
||||
* Construct an analog output on the given channel.
|
||||
* All analog outputs are located on the MXP port.
|
||||
* @param The channel number on the roboRIO to represent.
|
||||
*/
|
||||
AnalogOutput::AnalogOutput(uint32_t channel) {
|
||||
InitAnalogOutput(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor. Frees analog output resource
|
||||
*/
|
||||
AnalogOutput::~AnalogOutput() {
|
||||
outputs->Free(m_channel);
|
||||
}
|
||||
|
||||
@@ -11,21 +11,42 @@ void AnalogPotentiometer::initPot(AnalogInput *input, double fullRange, double o
|
||||
m_analog_input = input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an Analog Potentiometer object from a channel number.
|
||||
* @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
|
||||
* @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
|
||||
* @param offset The angular value (in desired units) representing the angular output at 0V.
|
||||
*/
|
||||
AnalogPotentiometer::AnalogPotentiometer(int channel, double fullRange, double offset) {
|
||||
m_init_analog_input = true;
|
||||
initPot(new AnalogInput(channel), fullRange, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an Analog Potentiometer object from an existing Analog Input pointer.
|
||||
* @param channel The existing Analog Input pointer
|
||||
* @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
|
||||
* @param offset The angular value (in desired units) representing the angular output at 0V.
|
||||
*/
|
||||
AnalogPotentiometer::AnalogPotentiometer(AnalogInput *input, double fullRange, double offset) {
|
||||
m_init_analog_input = false;
|
||||
initPot(input, fullRange, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an Analog Potentiometer object from an existing Analog Input reference.
|
||||
* @param channel The existing Analog Input reference
|
||||
* @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
|
||||
* @param offset The angular value (in desired units) representing the angular output at 0V.
|
||||
*/
|
||||
AnalogPotentiometer::AnalogPotentiometer(AnalogInput &input, double fullRange, double offset) {
|
||||
m_init_analog_input = false;
|
||||
initPot(&input, fullRange, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor. Releases the Analog Input resource if it was allocated by this object
|
||||
*/
|
||||
AnalogPotentiometer::~AnalogPotentiometer() {
|
||||
if(m_init_analog_input){
|
||||
delete m_analog_input;
|
||||
@@ -36,7 +57,7 @@ AnalogPotentiometer::~AnalogPotentiometer() {
|
||||
/**
|
||||
* Get the current reading of the potentiometer.
|
||||
*
|
||||
* @return The current position of the potentiometer.
|
||||
* @return The current position of the potentiometer (in the units used for fullRaneg and offset).
|
||||
*/
|
||||
double AnalogPotentiometer::Get() {
|
||||
return (m_analog_input->GetVoltage() / ControllerPower::GetVoltage5V()) * m_fullRange + m_offset;
|
||||
|
||||
@@ -29,7 +29,7 @@ void AnalogTrigger::InitTrigger(uint32_t channel)
|
||||
/**
|
||||
* Constructor for an analog trigger given a channel number.
|
||||
*
|
||||
* @param channel The analog channel (0..7).
|
||||
* @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
|
||||
*/
|
||||
AnalogTrigger::AnalogTrigger(int32_t channel)
|
||||
{
|
||||
@@ -40,6 +40,7 @@ AnalogTrigger::AnalogTrigger(int32_t channel)
|
||||
* Construct an analog trigger given an analog input.
|
||||
* This should be used in the case of sharing an analog channel between the
|
||||
* trigger and an analog input object.
|
||||
* @param channel The pointer to the existing AnalogInput object
|
||||
*/
|
||||
AnalogTrigger::AnalogTrigger(AnalogInput *input)
|
||||
{
|
||||
@@ -57,6 +58,8 @@ AnalogTrigger::~AnalogTrigger()
|
||||
* Set the upper and lower limits of the analog trigger.
|
||||
* The limits are given in ADC codes. If oversampling is used, the units must be scaled
|
||||
* appropriately.
|
||||
* @param lower The lower limit of the trigger in ADC codes (12-bit values).
|
||||
* @param upper The upper limit of the trigger in ADC codes (12-bit values).
|
||||
*/
|
||||
void AnalogTrigger::SetLimitsRaw(int32_t lower, int32_t upper)
|
||||
{
|
||||
@@ -69,6 +72,8 @@ void AnalogTrigger::SetLimitsRaw(int32_t lower, int32_t upper)
|
||||
/**
|
||||
* Set the upper and lower limits of the analog trigger.
|
||||
* The limits are given as floating point voltage values.
|
||||
* @param lower The lower limit of the trigger in Volts.
|
||||
* @param upper The upper limit of the trigger in Volts.
|
||||
*/
|
||||
void AnalogTrigger::SetLimitsVoltage(float lower, float upper)
|
||||
{
|
||||
@@ -82,6 +87,7 @@ void AnalogTrigger::SetLimitsVoltage(float lower, float upper)
|
||||
* Configure the analog trigger to use the averaged vs. raw values.
|
||||
* If the value is true, then the averaged value is selected for the analog trigger, otherwise
|
||||
* the immediate value is used.
|
||||
* @param useAveragedValue If true, use the Averaged value, otherwise use the instantaneous reading
|
||||
*/
|
||||
void AnalogTrigger::SetAveraged(bool useAveragedValue)
|
||||
{
|
||||
@@ -95,6 +101,7 @@ void AnalogTrigger::SetAveraged(bool useAveragedValue)
|
||||
* Configure the analog trigger to use a filtered value.
|
||||
* The analog trigger will operate with a 3 point average rejection filter. This is designed to
|
||||
* help with 360 degree pot applications for the period where the pot crosses through zero.
|
||||
* @param useFilteredValue If true, use the 3 point rejection filter, otherwise use the unfiltered value
|
||||
*/
|
||||
void AnalogTrigger::SetFiltered(bool useFilteredValue)
|
||||
{
|
||||
@@ -118,7 +125,7 @@ uint32_t AnalogTrigger::GetIndex()
|
||||
/**
|
||||
* Return the InWindow output of the analog trigger.
|
||||
* True if the analog input is between the upper and lower limits.
|
||||
* @return The InWindow output of the analog trigger.
|
||||
* @return True if the analog input is between the upper and lower limits.
|
||||
*/
|
||||
bool AnalogTrigger::GetInWindow()
|
||||
{
|
||||
@@ -134,7 +141,7 @@ bool AnalogTrigger::GetInWindow()
|
||||
* True if above upper limit.
|
||||
* False if below lower limit.
|
||||
* If in Hysteresis, maintain previous state.
|
||||
* @return The TriggerState output of the analog trigger.
|
||||
* @return True if above upper limit. False if below lower limit. If in Hysteresis, maintain previous state.
|
||||
*/
|
||||
bool AnalogTrigger::GetTriggerState()
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "BuiltInAccelerometer.h"
|
||||
#include "HAL/HAL.hpp"
|
||||
#include "WPIErrors.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -18,6 +19,7 @@ BuiltInAccelerometer::BuiltInAccelerometer(Range range)
|
||||
SetRange(range);
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_Accelerometer, 0, 0, "Built-in accelerometer");
|
||||
LiveWindow::GetInstance()->AddSensor((std::string)"BuiltInAccel",0, this);
|
||||
}
|
||||
|
||||
BuiltInAccelerometer::~BuiltInAccelerometer()
|
||||
@@ -62,7 +64,7 @@ double BuiltInAccelerometer::GetZ()
|
||||
}
|
||||
|
||||
std::string BuiltInAccelerometer::GetSmartDashboardType() {
|
||||
return "Accelerometer";
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void BuiltInAccelerometer::InitTable(ITable *subtable) {
|
||||
|
||||
@@ -105,6 +105,8 @@ float CANTalon::Get()
|
||||
*/
|
||||
void CANTalon::Set(float value, uint8_t syncGroup)
|
||||
{
|
||||
/* feed safety helper since caller just updated our output */
|
||||
m_safetyHelper->Feed();
|
||||
if(m_controlEnabled) {
|
||||
m_setPoint = value;
|
||||
CTR_Code status;
|
||||
|
||||
@@ -15,7 +15,7 @@ void Compressor::InitCompressor(uint8_t pcmID) {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Uses the default solenoid module number
|
||||
* Uses the default PCM ID (0)
|
||||
*/
|
||||
Compressor::Compressor() {
|
||||
InitCompressor(GetDefaultSolenoidModule());
|
||||
@@ -24,7 +24,7 @@ Compressor::Compressor() {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param module The module number to use (1 or 2)
|
||||
* @param module The PCM ID to use (0-62)
|
||||
*/
|
||||
Compressor::Compressor(uint8_t pcmID) {
|
||||
InitCompressor(pcmID);
|
||||
@@ -35,20 +35,21 @@ Compressor::~Compressor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts closed-loop control
|
||||
* Starts closed-loop control. Note that closed loop control is enabled by default.
|
||||
*/
|
||||
void Compressor::Start() {
|
||||
SetClosedLoopControl(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops closed-loop control
|
||||
* Stops closed-loop control. Note that closed loop control is enabled by default.
|
||||
*/
|
||||
void Compressor::Stop() {
|
||||
SetClosedLoopControl(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if compressor output is active
|
||||
* @return true if the compressor is on
|
||||
*/
|
||||
bool Compressor::Enabled() {
|
||||
@@ -65,6 +66,7 @@ bool Compressor::Enabled() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the pressure switch is triggered
|
||||
* @return true if pressure is low
|
||||
*/
|
||||
bool Compressor::GetPressureSwitchValue() {
|
||||
@@ -82,6 +84,7 @@ bool Compressor::GetPressureSwitchValue() {
|
||||
|
||||
|
||||
/**
|
||||
* Query how much current the compressor is drawing
|
||||
* @return The current through the compressor, in amps
|
||||
*/
|
||||
float Compressor::GetCompressorCurrent() {
|
||||
@@ -101,6 +104,7 @@ float Compressor::GetCompressorCurrent() {
|
||||
/**
|
||||
* Enables or disables automatically turning the compressor on when the
|
||||
* pressure is low.
|
||||
* @param on Set to true to enable closed loop control of the compressor. False to disable.
|
||||
*/
|
||||
void Compressor::SetClosedLoopControl(bool on) {
|
||||
int32_t status = 0;
|
||||
@@ -115,6 +119,7 @@ void Compressor::SetClosedLoopControl(bool on) {
|
||||
/**
|
||||
* Returns true if the compressor will automatically turn on when the
|
||||
* pressure is low.
|
||||
* @return True if closed loop control of the compressor is enabled. False if disabled.
|
||||
*/
|
||||
bool Compressor::GetClosedLoopControl() {
|
||||
int32_t status = 0;
|
||||
@@ -129,6 +134,132 @@ bool Compressor::GetClosedLoopControl() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if the compressor output has been disabled due to high current draw.
|
||||
* @return true if PCM is in fault state : Compressor Drive is
|
||||
* disabled due to compressor current being too high.
|
||||
*/
|
||||
bool Compressor::GetCompressorCurrentTooHighFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorCurrentTooHighFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Query if the compressor output has been disabled due to high current draw (sticky).
|
||||
* A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
|
||||
* @return true if PCM sticky fault is set : Compressor Drive is
|
||||
* disabled due to compressor current being too high.
|
||||
*/
|
||||
bool Compressor::GetCompressorCurrentTooHighStickyFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorCurrentTooHighStickyFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Query if the compressor output has been disabled due to a short circuit (sticky).
|
||||
* A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
|
||||
* @return true if PCM sticky fault is set : Compressor output
|
||||
* appears to be shorted.
|
||||
*/
|
||||
bool Compressor::GetCompressorShortedStickyFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorShortedStickyFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Query if the compressor output has been disabled due to a short circuit.
|
||||
* @return true if PCM is in fault state : Compressor output
|
||||
* appears to be shorted.
|
||||
*/
|
||||
bool Compressor::GetCompressorShortedFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorShortedFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Query if the compressor output does not appear to be wired (sticky).
|
||||
* A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
|
||||
* @return true if PCM sticky fault is set : Compressor does not
|
||||
* appear to be wired, i.e. compressor is
|
||||
* not drawing enough current.
|
||||
*/
|
||||
bool Compressor::GetCompressorNotConnectedStickyFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorNotConnectedStickyFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Query if the compressor output does not appear to be wired.
|
||||
* @return true if PCM is in fault state : Compressor does not
|
||||
* appear to be wired, i.e. compressor is
|
||||
* not drawing enough current.
|
||||
*/
|
||||
bool Compressor::GetCompressorNotConnectedFault() {
|
||||
int32_t status = 0;
|
||||
bool value;
|
||||
|
||||
value = getCompressorNotConnectedFault(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Clear ALL sticky faults inside PCM that Compressor is wired to.
|
||||
*
|
||||
* If a sticky fault is set, then it will be persistently cleared. Compressor drive
|
||||
* maybe momentarily disable while flags are being cleared. Care should be
|
||||
* taken to not call this too frequently, otherwise normal compressor
|
||||
* functionality may be prevented.
|
||||
*
|
||||
* If no sticky faults are set then this call will have no effect.
|
||||
*/
|
||||
void Compressor::ClearAllPCMStickyFaults() {
|
||||
int32_t status = 0;
|
||||
|
||||
clearAllPCMStickyFaults(m_pcm_pointer, &status);
|
||||
|
||||
if(status) {
|
||||
wpi_setWPIError(Timeout);
|
||||
}
|
||||
}
|
||||
void Compressor::UpdateTable() {
|
||||
if(m_table) {
|
||||
m_table->PutBoolean("Enabled", Enabled());
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
/**
|
||||
* Get the input voltage to the robot controller
|
||||
* @return The controller input voltage value
|
||||
* @return The controller input voltage value in Volts
|
||||
*/
|
||||
double ControllerPower::GetInputVoltage() {
|
||||
int32_t status = 0;
|
||||
@@ -24,7 +24,7 @@ double ControllerPower::GetInputVoltage() {
|
||||
|
||||
/**
|
||||
* Get the input current to the robot controller
|
||||
* @return The controller input current value
|
||||
* @return The controller input current value in Amps
|
||||
*/
|
||||
double ControllerPower::GetInputCurrent() {
|
||||
int32_t status = 0;
|
||||
@@ -35,7 +35,7 @@ double ControllerPower::GetInputCurrent() {
|
||||
|
||||
/**
|
||||
* Get the voltage of the 6V rail
|
||||
* @return The controller 6V rail voltage value
|
||||
* @return The controller 6V rail voltage value in Volts
|
||||
*/
|
||||
double ControllerPower::GetVoltage6V() {
|
||||
int32_t status = 0;
|
||||
@@ -46,7 +46,7 @@ double ControllerPower::GetVoltage6V() {
|
||||
|
||||
/**
|
||||
* Get the current output of the 6V rail
|
||||
* @return The controller 6V rail output current value
|
||||
* @return The controller 6V rail output current value in Amps
|
||||
*/
|
||||
double ControllerPower::GetCurrent6V() {
|
||||
int32_t status = 0;
|
||||
@@ -58,7 +58,7 @@ double ControllerPower::GetCurrent6V() {
|
||||
/**
|
||||
* Get the enabled state of the 6V rail. The rail may be disabled due to a controller
|
||||
* brownout, a short circuit on the rail, or controller over-voltage
|
||||
* @return The controller 6V rail enabled value
|
||||
* @return The controller 6V rail enabled value. True for enabled.
|
||||
*/
|
||||
bool ControllerPower::GetEnabled6V() {
|
||||
int32_t status = 0;
|
||||
@@ -69,7 +69,7 @@ bool ControllerPower::GetEnabled6V() {
|
||||
|
||||
/**
|
||||
* Get the count of the total current faults on the 6V rail since the controller has booted
|
||||
* @return The number of faults
|
||||
* @return The number of faults.
|
||||
*/
|
||||
int ControllerPower::GetFaultCount6V() {
|
||||
int32_t status = 0;
|
||||
@@ -80,6 +80,7 @@ int ControllerPower::GetFaultCount6V() {
|
||||
|
||||
/**
|
||||
* Get the voltage of the 5V rail
|
||||
* @return The controller 5V rail voltage value in Volts
|
||||
*/
|
||||
double ControllerPower::GetVoltage5V() {
|
||||
int32_t status = 0;
|
||||
@@ -90,6 +91,7 @@ double ControllerPower::GetVoltage5V() {
|
||||
|
||||
/**
|
||||
* Get the current output of the 5V rail
|
||||
* @return The controller 5V rail output current value in Amps
|
||||
*/
|
||||
double ControllerPower::GetCurrent5V() {
|
||||
int32_t status = 0;
|
||||
@@ -101,7 +103,7 @@ double ControllerPower::GetCurrent5V() {
|
||||
/**
|
||||
* Get the enabled state of the 5V rail. The rail may be disabled due to a controller
|
||||
* brownout, a short circuit on the rail, or controller over-voltage
|
||||
* @return The controller 5V rail enabled value
|
||||
* @return The controller 5V rail enabled value. True for enabled.
|
||||
*/
|
||||
bool ControllerPower::GetEnabled5V() {
|
||||
int32_t status = 0;
|
||||
@@ -123,6 +125,7 @@ int ControllerPower::GetFaultCount5V() {
|
||||
|
||||
/**
|
||||
* Get the voltage of the 3.3V rail
|
||||
* @return The controller 3.3V rail voltage value in Volts
|
||||
*/
|
||||
double ControllerPower::GetVoltage3V3() {
|
||||
int32_t status = 0;
|
||||
@@ -133,6 +136,7 @@ double ControllerPower::GetVoltage3V3() {
|
||||
|
||||
/**
|
||||
* Get the current output of the 3.3V rail
|
||||
* @return The controller 3.3V rail output current value in Amps
|
||||
*/
|
||||
double ControllerPower::GetCurrent3V3() {
|
||||
int32_t status = 0;
|
||||
@@ -145,7 +149,7 @@ double ControllerPower::GetCurrent3V3() {
|
||||
/**
|
||||
* Get the enabled state of the 3.3V rail. The rail may be disabled due to a controller
|
||||
* brownout, a short circuit on the rail, or controller over-voltage
|
||||
* @return The controller 3.3V rail enabled value
|
||||
* @return The controller 3.3V rail enabled value. True for enabled.
|
||||
*/
|
||||
bool ControllerPower::GetEnabled3V3() {
|
||||
int32_t status = 0;
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
* This creates a ChipObject counter and initializes status variables appropriately
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param mode The counter mode
|
||||
*/
|
||||
void Counter::InitCounter(Mode mode)
|
||||
{
|
||||
m_table = NULL;
|
||||
|
||||
int32_t status = 0;
|
||||
uint32_t index = 0;
|
||||
m_counter = initializeCounter(mode, &index, &status);
|
||||
m_index = 0;
|
||||
m_counter = initializeCounter(mode, &m_index, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
|
||||
m_upSource = NULL;
|
||||
@@ -31,12 +32,14 @@ void Counter::InitCounter(Mode mode)
|
||||
m_allocatedUpSource = false;
|
||||
m_allocatedDownSource = false;
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_Counter, index, mode);
|
||||
SetMaxPeriod(.5);
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_Counter, m_index, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a counter where no sources are selected.
|
||||
* Then they all must be selected by calling functions to specify the upsource and the downsource
|
||||
* They all must be selected by calling functions to specify the upsource and the downsource
|
||||
* independently.
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
@@ -50,11 +53,12 @@ Counter::Counter() :
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a counter from a Digital Input.
|
||||
* Create an instance of a counter from a Digital Source (such as a Digital Input).
|
||||
* This is used if an existing digital input is to be shared by multiple other objects such
|
||||
* as encoders.
|
||||
* as encoders or if the Digital Source is not a Digital Input channel (such as an Analog Trigger).
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param source A pointer to the existing DigitalSource object. It will be set as the Up Source.
|
||||
*/
|
||||
Counter::Counter(DigitalSource *source) :
|
||||
m_upSource(NULL),
|
||||
@@ -66,6 +70,14 @@ Counter::Counter(DigitalSource *source) :
|
||||
ClearDownSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a counter from a Digital Source (such as a Digital Input).
|
||||
* This is used if an existing digital input is to be shared by multiple other objects such
|
||||
* as encoders or if the Digital Source is not a Digital Input channel (such as an Analog Trigger).
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param source A reference to the existing DigitalSource object. It will be set as the Up Source.
|
||||
*/
|
||||
Counter::Counter(DigitalSource &source) :
|
||||
m_upSource(NULL),
|
||||
m_downSource(NULL),
|
||||
@@ -81,6 +93,7 @@ Counter::Counter(DigitalSource &source) :
|
||||
* Create an up-Counter instance given a channel.
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP
|
||||
*/
|
||||
Counter::Counter(int32_t channel) :
|
||||
m_upSource(NULL),
|
||||
@@ -98,6 +111,7 @@ Counter::Counter(int32_t channel) :
|
||||
* Use the trigger state output from the analog trigger.
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param trigger The pointer to the existing AnalogTrigger object.
|
||||
*/
|
||||
Counter::Counter(AnalogTrigger *trigger) :
|
||||
m_upSource(NULL),
|
||||
@@ -110,6 +124,14 @@ Counter::Counter(AnalogTrigger *trigger) :
|
||||
m_allocatedUpSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object.
|
||||
* Create an instance of a simple up-Counter given an analog trigger.
|
||||
* Use the trigger state output from the analog trigger.
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
* @param trigger The reference to the existing AnalogTrigger object.
|
||||
*/
|
||||
Counter::Counter(AnalogTrigger &trigger) :
|
||||
m_upSource(NULL),
|
||||
m_downSource(NULL),
|
||||
@@ -121,6 +143,15 @@ Counter::Counter(AnalogTrigger &trigger) :
|
||||
m_allocatedUpSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object.
|
||||
* Creates a full up-down counter given two Digital Sources
|
||||
* @param encodingType The quadrature decoding mode (1x or 2x)
|
||||
* @param upSource The pointer to the DigitalSource to set as the up source
|
||||
* @param downSource The pointer to the DigitalSource to set as the down source
|
||||
* @param inverted True to invert the output (reverse the direction)
|
||||
*/
|
||||
|
||||
Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted) :
|
||||
m_upSource(NULL),
|
||||
m_downSource(NULL),
|
||||
@@ -176,6 +207,7 @@ Counter::~Counter()
|
||||
|
||||
/**
|
||||
* Set the upsource for the counter as a digital input channel.
|
||||
* @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP
|
||||
*/
|
||||
void Counter::SetUpSource(int32_t channel)
|
||||
{
|
||||
@@ -209,6 +241,7 @@ void Counter::SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerType trigge
|
||||
/**
|
||||
* Set the source object that causes the counter to count up.
|
||||
* Set the up counting DigitalSource.
|
||||
* @param source Pointer to the DigitalSource object to set as the up source
|
||||
*/
|
||||
void Counter::SetUpSource(DigitalSource *source)
|
||||
{
|
||||
@@ -236,6 +269,7 @@ void Counter::SetUpSource(DigitalSource *source)
|
||||
/**
|
||||
* Set the source object that causes the counter to count up.
|
||||
* Set the up counting DigitalSource.
|
||||
* @param source Reference to the DigitalSource object to set as the up source
|
||||
*/
|
||||
void Counter::SetUpSource(DigitalSource &source)
|
||||
{
|
||||
@@ -244,7 +278,9 @@ void Counter::SetUpSource(DigitalSource &source)
|
||||
|
||||
/**
|
||||
* Set the edge sensitivity on an up counting source.
|
||||
* Set the up source to either detect rising edges or falling edges.
|
||||
* Set the up source to either detect rising edges or falling edges or both.
|
||||
* @param risingEdge True to trigger on rising edges
|
||||
* @param fallingEdge True to trigger on falling edges
|
||||
*/
|
||||
void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
|
||||
{
|
||||
@@ -277,6 +313,7 @@ void Counter::ClearUpSource()
|
||||
|
||||
/**
|
||||
* Set the down counting source to be a digital input channel.
|
||||
* @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP
|
||||
*/
|
||||
void Counter::SetDownSource(int32_t channel)
|
||||
{
|
||||
@@ -310,6 +347,7 @@ void Counter::SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerType trig
|
||||
/**
|
||||
* Set the source object that causes the counter to count down.
|
||||
* Set the down counting DigitalSource.
|
||||
* @param source Pointer to the DigitalSource object to set as the down source
|
||||
*/
|
||||
void Counter::SetDownSource(DigitalSource *source)
|
||||
{
|
||||
@@ -337,6 +375,7 @@ void Counter::SetDownSource(DigitalSource *source)
|
||||
/**
|
||||
* Set the source object that causes the counter to count down.
|
||||
* Set the down counting DigitalSource.
|
||||
* @param source Reference to the DigitalSource object to set as the down source
|
||||
*/
|
||||
void Counter::SetDownSource(DigitalSource &source)
|
||||
{
|
||||
@@ -346,6 +385,8 @@ void Counter::SetDownSource(DigitalSource &source)
|
||||
/**
|
||||
* Set the edge sensitivity on a down counting source.
|
||||
* Set the down source to either detect rising edges or falling edges.
|
||||
* @param risingEdge True to trigger on rising edges
|
||||
* @param fallingEdge True to trigger on falling edges
|
||||
*/
|
||||
void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge)
|
||||
{
|
||||
@@ -484,11 +525,11 @@ void Counter::Reset()
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Get the Period of the most recent count.
|
||||
* Returns the time interval of the most recent count. This can be used for velocity calculations
|
||||
* to determine shaft speed.
|
||||
* @returns The period of the last two pulses in units of seconds.
|
||||
* @returns The period between the last two pulses in units of seconds.
|
||||
*/
|
||||
double Counter::GetPeriod()
|
||||
{
|
||||
@@ -525,6 +566,7 @@ void Counter::SetMaxPeriod(double maxPeriod)
|
||||
* output (except when there have been no events since an FPGA reset) and you will likely not
|
||||
* see the stopped bit become true (since it is updated at the end of an average and there are
|
||||
* no samples to average).
|
||||
* @param enabled True to enable update when empty
|
||||
*/
|
||||
void Counter::SetUpdateWhenEmpty(bool enabled)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ void DigitalInput::InitDigitalInput(uint32_t channel)
|
||||
* Create an instance of a Digital Input class.
|
||||
* Creates a digital input given a channel.
|
||||
*
|
||||
* @param channel The digital channel (0..19).
|
||||
* @param channel The DIO channel 0-9 are on-board, 10-25 are on the MXP port
|
||||
*/
|
||||
DigitalInput::DigitalInput(uint32_t channel)
|
||||
{
|
||||
@@ -67,7 +67,7 @@ DigitalInput::~DigitalInput()
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Get the value from a digital input channel.
|
||||
* Retrieve the value of a single digital input channel from the FPGA.
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@ void DigitalOutput::InitDigitalOutput(uint32_t channel)
|
||||
* Create an instance of a digital output.
|
||||
* Create a digital output given a channel.
|
||||
*
|
||||
* @param channel The digital channel (0..19)
|
||||
* @param channel The digital channel 0-9 are on-board, 10-25 are on the MXP port
|
||||
*/
|
||||
DigitalOutput::DigitalOutput(uint32_t channel)
|
||||
{
|
||||
@@ -63,6 +63,7 @@ DigitalOutput::~DigitalOutput()
|
||||
/**
|
||||
* Set the value of a digital output.
|
||||
* Set the value of a digital output to either one (true) or zero (false).
|
||||
* @param value 1 (true) for high, 0 (false) for disabled
|
||||
*/
|
||||
void DigitalOutput::Set(uint32_t value)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
/**
|
||||
* Common function to implement constructor behavior.
|
||||
* Common function to implement constructor behaviour.
|
||||
*/
|
||||
void DoubleSolenoid::InitSolenoid()
|
||||
{
|
||||
@@ -59,9 +59,9 @@ void DoubleSolenoid::InitSolenoid()
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
* Uses the default PCM ID of 0
|
||||
* @param forwardChannel The forward channel number on the PCM.
|
||||
* @param reverseChannel The reverse channel number on the PCM.
|
||||
*/
|
||||
DoubleSolenoid::DoubleSolenoid(uint32_t forwardChannel, uint32_t reverseChannel)
|
||||
: SolenoidBase (GetDefaultSolenoidModule())
|
||||
@@ -101,7 +101,7 @@ DoubleSolenoid::~DoubleSolenoid()
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
*
|
||||
* @param value Move the solenoid to forward, reverse, or don't move it.
|
||||
* @param value The value to set (Off, Forward or Reverse)
|
||||
*/
|
||||
void DoubleSolenoid::Set(Value value)
|
||||
{
|
||||
@@ -138,6 +138,32 @@ DoubleSolenoid::Value DoubleSolenoid::Get()
|
||||
if (value & m_reverseMask) return kReverse;
|
||||
return kOff;
|
||||
}
|
||||
/**
|
||||
* Check if the forward solenoid is blacklisted.
|
||||
* If a solenoid is shorted, it is added to the blacklist and
|
||||
* disabled until power cycle, or until faults are cleared.
|
||||
* @see ClearAllPCMStickyFaults()
|
||||
*
|
||||
* @return If solenoid is disabled due to short.
|
||||
*/
|
||||
bool DoubleSolenoid::IsFwdSolenoidBlackListed()
|
||||
{
|
||||
int blackList = GetPCMSolenoidBlackList();
|
||||
return (blackList & m_forwardMask) ? 1 : 0;
|
||||
}
|
||||
/**
|
||||
* Check if the reverse solenoid is blacklisted.
|
||||
* If a solenoid is shorted, it is added to the blacklist and
|
||||
* disabled until power cycle, or until faults are cleared.
|
||||
* @see ClearAllPCMStickyFaults()
|
||||
*
|
||||
* @return If solenoid is disabled due to short.
|
||||
*/
|
||||
bool DoubleSolenoid::IsRevSolenoidBlackListed()
|
||||
{
|
||||
int blackList = GetPCMSolenoidBlackList();
|
||||
return (blackList & m_reverseMask) ? 1 : 0;
|
||||
}
|
||||
|
||||
void DoubleSolenoid::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) {
|
||||
Value lvalue = kOff;
|
||||
|
||||
@@ -116,6 +116,7 @@ void DriverStation::Run()
|
||||
|
||||
/**
|
||||
* Return a pointer to the singleton DriverStation.
|
||||
* @return Pointer to the DS instance
|
||||
*/
|
||||
DriverStation* DriverStation::GetInstance()
|
||||
{
|
||||
@@ -146,7 +147,7 @@ void DriverStation::GetData()
|
||||
/**
|
||||
* Read the battery voltage.
|
||||
*
|
||||
* @return The battery voltage.
|
||||
* @return The battery voltage in Volts.
|
||||
*/
|
||||
float DriverStation::GetBatteryVoltage()
|
||||
{
|
||||
@@ -157,6 +158,10 @@ float DriverStation::GetBatteryVoltage()
|
||||
return voltage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports errors related to unplugged joysticks
|
||||
* Throttles the errors so that they don't overwhelm the DS
|
||||
*/
|
||||
void DriverStation::ReportJoystickUnpluggedError(std::string message) {
|
||||
double currentTime = Timer::GetFPGATimestamp();
|
||||
if (currentTime > m_nextMessageTime) {
|
||||
@@ -165,10 +170,11 @@ void DriverStation::ReportJoystickUnpluggedError(std::string message) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the number of axis on a given joystick port
|
||||
/**
|
||||
* Returns the number of axes on a given joystick port
|
||||
*
|
||||
* @param stick The joystick port number
|
||||
* @return the number of axis on the indicated joystick
|
||||
* @return The number of axes on the indicated joystick
|
||||
*/
|
||||
int DriverStation::GetStickAxisCount(uint32_t stick)
|
||||
{
|
||||
@@ -182,10 +188,11 @@ int DriverStation::GetStickAxisCount(uint32_t stick)
|
||||
return joystickAxes.count;
|
||||
}
|
||||
|
||||
/** Returns the number of POVs on a given joystick port
|
||||
/**
|
||||
* Returns the number of POVs on a given joystick port
|
||||
*
|
||||
* @param stick The joystick port number
|
||||
* @return thenumber of POVs on the indicated joystick
|
||||
* @return The number of POVs on the indicated joystick
|
||||
*/
|
||||
int DriverStation::GetStickPOVCount(uint32_t stick)
|
||||
{
|
||||
@@ -199,7 +206,8 @@ int DriverStation::GetStickPOVCount(uint32_t stick)
|
||||
return joystickPOVs.count;
|
||||
}
|
||||
|
||||
/** Returns the number of buttons on a given joystick port
|
||||
/**
|
||||
* Returns the number of buttons on a given joystick port
|
||||
*
|
||||
* @param stick The joystick port number
|
||||
* @return The number of buttons on the indicated joystick
|
||||
@@ -322,6 +330,10 @@ bool DriverStation::GetStickButton(uint32_t stick, uint8_t button)
|
||||
return ((0x1 << (button-1)) & m_joystickButtons[stick].buttons) !=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DS has enabled the robot
|
||||
* @return True if the robot is enabled and the DS is connected
|
||||
*/
|
||||
bool DriverStation::IsEnabled()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -330,6 +342,10 @@ bool DriverStation::IsEnabled()
|
||||
return controlWord.enabled && controlWord.dsAttached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the robot is disabled
|
||||
* @return True if the robot is explicitly disabled or the DS is not connected
|
||||
*/
|
||||
bool DriverStation::IsDisabled()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -338,6 +354,10 @@ bool DriverStation::IsDisabled()
|
||||
return !(controlWord.enabled && controlWord.dsAttached);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DS is commanding autonomous mode
|
||||
* @return True if the robot is being commanded to be in autonomous mode
|
||||
*/
|
||||
bool DriverStation::IsAutonomous()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -346,6 +366,10 @@ bool DriverStation::IsAutonomous()
|
||||
return controlWord.autonomous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DS is commanding teleop mode
|
||||
* @return True if the robot is being commanded to be in teleop mode
|
||||
*/
|
||||
bool DriverStation::IsOperatorControl()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -354,6 +378,10 @@ bool DriverStation::IsOperatorControl()
|
||||
return !(controlWord.autonomous || controlWord.test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DS is commanding test mode
|
||||
* @return True if the robot is being commanded to be in test mode
|
||||
*/
|
||||
bool DriverStation::IsTest()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -361,6 +389,10 @@ bool DriverStation::IsTest()
|
||||
return controlWord.test;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DS is attached
|
||||
* @return True if the DS is connected to the robot
|
||||
*/
|
||||
bool DriverStation::IsDSAttached()
|
||||
{
|
||||
HALControlWord controlWord;
|
||||
@@ -369,6 +401,11 @@ bool DriverStation::IsDSAttached()
|
||||
return controlWord.dsAttached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the FPGA outputs are enabled. The outputs may be disabled if the robot is disabled
|
||||
* or e-stopped, the watchdog has expired, or if the roboRIO browns out.
|
||||
* @return True if the FPGA outputs are enabled.
|
||||
*/
|
||||
bool DriverStation::IsSysActive()
|
||||
{
|
||||
int32_t status = 0;
|
||||
@@ -377,6 +414,10 @@ bool DriverStation::IsSysActive()
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the system is browned out.
|
||||
* @return True if the system is browned out
|
||||
*/
|
||||
bool DriverStation::IsSysBrownedOut()
|
||||
{
|
||||
int32_t status = 0;
|
||||
@@ -388,7 +429,7 @@ bool DriverStation::IsSysBrownedOut()
|
||||
/**
|
||||
* Has a new control packet from the driver station arrived since the last time this function was called?
|
||||
* Warning: If you call this function from more than one place at the same time,
|
||||
* you will not get the get the intended behavior
|
||||
* you will not get the get the intended behaviour.
|
||||
* @return True if the control data has been updated since the last call.
|
||||
*/
|
||||
bool DriverStation::IsNewControlData()
|
||||
@@ -398,7 +439,6 @@ bool DriverStation::IsNewControlData()
|
||||
|
||||
/**
|
||||
* Is the driver station attached to a Field Management System?
|
||||
* Note: This does not work with the Blue DS.
|
||||
* @return True if the robot is competing on a field being controlled by a Field Management System
|
||||
*/
|
||||
bool DriverStation::IsFMSAttached()
|
||||
@@ -411,7 +451,7 @@ bool DriverStation::IsFMSAttached()
|
||||
/**
|
||||
* Return the alliance that the driver station says it is on.
|
||||
* This could return kRed or kBlue
|
||||
* @return The Alliance enum
|
||||
* @return The Alliance enum (kRed, kBlue or kInvalid)
|
||||
*/
|
||||
DriverStation::Alliance DriverStation::GetAlliance()
|
||||
{
|
||||
@@ -435,7 +475,7 @@ DriverStation::Alliance DriverStation::GetAlliance()
|
||||
/**
|
||||
* Return the driver station location on the field
|
||||
* This could return 1, 2, or 3
|
||||
* @return The location of the driver station
|
||||
* @return The location of the driver station (1-3, 0 for invalid)
|
||||
*/
|
||||
uint32_t DriverStation::GetLocation()
|
||||
{
|
||||
@@ -469,13 +509,12 @@ void DriverStation::WaitForData()
|
||||
|
||||
/**
|
||||
* Return the approximate match time
|
||||
* The FMS does not currently send the official match time to the robots
|
||||
* This returns the time since the enable signal sent from the Driver Station
|
||||
* At the beginning of autonomous, the time is reset to 0.0 seconds
|
||||
* At the beginning of teleop, the time is reset to +15.0 seconds
|
||||
* If the robot is disabled, this returns 0.0 seconds
|
||||
* Warning: This is not an official time (so it cannot be used to argue with referees)
|
||||
* @return Match time in seconds since the beginning of autonomous
|
||||
* The FMS does not send an official match time to the robots, but does send an approximate match time.
|
||||
* The value will count down the time remaining in the current period (auto or teleop).
|
||||
* Warning: This is not an official time (so it cannot be used to dispute ref calls or guarantee that a function
|
||||
* will trigger before the match ends)
|
||||
* The Practice Match function of the DS approximates the behaviour seen on the field.
|
||||
* @return Time remaining in current match period (auto or teleop)
|
||||
*/
|
||||
double DriverStation::GetMatchTime()
|
||||
{
|
||||
|
||||
@@ -28,11 +28,12 @@ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
|
||||
{
|
||||
m_table = NULL;
|
||||
m_encodingType = encodingType;
|
||||
int32_t index = 0;
|
||||
m_index = 0;
|
||||
switch (encodingType)
|
||||
{
|
||||
case k4X:
|
||||
{
|
||||
m_encodingScale = 4;
|
||||
if (m_aSource->StatusIsFatal())
|
||||
{
|
||||
CloneError(m_aSource);
|
||||
@@ -44,28 +45,32 @@ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
|
||||
return;
|
||||
}
|
||||
int32_t status = 0;
|
||||
int32_t index = 0;
|
||||
m_encoder = initializeEncoder(m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(),
|
||||
m_aSource->GetAnalogTriggerForRouting(),
|
||||
m_bSource->GetModuleForRouting(), m_bSource->GetChannelForRouting(),
|
||||
m_bSource->GetAnalogTriggerForRouting(),
|
||||
reverseDirection, &index, &status);
|
||||
reverseDirection, &m_index, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
m_counter = NULL;
|
||||
SetMaxPeriod(.5);
|
||||
break;
|
||||
}
|
||||
case k1X:
|
||||
case k2X:
|
||||
{
|
||||
m_encodingScale = encodingType == k1X ? 1 : 2;
|
||||
m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
|
||||
index = m_counter->GetIndex();
|
||||
m_index = m_counter->GetFPGAIndex();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
wpi_setErrorWithContext(-1, "Invalid encodingType argument");
|
||||
break;
|
||||
}
|
||||
m_distancePerPulse = 1.0;
|
||||
m_pidSource = kDistance;
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_Encoder, index, encodingType);
|
||||
HALReport(HALUsageReporting::kResourceType_Encoder, m_index, encodingType);
|
||||
LiveWindow::GetInstance()->AddSensor("Encoder", m_aSource->GetChannelForRouting(), this);
|
||||
}
|
||||
|
||||
@@ -75,8 +80,8 @@ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
|
||||
*
|
||||
* The counter will start counting immediately.
|
||||
*
|
||||
* @param aChannel The a channel digital input channel.
|
||||
* @param bChannel The b channel digital input channel.
|
||||
* @param aChannel The a channel DIO channel. 0-9 are on-board, 10-25 are on the MXP port
|
||||
* @param bChannel The b channel DIO channel. 0-9 are on-board, 10-25 are on the MXP port
|
||||
* @param reverseDirection represents the orientation of the encoder and inverts the output values
|
||||
* if necessary so forward represents positive values.
|
||||
* @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
|
||||
@@ -177,6 +182,12 @@ Encoder::~Encoder()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The encoding scale factor 1x, 2x, or 4x, per the requested encodingType.
|
||||
* Used to divide raw edge counts down to spec'd counts.
|
||||
*/
|
||||
int32_t Encoder::GetEncodingScale() { return m_encodingScale; }
|
||||
|
||||
/**
|
||||
* Gets the raw value from the encoder.
|
||||
* The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
|
||||
@@ -231,7 +242,7 @@ void Encoder::Reset()
|
||||
/**
|
||||
* Returns the period of the most recent pulse.
|
||||
* Returns the period of the most recent Encoder pulse in seconds.
|
||||
* This method compenstates for the decoding type.
|
||||
* This method compensates for the decoding type.
|
||||
*
|
||||
* @deprecated Use GetRate() in favor of this method. This returns unscaled periods and GetRate() scales using value from SetDistancePerPulse().
|
||||
*
|
||||
|
||||
@@ -23,8 +23,8 @@ void GearTooth::EnableDirectionSensing(bool directionSensitive)
|
||||
/**
|
||||
* Construct a GearTooth sensor given a channel.
|
||||
*
|
||||
* @param channel The GPIO channel that the sensor is connected to.
|
||||
* @param directionSensitive Enable the pulse length decoding in hardware to specify count direction.
|
||||
* @param channel The DIO channel that the sensor is connected to. 0-9 are on-board, 10-25 are on the MXP.
|
||||
* @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
GearTooth::GearTooth(uint32_t channel, bool directionSensitive)
|
||||
: Counter(channel)
|
||||
@@ -35,10 +35,10 @@ GearTooth::GearTooth(uint32_t channel, bool directionSensitive)
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a digital input.
|
||||
* This should be used when sharing digial inputs.
|
||||
* This should be used when sharing digital inputs.
|
||||
*
|
||||
* @param source An object that fully descibes the input that the sensor is connected to.
|
||||
* @param directionSensitive Enable the pulse length decoding in hardware to specify count direction.
|
||||
* @param source A pointer to the existing DigitalSource object (such as a DigitalInput)
|
||||
* @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
GearTooth::GearTooth(DigitalSource *source, bool directionSensitive)
|
||||
: Counter(source)
|
||||
@@ -46,6 +46,13 @@ GearTooth::GearTooth(DigitalSource *source, bool directionSensitive)
|
||||
EnableDirectionSensing(directionSensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a digital input.
|
||||
* This should be used when sharing digital inputs.
|
||||
*
|
||||
* @param source A reference to the existing DigitalSource object (such as a DigitalInput)
|
||||
* @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
GearTooth::GearTooth(DigitalSource &source, bool directionSensitive): Counter(source)
|
||||
{
|
||||
EnableDirectionSensing(directionSensitive);
|
||||
|
||||
@@ -19,8 +19,8 @@ constexpr float Gyro::kDefaultVoltsPerDegreePerSecond;
|
||||
|
||||
/**
|
||||
* Initialize the gyro.
|
||||
* Calibrate the gyro by running for a number of samples and computing the center value for this
|
||||
* part. Then use the center value as the Accumulator center value for subsequent measurements.
|
||||
* Calibrate the gyro by running for a number of samples and computing the center value.
|
||||
* Then use the center value as the Accumulator center value for subsequent measurements.
|
||||
* It's important to make sure that the robot is not moving while the centering calculations are
|
||||
* in progress, this is typically done when the robot is first turned on while it's sitting at
|
||||
* rest before the competition starts.
|
||||
@@ -71,9 +71,10 @@ void Gyro::InitGyro()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with only a channel..
|
||||
* Gyro constructor using the Analog Input channel number.
|
||||
*
|
||||
* @param channel The analog channel the gyro is connected to.
|
||||
* @param channel The analog channel the gyro is connected to. Gyros
|
||||
can only be used on on-board Analog Inputs 0-1.
|
||||
*/
|
||||
Gyro::Gyro(int32_t channel)
|
||||
{
|
||||
@@ -83,10 +84,11 @@ Gyro::Gyro(int32_t channel)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with a precreated analog channel object.
|
||||
* Use this constructor when the analog channel needs to be shared. There
|
||||
* is no reference counting when an AnalogInput is passed to the gyro.
|
||||
* @param channel The AnalogInput object that the gyro is connected to.
|
||||
* Gyro constructor with a precreated AnalogInput object.
|
||||
* Use this constructor when the analog channel needs to be shared.
|
||||
* This object will not clean up the AnalogInput object when using this constructor.
|
||||
* Gyros can only be used on on-board channels 0-1.
|
||||
* @param channel A pointer to the AnalogInput object that the gyro is connected to.
|
||||
*/
|
||||
Gyro::Gyro(AnalogInput *channel)
|
||||
{
|
||||
@@ -102,6 +104,12 @@ Gyro::Gyro(AnalogInput *channel)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with a precreated AnalogInput object.
|
||||
* Use this constructor when the analog channel needs to be shared.
|
||||
* This object will not clean up the AnalogInput object when using this constructor
|
||||
* @param channel A reference to the AnalogInput object that the gyro is connected to.
|
||||
*/
|
||||
Gyro::Gyro(AnalogInput &channel)
|
||||
{
|
||||
m_analog = &channel;
|
||||
@@ -133,8 +141,8 @@ Gyro::~Gyro()
|
||||
*
|
||||
* The angle is based on the current accumulator value corrected by the oversampling rate, the
|
||||
* gyro type and the A/D calibration values.
|
||||
* The angle is continuous, that is can go beyond 360 degrees. This make algorithms that wouldn't
|
||||
* want to see a discontinuity in the gyro output as it sweeps past 0 on the second time around.
|
||||
* The angle is continuous, that is it will continue from 360->361 degrees. This allows algorithms that wouldn't
|
||||
* want to see a discontinuity in the gyro output as it sweeps from 360 to 0 on the second time around.
|
||||
*
|
||||
* @return the current heading of the robot in degrees. This heading is based on integration
|
||||
* of the returned rate from the gyro.
|
||||
@@ -169,11 +177,12 @@ double Gyro::GetRate( void )
|
||||
|
||||
|
||||
/**
|
||||
* Set the gyro type based on the sensitivity.
|
||||
* Set the gyro sensitivity.
|
||||
* This takes the number of volts/degree/second sensitivity of the gyro and uses it in subsequent
|
||||
* calculations to allow the code to work with multiple gyros.
|
||||
* calculations to allow the code to work with multiple gyros. This value is typically found in
|
||||
* the gyro datasheet.
|
||||
*
|
||||
* @param voltsPerDegreePerSecond The type of gyro specified as the voltage that represents one degree/second.
|
||||
* @param voltsPerDegreePerSecond The sensitivity in Volts/degree/second
|
||||
*/
|
||||
void Gyro::SetSensitivity( float voltsPerDegreePerSecond )
|
||||
{
|
||||
@@ -193,6 +202,11 @@ void Gyro::SetDeadband( float volts ) {
|
||||
m_analog->SetAccumulatorDeadband(deadband);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the type of output to use with the WPILib PID class
|
||||
* The gyro supports using either rate or angle for PID calculations
|
||||
*/
|
||||
void Gyro::SetPIDSourceParameter(PIDSourceParameter pidSource)
|
||||
{
|
||||
if(pidSource == 0 || pidSource > 2)
|
||||
@@ -201,9 +215,10 @@ void Gyro::SetPIDSourceParameter(PIDSourceParameter pidSource)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angle in degrees for the PIDSource base object.
|
||||
* Get the PIDOutput for the PIDSource base object. Can be set to return
|
||||
* angle or rate using SetPIDSourceParameter(). Defaults to angle.
|
||||
*
|
||||
* @return The angle in degrees.
|
||||
* @return The PIDOutput (angle or rate, defaults to angle)
|
||||
*/
|
||||
double Gyro::PIDGet()
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Port The I2C port to which the device is connected.
|
||||
* @param port The I2C port to which the device is connected.
|
||||
* @param deviceAddress The address of the device on the I2C bus.
|
||||
*/
|
||||
I2C::I2C(Port port, uint8_t deviceAddress) :
|
||||
|
||||
@@ -101,7 +101,9 @@ void InterruptableSensorBase::CancelInterrupts()
|
||||
}
|
||||
|
||||
/**
|
||||
* In synchronous mode, wait for the defined interrupt to occur.
|
||||
* In synchronous mode, wait for the defined interrupt to occur. You should <b>NOT</b> attempt to read the
|
||||
* sensor from another thread while waiting for an interrupt. This is not threadsafe, and can cause
|
||||
* memory corruption
|
||||
* @param timeout Timeout in seconds
|
||||
* @param ignorePrevious If true, ignore interrupts that happened before
|
||||
* WaitForInterrupt was called.
|
||||
|
||||
@@ -44,10 +44,7 @@ void IterativeRobot::Prestart() {
|
||||
/**
|
||||
* Provide an alternate "main loop" via StartCompetition().
|
||||
*
|
||||
* This specific StartCompetition() implements "main loop" behavior like that of the FRC
|
||||
* control system in 2008 and earlier, with a primary (slow) loop that is
|
||||
* called periodically, and a "fast loop" (a.k.a. "spin loop") that is
|
||||
* called as fast as possible with no delay between calls.
|
||||
* This specific StartCompetition() implements "main loop" behaviour synced with the DS packets
|
||||
*/
|
||||
void IterativeRobot::StartCompetition()
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
void Jaguar::InitJaguar()
|
||||
{
|
||||
/*
|
||||
/**
|
||||
* Input profile defined by Luminary Micro.
|
||||
*
|
||||
* Full reverse ranges from 0.671325ms to 0.6972211ms
|
||||
@@ -33,7 +33,8 @@ void Jaguar::InitJaguar()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel that the Jaguar is attached to.
|
||||
* Constructor for a Jaguar connected via PWM
|
||||
* @param channel The PWM channel that the Jaguar is attached to. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
Jaguar::Jaguar(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ static bool joySticksInitialized = false;
|
||||
* Construct an instance of a joystick.
|
||||
* The joystick index is the usb port on the drivers station.
|
||||
*
|
||||
* @param port The port on the driver station that the joystick is plugged into.
|
||||
* @param port The port on the driver station that the joystick is plugged into (0-5).
|
||||
*/
|
||||
Joystick::Joystick(uint32_t port)
|
||||
: m_ds (NULL)
|
||||
@@ -221,12 +221,12 @@ bool Joystick::GetBumper(JoystickHand hand)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for buttons 1 through 12.
|
||||
* Get the button value (starting at button 1)
|
||||
*
|
||||
* The buttons are returned in a single 16 bit value with one bit representing the state
|
||||
* of each button. The appropriate button is returned as a boolean value.
|
||||
*
|
||||
* @param button The button number to be read.
|
||||
* @param button The button number to be read (starting at 1)
|
||||
* @return The state of the button.
|
||||
**/
|
||||
bool Joystick::GetRawButton(uint32_t button)
|
||||
@@ -237,6 +237,7 @@ bool Joystick::GetRawButton(uint32_t button)
|
||||
/**
|
||||
* Get the state of a POV on the joystick.
|
||||
*
|
||||
* @param pov The index of the POV to read (starting at 0)
|
||||
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
|
||||
*/
|
||||
int Joystick::GetPOV(uint32_t pov) {
|
||||
|
||||
@@ -56,7 +56,7 @@ MotorSafetyHelper::~MotorSafetyHelper()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Feed the motor safety object.
|
||||
* Resets the timer on this object that is used to do the timeouts.
|
||||
*/
|
||||
@@ -66,7 +66,7 @@ void MotorSafetyHelper::Feed()
|
||||
m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Set the expiration time for the corresponding motor safety object.
|
||||
* @param expirationTime The timeout value in seconds.
|
||||
*/
|
||||
@@ -78,7 +78,7 @@ void MotorSafetyHelper::SetExpiration(float expirationTime)
|
||||
|
||||
/**
|
||||
* Retrieve the timeout value for the corresponding motor safety object.
|
||||
* @returns the timeout value in seconds.
|
||||
* @return the timeout value in seconds.
|
||||
*/
|
||||
float MotorSafetyHelper::GetExpiration()
|
||||
{
|
||||
@@ -88,7 +88,7 @@ float MotorSafetyHelper::GetExpiration()
|
||||
|
||||
/**
|
||||
* Determine if the motor is still operating or has timed out.
|
||||
* @returns a true value if the motor is still operating normally and hasn't timed out.
|
||||
* @return a true value if the motor is still operating normally and hasn't timed out.
|
||||
*/
|
||||
bool MotorSafetyHelper::IsAlive()
|
||||
{
|
||||
@@ -133,7 +133,7 @@ void MotorSafetyHelper::SetSafetyEnabled(bool enabled)
|
||||
/**
|
||||
* Return the state of the motor safety enabled flag
|
||||
* Return if the motor safety is currently enabled for this devicce.
|
||||
* @returns True if motor safety is enforced for this device
|
||||
* @return True if motor safety is enforced for this device
|
||||
*/
|
||||
bool MotorSafetyHelper::IsSafetyEnabled()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ const int32_t PWM::kPwmDisabled;
|
||||
* This method is private and is the common path for all the constructors for creating PWM
|
||||
* instances. Checks channel value range and allocates the appropriate channel.
|
||||
* The allocation is only done to help users ensure that they don't double assign channels.
|
||||
* @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
void PWM::InitPWM(uint32_t channel)
|
||||
{
|
||||
|
||||
@@ -7,14 +7,17 @@
|
||||
#include "PowerDistributionPanel.h"
|
||||
#include "WPIErrors.h"
|
||||
#include "HAL/PDP.hpp"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
/**
|
||||
* Initialize the PDP.
|
||||
*/
|
||||
PowerDistributionPanel::PowerDistributionPanel() {
|
||||
m_table=NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the input voltage of the PDP
|
||||
* @return The voltage of the PDP
|
||||
*/
|
||||
double
|
||||
@@ -31,6 +34,7 @@ PowerDistributionPanel::GetVoltage() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the temperature of the PDP
|
||||
* @return The temperature of the PDP in degrees Celsius
|
||||
*/
|
||||
double
|
||||
@@ -47,6 +51,7 @@ PowerDistributionPanel::GetTemperature() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the current of a single channel of the PDP
|
||||
* @return The current of one of the PDP channels (channels 0-15) in Amperes
|
||||
*/
|
||||
double
|
||||
@@ -70,6 +75,7 @@ PowerDistributionPanel::GetCurrent(uint8_t channel) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the total current of all monitored PDP channels (0-15)
|
||||
* @return The the total current drawn from the PDP channels in Amperes
|
||||
*/
|
||||
double
|
||||
@@ -86,6 +92,7 @@ PowerDistributionPanel::GetTotalCurrent() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the total power drawn from the monitored PDP channels
|
||||
* @return The the total power drawn from the PDP channels in Joules
|
||||
*/
|
||||
double
|
||||
@@ -102,6 +109,7 @@ PowerDistributionPanel::GetTotalPower() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the total energy drawn from the monitored PDP channels
|
||||
* @return The the total energy drawn from the PDP channels in Watts
|
||||
*/
|
||||
double
|
||||
@@ -146,3 +154,44 @@ PowerDistributionPanel::ClearStickyFaults() {
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::UpdateTable() {
|
||||
if (m_table != NULL) {
|
||||
m_table->PutNumber("Chan0", GetCurrent(0));
|
||||
m_table->PutNumber("Chan1", GetCurrent(1));
|
||||
m_table->PutNumber("Chan2", GetCurrent(2));
|
||||
m_table->PutNumber("Chan3", GetCurrent(3));
|
||||
m_table->PutNumber("Chan4", GetCurrent(4));
|
||||
m_table->PutNumber("Chan5", GetCurrent(5));
|
||||
m_table->PutNumber("Chan6", GetCurrent(6));
|
||||
m_table->PutNumber("Chan7", GetCurrent(7));
|
||||
m_table->PutNumber("Chan8", GetCurrent(8));
|
||||
m_table->PutNumber("Chan9", GetCurrent(9));
|
||||
m_table->PutNumber("Chan10", GetCurrent(10));
|
||||
m_table->PutNumber("Chan11", GetCurrent(11));
|
||||
m_table->PutNumber("Chan12", GetCurrent(12));
|
||||
m_table->PutNumber("Chan13", GetCurrent(13));
|
||||
m_table->PutNumber("Chan14", GetCurrent(14));
|
||||
m_table->PutNumber("Chan15", GetCurrent(15));
|
||||
m_table->PutNumber("Voltage", GetVoltage());
|
||||
m_table->PutNumber("TotalCurrent", GetTotalCurrent());
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::StartLiveWindowMode() {
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::StopLiveWindowMode() {
|
||||
}
|
||||
|
||||
std::string PowerDistributionPanel::GetSmartDashboardType() {
|
||||
return "PowerDistributionPanel";
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::InitTable(ITable *subTable) {
|
||||
m_table = subTable;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
ITable * PowerDistributionPanel::GetTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Utility.h"
|
||||
#include <cstring>
|
||||
#include "HAL/HAL.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __vxworks
|
||||
// VXWorks needs som special unloading code
|
||||
@@ -60,6 +61,13 @@ RobotBase::RobotBase()
|
||||
HLUsageReporting::SetImplementation(new HardwareHLReporting()); \
|
||||
|
||||
RobotBase::setInstance(this);
|
||||
|
||||
FILE *file = NULL;
|
||||
file = fopen("/tmp/frc_versions/FRC_Lib_Version.ini", "w");
|
||||
|
||||
fputs("2015 C++ 1.0.0", file);
|
||||
if (file != NULL)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,6 +131,8 @@ bool RobotBase::IsTest()
|
||||
/**
|
||||
* This hook is called right before startCompetition(). By default, tell the DS that the robot is now ready to
|
||||
* be enabled. If you don't want for the robot to be enabled yet, you can override this method to do nothing.
|
||||
* If you do so, you will need to call HALNetworkCommunicationObserveUserProgramStarting() from your code when
|
||||
* you are ready for the robot to be enabled.
|
||||
*/
|
||||
void RobotBase::Prestart()
|
||||
{
|
||||
|
||||
@@ -43,12 +43,13 @@ void RobotDrive::InitRobotDrive() {
|
||||
m_safetyHelper->SetSafetyEnabled(true);
|
||||
}
|
||||
|
||||
/** Constructor for RobotDrive with 2 motors specified with channel numbers.
|
||||
/**
|
||||
* Constructor for RobotDrive with 2 motors specified with channel numbers.
|
||||
* Set up parameters for a two wheel drive system where the
|
||||
* left and right motor pwm channels are specified in the call.
|
||||
* This call assumes Talons for controlling the motors.
|
||||
* @param leftMotorChannel The PWM channel number that drives the left motor.
|
||||
* @param rightMotorChannel The PWM channel number that drives the right motor.
|
||||
* @param leftMotorChannel The PWM channel number that drives the left motor. 0-9 are on-board, 10-19 are on the MXP port
|
||||
* @param rightMotorChannel The PWM channel number that drives the right motor. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
RobotDrive::RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel)
|
||||
{
|
||||
@@ -68,10 +69,10 @@ RobotDrive::RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel)
|
||||
* Set up parameters for a four wheel drive system where all four motor
|
||||
* pwm channels are specified in the call.
|
||||
* This call assumes Talons for controlling the motors.
|
||||
* @param frontLeftMotor Front left motor channel number
|
||||
* @param rearLeftMotor Rear Left motor channel number
|
||||
* @param frontRightMotor Front right motor channel number
|
||||
* @param rearRightMotor Rear Right motor channel number
|
||||
* @param frontLeftMotor Front left motor channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
* @param rearLeftMotor Rear Left motor channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
* @param frontRightMotor Front right motor channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
* @param rearRightMotor Rear Right motor channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
RobotDrive::RobotDrive(uint32_t frontLeftMotor, uint32_t rearLeftMotor,
|
||||
uint32_t frontRightMotor, uint32_t rearRightMotor)
|
||||
@@ -94,7 +95,7 @@ RobotDrive::RobotDrive(uint32_t frontLeftMotor, uint32_t rearLeftMotor,
|
||||
* The SpeedController version of the constructor enables programs to use the RobotDrive classes with
|
||||
* subclasses of the SpeedController objects, for example, versions with ramping or reshaping of
|
||||
* the curve to suit motor bias or deadband elimination.
|
||||
* @param leftMotor The left SpeedController object used to drive the robot.
|
||||
* @param leftMotor The left SpeedController object used to drive the robot.
|
||||
* @param rightMotor the right SpeedController object used to drive the robot.
|
||||
*/
|
||||
RobotDrive::RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor)
|
||||
|
||||
@@ -39,7 +39,9 @@ SPI::~SPI()
|
||||
|
||||
/**
|
||||
* Configure the rate of the generated clock signal.
|
||||
* The default and maximum value is 500,000 Hz.
|
||||
*
|
||||
* The default value is 500,000Hz.
|
||||
* The maximum value is 4,000,000Hz.
|
||||
*
|
||||
* @param hz The clock rate in Hertz.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ void SafePWM::InitSafePWM()
|
||||
|
||||
/**
|
||||
* Constructor for a SafePWM object taking a channel number.
|
||||
* @param channel The PWM channel number (0..19).
|
||||
* @param channel The PWM channel number 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
SafePWM::SafePWM(uint32_t channel): PWM(channel)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ SafePWM::~SafePWM()
|
||||
delete m_safetyHelper;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Set the expiration time for the PWM object
|
||||
* @param timeout The timeout (in seconds) for this motor object
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* Create an instance of a Serial Port class.
|
||||
*
|
||||
* @param baudRate The baud rate to configure the serial port.
|
||||
* @param port The physical port to use
|
||||
* @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits.
|
||||
* @param parity Select the type of parity checking to use.
|
||||
* @param stopBits The number of stop bits to use as defined by the enum StopBits.
|
||||
@@ -235,14 +236,4 @@ void SerialPort::Reset()
|
||||
int32_t status = 0;
|
||||
serialClear(m_port, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
//void SerialPort::_internalHandler(uint32_t port, uint32_t eventType, uint32_t event)
|
||||
//{
|
||||
//}
|
||||
|
||||
//ViStatus _VI_FUNCH ioCompleteHandler (ViSession vi, ViEventType eventType, ViEvent event, ViAddr userHandle)
|
||||
//{
|
||||
// ((SerialPort*) userHandle)->_internalHandler(vi, eventType, event);
|
||||
// return VI_SUCCESS;
|
||||
//}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ void Servo::InitServo()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel to which the servo is attached.
|
||||
* @param channel The PWM channel to which the servo is attached. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
Servo::Servo(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
@@ -42,9 +42,9 @@ void Solenoid::InitSolenoid()
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor using the default PCM ID (0).
|
||||
*
|
||||
* @param channel The channel on the solenoid module to control (1..8).
|
||||
* @param channel The channel on the PCM to control (0..7).
|
||||
*/
|
||||
Solenoid::Solenoid(uint32_t channel)
|
||||
: SolenoidBase (GetDefaultSolenoidModule())
|
||||
@@ -56,8 +56,8 @@ Solenoid::Solenoid(uint32_t channel)
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The solenoid module (1 or 2).
|
||||
* @param channel The channel on the solenoid module to control (1..8).
|
||||
* @param moduleNumber The CAN ID of the PCM the solenoid is attached to
|
||||
* @param channel The channel on the PCM to control (0..7).
|
||||
*/
|
||||
Solenoid::Solenoid(uint8_t moduleNumber, uint32_t channel)
|
||||
: SolenoidBase (moduleNumber)
|
||||
@@ -102,7 +102,19 @@ bool Solenoid::Get()
|
||||
uint8_t value = GetAll() & ( 1 << m_channel);
|
||||
return (value != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if solenoid is blacklisted.
|
||||
* If a solenoid is shorted, it is added to the blacklist and
|
||||
* disabled until power cycle, or until faults are cleared.
|
||||
* @see ClearAllPCMStickyFaults()
|
||||
*
|
||||
* @return If solenoid is disabled due to short.
|
||||
*/
|
||||
bool Solenoid::IsBlackListed()
|
||||
{
|
||||
int value = GetPCMSolenoidBlackList() & ( 1 << m_channel);
|
||||
return (value != 0);
|
||||
}
|
||||
|
||||
void Solenoid::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) {
|
||||
Set(value.b);
|
||||
|
||||
@@ -12,7 +12,7 @@ Resource *SolenoidBase::m_allocated = NULL;
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param moduleNumber The solenoid module (1 or 2).
|
||||
* @param moduleNumber The CAN PCM ID.
|
||||
*/
|
||||
SolenoidBase::SolenoidBase(uint8_t moduleNumber)
|
||||
: m_moduleNumber (moduleNumber)
|
||||
@@ -64,3 +64,52 @@ uint8_t SolenoidBase::GetAll()
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Reads complete solenoid blacklist for all 8 solenoids as a single byte.
|
||||
*
|
||||
* If a solenoid is shorted, it is added to the blacklist and
|
||||
* disabled until power cycle, or until faults are cleared.
|
||||
* @see ClearAllPCMStickyFaults()
|
||||
*
|
||||
* @return The solenoid blacklist of all 8 solenoids on the module.
|
||||
*/
|
||||
uint8_t SolenoidBase::GetPCMSolenoidBlackList()
|
||||
{
|
||||
int32_t status = 0;
|
||||
return getPCMSolenoidBlackList(m_ports[0], &status);
|
||||
}
|
||||
/**
|
||||
* @return true if PCM sticky fault is set : The common
|
||||
* highside solenoid voltage rail is too low,
|
||||
* most likely a solenoid channel is shorted.
|
||||
*/
|
||||
bool SolenoidBase::GetPCMSolenoidVoltageStickyFault()
|
||||
{
|
||||
int32_t status = 0;
|
||||
return getPCMSolenoidVoltageStickyFault(m_ports[0], &status);
|
||||
}
|
||||
/**
|
||||
* @return true if PCM is in fault state : The common
|
||||
* highside solenoid voltage rail is too low,
|
||||
* most likely a solenoid channel is shorted.
|
||||
*/
|
||||
bool SolenoidBase::GetPCMSolenoidVoltageFault()
|
||||
{
|
||||
int32_t status = 0;
|
||||
return getPCMSolenoidVoltageFault(m_ports[0], &status);
|
||||
}
|
||||
/**
|
||||
* Clear ALL sticky faults inside PCM that Compressor is wired to.
|
||||
*
|
||||
* If a sticky fault is set, then it will be persistently cleared. Compressor drive
|
||||
* maybe momentarily disable while flags are being cleared. Care should be
|
||||
* taken to not call this too frequently, otherwise normal compressor
|
||||
* functionality may be prevented.
|
||||
*
|
||||
* If no sticky faults are set then this call will have no effect.
|
||||
*/
|
||||
void SolenoidBase::ClearAllPCMStickyFaults()
|
||||
{
|
||||
int32_t status = 0;
|
||||
return clearAllPCMStickyFaults_sol(m_ports[0], &status);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the Talon User Manual available from CTRE.
|
||||
*
|
||||
* - 211 = full "forward"
|
||||
* - 133 = the "high end" of the deadband range
|
||||
* - 129 = center of the deadband range (off)
|
||||
* - 125 = the "low end" of the deadband range
|
||||
* - 49 = full "reverse"
|
||||
* 2.037ms = full "forward"
|
||||
* 1.539ms = the "high end" of the deadband range
|
||||
* 1.513ms = center of the deadband range (off)
|
||||
* 1.487ms = the "low end" of the deadband range
|
||||
* 0.989ms = full "reverse"
|
||||
*/
|
||||
void Talon::InitTalon() {
|
||||
SetBounds(2.037, 1.539, 1.513, 1.487, .989);
|
||||
@@ -34,7 +34,8 @@ void Talon::InitTalon() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel that the Talon is attached to.
|
||||
* Constructor for a Talon (original or Talon SR)
|
||||
* @param channel The PWM channel number that the Talon is attached to. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
Talon::Talon(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
@@ -13,10 +13,14 @@
|
||||
* Common initialization code called by all constructors.
|
||||
*
|
||||
* Note that the TalonSRX uses the following bounds for PWM values. These values should work reasonably well for
|
||||
* most controllers, but if users experience issues such as asymmetric behavior around
|
||||
* most controllers, but if users experience issues such as asymmetric behaviour around
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the TalonSRX User Manual available from Cross The Road Electronics.
|
||||
*
|
||||
* 2.004ms = full "forward"
|
||||
* 1.52ms = the "high end" of the deadband range
|
||||
* 1.50ms = center of the deadband range (off)
|
||||
* 1.48ms = the "low end" of the deadband range
|
||||
* 0.997ms = full "reverse"
|
||||
*/
|
||||
void TalonSRX::InitTalonSRX() {
|
||||
SetBounds(2.004, 1.52, 1.50, 1.48, .997);
|
||||
@@ -29,7 +33,8 @@ void TalonSRX::InitTalonSRX() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel that the TalonSRX is attached to.
|
||||
* Construct a TalonSRX connected via PWM
|
||||
* @param channel The PWM channel that the TalonSRX is attached to. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
TalonSRX::TalonSRX(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
@@ -28,10 +28,10 @@ void Wait(double seconds)
|
||||
delaySeconds(seconds);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Return the FPGA system clock time in seconds.
|
||||
* This is deprecated and just forwards to Timer::GetFPGATimestamp().
|
||||
* @returns Robot running time in seconds.
|
||||
* @return Robot running time in seconds.
|
||||
*/
|
||||
double GetClock()
|
||||
{
|
||||
@@ -80,7 +80,7 @@ Timer::~Timer()
|
||||
* the current system clock the start time stored in the timer class. If the clock
|
||||
* is not running, then return the time when it was last stopped.
|
||||
*
|
||||
* @return unsigned Current time value for this timer in seconds
|
||||
* @return Current time value for this timer in seconds
|
||||
*/
|
||||
double Timer::Get()
|
||||
{
|
||||
@@ -158,7 +158,7 @@ void Timer::Stop()
|
||||
* work without drifting later by the time it took to get around to checking.
|
||||
*
|
||||
* @param period The period to check for (in seconds).
|
||||
* @return If the period has passed.
|
||||
* @return True if the period has passed.
|
||||
*/
|
||||
bool Timer::HasPeriodPassed(double period)
|
||||
{
|
||||
@@ -166,14 +166,14 @@ bool Timer::HasPeriodPassed(double period)
|
||||
{
|
||||
Synchronized sync(m_semaphore);
|
||||
// Advance the start time by the period.
|
||||
// Don't set it to the current time... we want to avoid drift.
|
||||
m_startTime += period;
|
||||
// Don't set it to the current time... we want to avoid drift.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Return the FPGA system clock time in seconds.
|
||||
*
|
||||
* Return the time from the FPGA hardware clock in seconds since the FPGA
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
static bool suspendOnAssertEnabled = false;
|
||||
|
||||
/**
|
||||
* Enable suspend on asssert.
|
||||
* Enable suspend on assert.
|
||||
* If enabled, the user task will be suspended whenever an assert fails. This
|
||||
* will allow the user to attach to the task with the debugger and examine variables
|
||||
* around the failure.
|
||||
@@ -204,7 +204,7 @@ uint32_t GetFPGATime()
|
||||
|
||||
/**
|
||||
* Get the state of the "USER" button on the RoboRIO
|
||||
* @return true if the button is currently pressed down
|
||||
* @return True if the button is currently pressed down
|
||||
*/
|
||||
bool GetUserButton()
|
||||
{
|
||||
@@ -247,6 +247,7 @@ static std::string demangle(char const *mangledSymbol)
|
||||
|
||||
/**
|
||||
* Get a stack trace, ignoring the first "offset" symbols.
|
||||
* @param offset The number of symbols at the top of the stack to ignore
|
||||
*/
|
||||
std::string GetStackTrace(uint32_t offset)
|
||||
{
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
*
|
||||
* Note that the Victor uses the following bounds for PWM values. These values were determined
|
||||
* empirically and optimized for the Victor 888. These values should work reasonably well for
|
||||
* Victor 884 controllers as well but if users experience issues such as asymmetric behavior around
|
||||
* Victor 884 controllers as well but if users experience issues such as asymmetric behaviour around
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the Victor 884 User Manual available from IFI.
|
||||
*
|
||||
* - 206 = full "forward"
|
||||
* - 131 = the "high end" of the deadband range
|
||||
* - 128 = center of the deadband range (off)
|
||||
* - 125 = the "low end" of the deadband range
|
||||
* - 56 = full "reverse"
|
||||
* 2.027ms = full "forward"
|
||||
* 1.525ms = the "high end" of the deadband range
|
||||
* 1.507ms = center of the deadband range (off)
|
||||
* 1.49ms = the "low end" of the deadband range
|
||||
* 1.026ms = full "reverse"
|
||||
*/
|
||||
void Victor::InitVictor() {
|
||||
SetBounds(2.027, 1.525, 1.507, 1.49, 1.026);
|
||||
@@ -36,7 +36,8 @@ void Victor::InitVictor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel that the Victor is attached to.
|
||||
* Constructor for a Victor
|
||||
* @param channel The PWM channel number that the Victor is attached to. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
Victor::Victor(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the VictorSP User Manual available from Vex.
|
||||
*
|
||||
* 2.004ms = full "forward"
|
||||
* 1.52ms = the "high end" of the deadband range
|
||||
* 1.50ms = center of the deadband range (off)
|
||||
* 1.48ms = the "low end" of the deadband range
|
||||
* 0.997ms = full "reverse"
|
||||
*/
|
||||
void VictorSP::InitVictorSP() {
|
||||
SetBounds(2.004, 1.52, 1.50, 1.48, .997);
|
||||
@@ -29,7 +34,8 @@ void VictorSP::InitVictorSP() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel The PWM channel that the VictorSP is attached to.
|
||||
* Constructor for a VictorSP
|
||||
* @param channel The PWM channel that the VictorSP is attached to. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
VictorSP::VictorSP(uint32_t channel) : SafePWM(channel)
|
||||
{
|
||||
|
||||
645
wpilibc/wpilibC++Devices/src/Vision/AxisCamera.cpp
Normal file
645
wpilibc/wpilibC++Devices/src/Vision/AxisCamera.cpp
Normal file
@@ -0,0 +1,645 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/AxisCamera.h"
|
||||
|
||||
#include "WPIErrors.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <Timer.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
static const unsigned int kMaxPacketSize = 1536;
|
||||
static const unsigned int kImageBufferAllocationIncrement = 1000;
|
||||
|
||||
static const std::string kWhiteBalanceStrings[] =
|
||||
{ "auto", "hold", "fixed_outdoor1", "fixed_outdoor2", "fixed_indoor",
|
||||
"fixed_fluor1", "fixed_fluor2", };
|
||||
|
||||
static const std::string kExposureControlStrings[] =
|
||||
{ "auto", "hold", "flickerfree50", "flickerfree60", };
|
||||
|
||||
static const std::string kResolutionStrings[] =
|
||||
{ "640x480", "480x360", "320x240", "240x180", "176x144", "160x120", };
|
||||
|
||||
static const std::string kRotationStrings[] =
|
||||
{ "0", "180", };
|
||||
|
||||
/**
|
||||
* AxisCamera constructor
|
||||
* @param cameraHost The host to find the camera at, typically an IP address
|
||||
*/
|
||||
AxisCamera::AxisCamera(std::string const& cameraHost)
|
||||
: m_cameraHost(cameraHost)
|
||||
, m_cameraSocket(-1)
|
||||
, m_freshImage(false)
|
||||
, m_brightness(50)
|
||||
, m_whiteBalance(kWhiteBalance_Automatic)
|
||||
, m_colorLevel(50)
|
||||
, m_exposureControl(kExposureControl_Automatic)
|
||||
, m_exposurePriority(50)
|
||||
, m_maxFPS(0)
|
||||
, m_resolution(kResolution_640x480)
|
||||
, m_compression(50)
|
||||
, m_rotation(kRotation_0)
|
||||
, m_parametersDirty(true)
|
||||
, m_streamDirty(true)
|
||||
, m_done(false)
|
||||
{
|
||||
m_captureThread = std::thread(&AxisCamera::Capture, this);
|
||||
}
|
||||
|
||||
AxisCamera::~AxisCamera()
|
||||
{
|
||||
m_done = true;
|
||||
m_captureThread.join();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the latest image from the camera has not been retrieved by calling GetImage() yet.
|
||||
* @return true if the image has not been retrieved yet.
|
||||
*/
|
||||
bool AxisCamera::IsFreshImage() const
|
||||
{
|
||||
return m_freshImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
* @param image The imaq image to store the result in. This must be an HSL or RGB image.
|
||||
* @return 1 upon success, zero on a failure
|
||||
*/
|
||||
int AxisCamera::GetImage(Image *image)
|
||||
{
|
||||
if (m_imageData.size() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_imageDataMutex);
|
||||
|
||||
Priv_ReadJPEGString_C(image, m_imageData.data(), m_imageData.size());
|
||||
|
||||
m_freshImage = false;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
* @param image The image to store the result in. This must be an HSL or RGB image
|
||||
* @return 1 upon success, zero on a failure
|
||||
*/
|
||||
int AxisCamera::GetImage(ColorImage *image)
|
||||
{
|
||||
return GetImage(image->GetImaqImage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new image object and fill it with the latest image from the camera.
|
||||
*
|
||||
* The returned pointer is owned by the caller and is their responsibility to delete.
|
||||
* @return a pointer to an HSLImage object
|
||||
*/
|
||||
HSLImage *AxisCamera::GetImage()
|
||||
{
|
||||
HSLImage *image = new HSLImage();
|
||||
GetImage(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an image into an existing buffer.
|
||||
* This copies an image into an existing buffer rather than creating a new image
|
||||
* in memory. That way a new image is only allocated when the image being copied is
|
||||
* larger than the destination.
|
||||
* This method is called by the PCVideoServer class.
|
||||
* @param imageData The destination image.
|
||||
* @param numBytes The size of the destination image.
|
||||
* @return 0 if failed (no source image or no memory), 1 if success.
|
||||
*/
|
||||
int AxisCamera::CopyJPEG(char **destImage, unsigned int &destImageSize, unsigned int &destImageBufferSize)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_imageDataMutex);
|
||||
if (destImage == NULL)
|
||||
wpi_setWPIErrorWithContext(NullParameter, "destImage must not be NULL");
|
||||
|
||||
if (m_imageData.size() == 0)
|
||||
return 0; // if no source image
|
||||
|
||||
if (destImageBufferSize < m_imageData.size()) // if current destination buffer too small
|
||||
{
|
||||
if (*destImage != NULL) delete [] *destImage;
|
||||
destImageBufferSize = m_imageData.size() + kImageBufferAllocationIncrement;
|
||||
*destImage = new char[destImageBufferSize];
|
||||
if (*destImage == NULL) return 0;
|
||||
}
|
||||
// copy this image into destination buffer
|
||||
if (*destImage == NULL)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(NullParameter, "*destImage must not be NULL");
|
||||
}
|
||||
|
||||
std::copy(m_imageData.begin(), m_imageData.end(), *destImage);
|
||||
destImageSize = m_imageData.size();;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the brightness of the camera images.
|
||||
* @param brightness valid values 0 .. 100
|
||||
*/
|
||||
void AxisCamera::WriteBrightness(int brightness)
|
||||
{
|
||||
if (brightness < 0 || brightness > 100)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Brightness must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_brightness != brightness)
|
||||
{
|
||||
m_brightness = brightness;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured brightness of the camera images
|
||||
*/
|
||||
int AxisCamera::GetBrightness()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the white balance on the camera.
|
||||
* @param whiteBalance Valid values from the <code>WhiteBalance</code> enum.
|
||||
*/
|
||||
void AxisCamera::WriteWhiteBalance(AxisCamera::WhiteBalance whiteBalance)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_whiteBalance != whiteBalance)
|
||||
{
|
||||
m_whiteBalance = whiteBalance;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured white balances of the camera images
|
||||
*/
|
||||
AxisCamera::WhiteBalance AxisCamera::GetWhiteBalance()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_whiteBalance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the color level of the camera images.
|
||||
* @param colorLevel valid values are 0 .. 100
|
||||
*/
|
||||
void AxisCamera::WriteColorLevel(int colorLevel)
|
||||
{
|
||||
if (colorLevel < 0 || colorLevel > 100)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Color level must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_colorLevel != colorLevel)
|
||||
{
|
||||
m_colorLevel = colorLevel;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured color level of the camera images
|
||||
*/
|
||||
int AxisCamera::GetColorLevel()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_colorLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the camera's exposure mode.
|
||||
* @param exposureControl A mode to write in the <code>Exposure</code> enum.
|
||||
*/
|
||||
void AxisCamera::WriteExposureControl(
|
||||
AxisCamera::ExposureControl exposureControl)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_exposureControl != exposureControl)
|
||||
{
|
||||
m_exposureControl = exposureControl;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured exposure control mode of the camera
|
||||
*/
|
||||
AxisCamera::ExposureControl AxisCamera::GetExposureControl()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_exposureControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the exposure priority of the camera.
|
||||
* @param exposurePriority Valid values are 0, 50, 100.
|
||||
* 0 = Prioritize image quality
|
||||
* 50 = None
|
||||
* 100 = Prioritize frame rate
|
||||
*/
|
||||
void AxisCamera::WriteExposurePriority(int exposurePriority)
|
||||
{
|
||||
if (exposurePriority != 0 && exposurePriority != 50
|
||||
&& exposurePriority != 100)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Exposure priority must be from 0, 50, or 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_exposurePriority != exposurePriority)
|
||||
{
|
||||
m_exposurePriority = exposurePriority;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured exposure priority of the camera
|
||||
*/
|
||||
int AxisCamera::GetExposurePriority()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_exposurePriority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the maximum frames per second that the camera should send
|
||||
* Write 0 to send as many as possible.
|
||||
* @param maxFPS The number of frames the camera should send in a second, exposure permitting.
|
||||
*/
|
||||
void AxisCamera::WriteMaxFPS(int maxFPS)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_maxFPS != maxFPS)
|
||||
{
|
||||
m_maxFPS = maxFPS;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured maximum FPS of the camera
|
||||
*/
|
||||
int AxisCamera::GetMaxFPS()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_maxFPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write resolution value to camera.
|
||||
* @param resolution The camera resolution value to write to the camera.
|
||||
*/
|
||||
void AxisCamera::WriteResolution(AxisCamera::Resolution resolution)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_resolution != resolution)
|
||||
{
|
||||
m_resolution = resolution;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured resolution of the camera (not necessarily the same
|
||||
* resolution as the most recent image, if it was changed recently.)
|
||||
*/
|
||||
AxisCamera::Resolution AxisCamera::GetResolution()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the rotation value to the camera.
|
||||
* If you mount your camera upside down, use this to adjust the image for you.
|
||||
* @param rotation The angle to rotate the camera (<code>AxisCamera::Rotation::k0</code>
|
||||
* or <code>AxisCamera::Rotation::k180</code>)
|
||||
*/
|
||||
void AxisCamera::WriteRotation(AxisCamera::Rotation rotation)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_rotation != rotation)
|
||||
{
|
||||
m_rotation = rotation;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured rotation mode of the camera
|
||||
*/
|
||||
AxisCamera::Rotation AxisCamera::GetRotation()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the compression value to the camera.
|
||||
* @param compression Values between 0 and 100.
|
||||
*/
|
||||
void AxisCamera::WriteCompression(int compression)
|
||||
{
|
||||
if (compression < 0 || compression > 100)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Compression must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_compression != compression)
|
||||
{
|
||||
m_compression = compression;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured compression level of the camera
|
||||
*/
|
||||
int AxisCamera::GetCompression()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_parametersMutex);
|
||||
return m_compression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called in the capture thread to receive images from the camera
|
||||
*/
|
||||
void AxisCamera::Capture()
|
||||
{
|
||||
int consecutiveErrors = 0;
|
||||
|
||||
// Loop on trying to setup the camera connection. This happens in a background
|
||||
// thread so it shouldn't effect the operation of user programs.
|
||||
while (!m_done)
|
||||
{
|
||||
std::string requestString = "GET /mjpg/video.mjpg HTTP/1.1\n"
|
||||
"User-Agent: HTTPStreamClient\n"
|
||||
"Connection: Keep-Alive\n"
|
||||
"Cache-Control: no-cache\n"
|
||||
"Authorization: Basic RlJDOkZSQw==\n\n";
|
||||
m_captureMutex.lock();
|
||||
m_cameraSocket = CreateCameraSocket(requestString, consecutiveErrors > 5);
|
||||
if (m_cameraSocket != -1)
|
||||
{
|
||||
ReadImagesFromCamera();
|
||||
consecutiveErrors = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
consecutiveErrors++;
|
||||
}
|
||||
m_captureMutex.unlock();
|
||||
Wait(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function actually reads the images from the camera.
|
||||
*/
|
||||
void AxisCamera::ReadImagesFromCamera()
|
||||
{
|
||||
char *imgBuffer = NULL;
|
||||
int imgBufferLength = 0;
|
||||
|
||||
// TODO: these recv calls must be non-blocking. Otherwise if the camera
|
||||
// fails during a read, the code hangs and never retries when the camera comes
|
||||
// back up.
|
||||
|
||||
int counter = 2;
|
||||
while (!m_done)
|
||||
{
|
||||
char initialReadBuffer[kMaxPacketSize] = "";
|
||||
char intermediateBuffer[1];
|
||||
char *trailingPtr = initialReadBuffer;
|
||||
int trailingCounter = 0;
|
||||
while (counter)
|
||||
{
|
||||
// TODO: fix me... this cannot be the most efficient way to approach this, reading one byte at a time.
|
||||
if (recv(m_cameraSocket, intermediateBuffer, 1, 0) == -1)
|
||||
{
|
||||
wpi_setErrnoErrorWithContext("Failed to read image header");
|
||||
close(m_cameraSocket);
|
||||
return;
|
||||
}
|
||||
strncat(initialReadBuffer, intermediateBuffer, 1);
|
||||
// trailingCounter ensures that we start looking for the 4 byte string after
|
||||
// there is at least 4 bytes total. Kind of obscure.
|
||||
// look for 2 blank lines (\r\n)
|
||||
if (NULL != strstr(trailingPtr, "\r\n\r\n"))
|
||||
{
|
||||
--counter;
|
||||
}
|
||||
if (++trailingCounter >= 4)
|
||||
{
|
||||
trailingPtr++;
|
||||
}
|
||||
}
|
||||
counter = 1;
|
||||
char *contentLength = strstr(initialReadBuffer, "Content-Length: ");
|
||||
if (contentLength == NULL)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(IncompatibleMode,
|
||||
"No content-length token found in packet");
|
||||
close(m_cameraSocket);
|
||||
return;
|
||||
}
|
||||
contentLength = contentLength + 16; // skip past "content length"
|
||||
int readLength = atol(contentLength); // get the image byte count
|
||||
|
||||
// Make sure buffer is large enough
|
||||
if (imgBufferLength < readLength)
|
||||
{
|
||||
if (imgBuffer)
|
||||
delete[] imgBuffer;
|
||||
imgBufferLength = readLength + kImageBufferAllocationIncrement;
|
||||
imgBuffer = new char[imgBufferLength];
|
||||
if (imgBuffer == NULL)
|
||||
{
|
||||
imgBufferLength = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the image data for "Content-Length" bytes
|
||||
int bytesRead = 0;
|
||||
int remaining = readLength;
|
||||
while (bytesRead < readLength)
|
||||
{
|
||||
int bytesThisRecv = recv(m_cameraSocket, &imgBuffer[bytesRead],
|
||||
remaining, 0);
|
||||
bytesRead += bytesThisRecv;
|
||||
remaining -= bytesThisRecv;
|
||||
}
|
||||
|
||||
// Update image
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_imageDataMutex);
|
||||
|
||||
m_imageData.assign(imgBuffer, imgBuffer + imgBufferLength);
|
||||
m_freshImage = true;
|
||||
}
|
||||
|
||||
if (WriteParameters())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(m_cameraSocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to the camera to set all of the parameters. This is called
|
||||
* in the capture thread between each frame. This strategy avoids making lots
|
||||
* of redundant HTTP requests, accounts for failed initial requests, and
|
||||
* avoids blocking calls in the main thread unless necessary.
|
||||
*
|
||||
* This method does nothing if no parameters have been modified since it last
|
||||
* completely successfully.
|
||||
*
|
||||
* @return <code>true</code> if the stream should be restarted due to a
|
||||
* parameter changing.
|
||||
*/
|
||||
bool AxisCamera::WriteParameters()
|
||||
{
|
||||
if (m_parametersDirty)
|
||||
{
|
||||
std::stringstream request;
|
||||
request << "GET /axis-cgi/admin/param.cgi?action=update";
|
||||
|
||||
m_parametersMutex.lock();
|
||||
request << "&ImageSource.I0.Sensor.Brightness=" << m_brightness;
|
||||
request << "&ImageSource.I0.Sensor.WhiteBalance=" << kWhiteBalanceStrings[m_whiteBalance];
|
||||
request << "&ImageSource.I0.Sensor.ColorLevel=" << m_colorLevel;
|
||||
request << "&ImageSource.I0.Sensor.Exposure=" << kExposureControlStrings[m_exposureControl];
|
||||
request << "&ImageSource.I0.Sensor.ExposurePriority=" << m_exposurePriority;
|
||||
request << "&Image.I0.Stream.FPS=" << m_maxFPS;
|
||||
request << "&Image.I0.Appearance.Resolution=" << kResolutionStrings[m_resolution];
|
||||
request << "&Image.I0.Appearance.Compression=" << m_compression;
|
||||
request << "&Image.I0.Appearance.Rotation=" << kRotationStrings[m_rotation];
|
||||
m_parametersMutex.unlock();
|
||||
|
||||
request << " HTTP/1.1" << std::endl;
|
||||
request << "User-Agent: HTTPStreamClient" << std::endl;
|
||||
request << "Connection: Keep-Alive" << std::endl;
|
||||
request << "Cache-Control: no-cache" << std::endl;
|
||||
request << "Authorization: Basic RlJDOkZSQw==" << std::endl;
|
||||
request << std::endl;
|
||||
|
||||
int socket = CreateCameraSocket(request.str(), false);
|
||||
if (socket == -1)
|
||||
{
|
||||
wpi_setErrnoErrorWithContext("Error setting camera parameters");
|
||||
}
|
||||
else
|
||||
{
|
||||
close(socket);
|
||||
m_parametersDirty = false;
|
||||
|
||||
if (m_streamDirty)
|
||||
{
|
||||
m_streamDirty = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket connected to camera
|
||||
* Used to create a connection to the camera for both capturing images and setting parameters.
|
||||
* @param requestString The initial request string to send upon successful connection.
|
||||
* @param setError If true, rais an error if there's a problem creating the connection.
|
||||
* This is only enabled after several unsucessful connections, so a single one doesn't
|
||||
* cause an error message to be printed if it immediately recovers.
|
||||
* @return -1 if failed, socket handle if successful.
|
||||
*/
|
||||
int AxisCamera::CreateCameraSocket(std::string const& requestString, bool setError)
|
||||
{
|
||||
struct addrinfo *address = 0;
|
||||
int camSocket;
|
||||
|
||||
/* create socket */
|
||||
if ((camSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
if (setError) wpi_setErrnoErrorWithContext("Failed to create the camera socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (getaddrinfo(m_cameraHost.c_str(), "80", 0, &address) == -1)
|
||||
{
|
||||
if (setError) wpi_setErrnoErrorWithContext("Failed to create the camera socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect to server */
|
||||
if (connect(camSocket, address->ai_addr, address->ai_addrlen) == -1)
|
||||
{
|
||||
if (setError) wpi_setErrnoErrorWithContext("Failed to connect to the camera");
|
||||
close(camSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sent = send(camSocket, requestString.c_str(), requestString.size(), 0);
|
||||
if (sent == -1)
|
||||
{
|
||||
if (setError) wpi_setErrnoErrorWithContext("Failed to send a request to the camera");
|
||||
close(camSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return camSocket;
|
||||
}
|
||||
|
||||
385
wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp
Normal file
385
wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Vision/BaeUtilities.h"
|
||||
#include "Servo.h"
|
||||
#include "Timer.h"
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* debug output flag options:
|
||||
* DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE
|
||||
*/
|
||||
static DebugOutputType dprintfFlag = DEBUG_OFF;
|
||||
|
||||
/**
|
||||
* Set the debug flag to print to screen, file on cRIO, both or neither
|
||||
* @param tempString The format string.
|
||||
*/
|
||||
void SetDebugFlag ( DebugOutputType flag )
|
||||
{ dprintfFlag = flag; }
|
||||
|
||||
/**
|
||||
* Debug print to a file and/or a terminal window.
|
||||
* Call like you would call printf.
|
||||
* Set functionName in the function if you want the correct function name to print out.
|
||||
* The file line number will also be printed.
|
||||
* @param tempString The format string.
|
||||
*/
|
||||
void dprintf ( const char * tempString, ... ) /* Variable argument list */
|
||||
{
|
||||
va_list args; /* Input argument list */
|
||||
int line_number; /* Line number passed in argument */
|
||||
int type;
|
||||
const char *functionName; /* Format passed in argument */
|
||||
const char *fmt; /* Format passed in argument */
|
||||
char text[512]; /* Text string */
|
||||
char outtext[512]; /* Text string */
|
||||
FILE *outfile_fd; /* Output file pointer */
|
||||
char filepath[128]; /* Text string */
|
||||
int fatalFlag=0;
|
||||
const char *filename;
|
||||
int index;
|
||||
int tempStringLen;
|
||||
|
||||
if (dprintfFlag == DEBUG_OFF) { return; }
|
||||
|
||||
va_start (args, tempString);
|
||||
|
||||
tempStringLen = strlen(tempString);
|
||||
filename = tempString;
|
||||
for (index=0;index<tempStringLen;index++){
|
||||
if (tempString[index] == ' ') {
|
||||
printf( "ERROR in dprintf: malformed calling sequence (%s)\n",tempString);return;
|
||||
}
|
||||
if (tempString[index] == '\\' || tempString[index] == '/')
|
||||
filename = tempString + index + 1;
|
||||
}
|
||||
|
||||
/* Extract function name */
|
||||
functionName = va_arg (args, const char *);
|
||||
|
||||
/* Extract line number from argument list */
|
||||
line_number = va_arg (args, int);
|
||||
|
||||
/* Extract information type from argument list */
|
||||
type = va_arg (args, int);
|
||||
|
||||
/* Extract format from argument list */
|
||||
fmt = va_arg (args, const char *);
|
||||
|
||||
vsprintf (text, fmt, args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
/* Format output statement */
|
||||
switch (type)
|
||||
{
|
||||
case DEBUG_TYPE:
|
||||
sprintf (outtext, "[%s:%s@%04d] DEBUG %s\n",
|
||||
filename, functionName, line_number, text);
|
||||
break;
|
||||
case INFO_TYPE:
|
||||
sprintf (outtext, "[%s:%s@%04d] INFO %s\n",
|
||||
filename, functionName, line_number, text);
|
||||
break;
|
||||
case ERROR_TYPE:
|
||||
sprintf (outtext, "[%s:%s@%04d] ERROR %s\n",
|
||||
filename, functionName, line_number, text);
|
||||
break;
|
||||
case CRITICAL_TYPE:
|
||||
sprintf (outtext, "[%s:%s@%04d] CRITICAL %s\n",
|
||||
filename, functionName, line_number, text);
|
||||
break;
|
||||
case FATAL_TYPE:
|
||||
fatalFlag = 1;
|
||||
sprintf (outtext, "[%s:%s@%04d] FATAL %s\n",
|
||||
filename, functionName, line_number, text);
|
||||
break;
|
||||
default:
|
||||
printf( "ERROR in dprintf: malformed calling sequence\n");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf (filepath, "%s.debug", filename);
|
||||
|
||||
/* Write output statement */
|
||||
switch (dprintfFlag)
|
||||
{
|
||||
default:
|
||||
case DEBUG_OFF:
|
||||
break;
|
||||
case DEBUG_MOSTLY_OFF:
|
||||
if (fatalFlag) {
|
||||
if ((outfile_fd = fopen (filepath, "a+")) != NULL) {
|
||||
fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
|
||||
fclose (outfile_fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEBUG_SCREEN_ONLY:
|
||||
printf ("%s", outtext);
|
||||
break;
|
||||
case DEBUG_FILE_ONLY:
|
||||
if ((outfile_fd = fopen (filepath, "a+")) != NULL) {
|
||||
fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
|
||||
fclose (outfile_fd);
|
||||
}
|
||||
break;
|
||||
case DEBUG_SCREEN_AND_FILE: // BOTH
|
||||
printf ("%s", outtext);
|
||||
if ((outfile_fd = fopen (filepath, "a+")) != NULL) {
|
||||
fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
|
||||
fclose (outfile_fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalizes a value in a range, used for drive input
|
||||
* @param position The position in the range, starting at 0
|
||||
* @param range The size of the range that position is in
|
||||
* @return The normalized position from -1 to +1
|
||||
*/
|
||||
double RangeToNormalized(double position, int range){
|
||||
return(((position*2.0)/(double)range)-1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a normalized value to the corresponding value in a range.
|
||||
* This is used to convert normalized values to the servo command range.
|
||||
* @param normalizedValue The normalized value (in the -1 to +1 range)
|
||||
* @param minRange The minimum of the range (0 is default)
|
||||
* @param maxRange The maximum of the range (1 is default)
|
||||
* @return The value in the range corresponding to the input normalized value
|
||||
*/
|
||||
float NormalizeToRange(float normalizedValue, float minRange, float maxRange) {
|
||||
float range = maxRange-minRange;
|
||||
float temp = (float)((normalizedValue / 2.0)+ 0.5)*range;
|
||||
return (temp + minRange);
|
||||
}
|
||||
float NormalizeToRange(float normalizedValue) {
|
||||
return (float)((normalizedValue / 2.0) + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays an activity indicator to console.
|
||||
* Call this function like you would call printf.
|
||||
* @param fmt The format string
|
||||
*/
|
||||
void ShowActivity (char *fmt, ...)
|
||||
{
|
||||
static char activity_indication_string[] = "|/-\\";
|
||||
static int ai = 3;
|
||||
va_list args;
|
||||
char text[1024];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
vsprintf (text, fmt, args);
|
||||
|
||||
ai = ai == 3 ? 0 : ai + 1;
|
||||
|
||||
printf ("%c %s \r", activity_indication_string[ai], text);
|
||||
fflush (stdout);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#define PI 3.14159265358979
|
||||
/**
|
||||
* @brief Calculate sine wave increments (-1.0 to 1.0).
|
||||
* The first time this is called, it sets up the time increment. Subsequent calls
|
||||
* will give values along the sine wave depending on current time. If the wave is
|
||||
* stopped and restarted, it must be reinitialized with a new "first call".
|
||||
*
|
||||
* @param period length of time to complete a complete wave
|
||||
* @param sinStart Where to start the sine wave (0.0 = 2 pi, pi/2 = 1.0, etc.)
|
||||
*/
|
||||
double SinPosition (double *period, double sinStart)
|
||||
{
|
||||
double rtnVal;
|
||||
static double sinePeriod=0.0;
|
||||
static double timestamp;
|
||||
double sinArg;
|
||||
|
||||
//1st call
|
||||
if (period != NULL) {
|
||||
sinePeriod = *period;
|
||||
timestamp = GetTime();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//Multiplying by 2*pi to the time difference makes sinePeriod work if it's measured in seconds.
|
||||
//Adding sinStart to the part multiplied by PI, but not by 2, allows it to work as described in the comments.
|
||||
sinArg = PI *((2.0 * (GetTime() - timestamp)) + sinStart) / sinePeriod;
|
||||
rtnVal = sin (sinArg);
|
||||
return (rtnVal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find the elapsed time since a specified time.
|
||||
* @param startTime The starting time
|
||||
* @return How long it has been since the starting time
|
||||
*/
|
||||
double ElapsedTime ( double startTime )
|
||||
{
|
||||
double realTime = GetTime();
|
||||
return (realTime-startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize pan parameters
|
||||
* @param period The number of seconds to complete one pan
|
||||
*/
|
||||
void panInit() {
|
||||
double period = 3.0; // number of seconds for one complete pan
|
||||
SinPosition(&period, 0.0); // initial call to set up time
|
||||
}
|
||||
|
||||
void panInit(double period) {
|
||||
if (period < 0.0) period=3.0;
|
||||
SinPosition(&period, 0.0); // initial call to set up time
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move the horizontal servo back and forth.
|
||||
* @param panServo The servo object to move
|
||||
* @param sinStart The position on the sine wave to begin the pan
|
||||
*/
|
||||
void panForTarget(Servo *panServo) { panForTarget(panServo, 0.0); }
|
||||
|
||||
void panForTarget(Servo *panServo, double sinStart) {
|
||||
float normalizedSinPosition = (float)SinPosition(NULL, sinStart);
|
||||
float newServoPosition = NormalizeToRange(normalizedSinPosition);
|
||||
panServo->Set( newServoPosition );
|
||||
//ShowActivity ("pan x: normalized %f newServoPosition = %f" ,
|
||||
// normalizedSinPosition, newServoPosition );
|
||||
}
|
||||
|
||||
|
||||
/** @brief Read a file and return non-comment output string
|
||||
|
||||
Call the first time with 0 lineNumber to get the number of lines to read
|
||||
Then call with each lineNumber to get one camera parameter. There should
|
||||
be one property=value entry on each line, i.e. "exposure=auto"
|
||||
|
||||
* @param inputFile filename to read
|
||||
* @param outputString one string
|
||||
* @param lineNumber if 0, return number of lines; else return that line number
|
||||
* @return int number of lines or -1 if error
|
||||
**/
|
||||
int processFile(char *inputFile, char *outputString, int lineNumber)
|
||||
{
|
||||
FILE *infile;
|
||||
int stringSize = 80; // max size of one line in file
|
||||
char inputStr[stringSize];
|
||||
int lineCount=0;
|
||||
|
||||
if (lineNumber < 0)
|
||||
return (-1);
|
||||
|
||||
if ((infile = fopen (inputFile, "r")) == NULL) {
|
||||
printf ("Fatal error opening file %s\n",inputFile);
|
||||
return (0);
|
||||
}
|
||||
|
||||
while (!feof(infile)) {
|
||||
if (fgets (inputStr, stringSize, infile) != NULL) {
|
||||
// Skip empty lines
|
||||
if (emptyString(inputStr))
|
||||
continue;
|
||||
// Skip comment lines
|
||||
if (inputStr[0] == '#' || inputStr[0] == '!')
|
||||
continue;
|
||||
|
||||
lineCount++;
|
||||
if (lineNumber == 0)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (lineCount == lineNumber)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close file
|
||||
fclose (infile);
|
||||
// if number lines requested return the count
|
||||
if (lineNumber == 0)
|
||||
return (lineCount);
|
||||
// check for input out of range
|
||||
if (lineNumber > lineCount)
|
||||
return (-1);
|
||||
// return the line selected
|
||||
if (lineCount) {
|
||||
stripString(inputStr);
|
||||
strcpy(outputString, inputStr);
|
||||
return(lineCount);
|
||||
}
|
||||
else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Ignore empty string
|
||||
* @param string to check if empty
|
||||
**/
|
||||
int emptyString(char *string)
|
||||
{
|
||||
int i,len;
|
||||
|
||||
if(string == NULL)
|
||||
return(1);
|
||||
|
||||
len = strlen(string);
|
||||
for(i=0; i<len; i++) {
|
||||
// Ignore the following characters
|
||||
if (string[i] == '\n' || string[i] == '\r' ||
|
||||
string[i] == '\t' || string[i] == ' ')
|
||||
continue;
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/** Remove special characters from string
|
||||
* @param string to process
|
||||
**/
|
||||
void stripString(char *string)
|
||||
{
|
||||
int i,j,len;
|
||||
|
||||
if(string == NULL)
|
||||
return;
|
||||
|
||||
len = strlen(string);
|
||||
for(i=0,j=0; i<len; i++) {
|
||||
// Remove the following characters from the string
|
||||
if (string[i] == '\n' || string[i] == '\r' || string[i] == '\"')
|
||||
continue;
|
||||
// Copy anything else
|
||||
string[j++] = string[i];
|
||||
}
|
||||
string[j] = '\0';
|
||||
}
|
||||
|
||||
|
||||
222
wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp
Normal file
222
wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/BinaryImage.h"
|
||||
#include "WPIErrors.h"
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
BinaryImage::BinaryImage() : MonoImage()
|
||||
{
|
||||
}
|
||||
|
||||
BinaryImage::~BinaryImage()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get then number of particles for the image.
|
||||
* @returns the number of particles found for the image.
|
||||
*/
|
||||
int BinaryImage::GetNumberParticles()
|
||||
{
|
||||
int numParticles = 0;
|
||||
int success = imaqCountParticles(m_imaqImage, 1, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error counting particles");
|
||||
return numParticles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single particle analysis report.
|
||||
* Get one (of possibly many) particle analysis reports for an image.
|
||||
* @param particleNumber Which particle analysis report to return.
|
||||
* @returns the selected particle analysis report
|
||||
*/
|
||||
ParticleAnalysisReport BinaryImage::GetParticleAnalysisReport(int particleNumber)
|
||||
{
|
||||
ParticleAnalysisReport par;
|
||||
GetParticleAnalysisReport(particleNumber, &par);
|
||||
return par;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single particle analysis report.
|
||||
* Get one (of possibly many) particle analysis reports for an image.
|
||||
* This version could be more efficient when copying many reports.
|
||||
* @param particleNumber Which particle analysis report to return.
|
||||
* @param par the selected particle analysis report
|
||||
*/
|
||||
void BinaryImage::GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par)
|
||||
{
|
||||
int success;
|
||||
int numParticles = 0;
|
||||
|
||||
success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight);
|
||||
wpi_setImaqErrorWithContext(success, "Error getting image size");
|
||||
if (StatusIsFatal())
|
||||
return;
|
||||
|
||||
success = imaqCountParticles(m_imaqImage, 1, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error counting particles");
|
||||
if (StatusIsFatal())
|
||||
return;
|
||||
|
||||
if (particleNumber >= numParticles)
|
||||
{
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber");
|
||||
return;
|
||||
}
|
||||
|
||||
par->particleIndex = particleNumber;
|
||||
// Don't bother measuring the rest of the particle if one fails
|
||||
bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X, &par->center_mass_x);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y, &par->center_mass_y);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP, &par->boundingRect.top);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT, &par->boundingRect.left);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT, &par->boundingRect.height);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH, &par->boundingRect.width);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA, &par->particleToImagePercent);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &par->particleQuality);
|
||||
|
||||
if (good)
|
||||
{
|
||||
/* normalized position (-1 to 1) */
|
||||
par->center_mass_x_normalized = NormalizeFromRange(par->center_mass_x, par->imageWidth);
|
||||
par->center_mass_y_normalized = NormalizeFromRange(par->center_mass_y, par->imageHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an ordered vector of particles for the image.
|
||||
* Create a vector of particle analysis reports sorted by size for an image.
|
||||
* The vector contains the actual report structures.
|
||||
* @returns a pointer to the vector of particle analysis reports. The caller must delete the
|
||||
* vector when finished using it.
|
||||
*/
|
||||
vector<ParticleAnalysisReport>* BinaryImage::GetOrderedParticleAnalysisReports()
|
||||
{
|
||||
vector<ParticleAnalysisReport>* particles = new vector<ParticleAnalysisReport>;
|
||||
int particleCount = GetNumberParticles();
|
||||
for(int particleIndex = 0; particleIndex < particleCount; particleIndex++)
|
||||
{
|
||||
particles->push_back(GetParticleAnalysisReport(particleIndex));
|
||||
}
|
||||
// TODO: This is pretty inefficient since each compare in the sort copies
|
||||
// both reports being compared... do it manually instead... while we're
|
||||
// at it, we should provide a version that allows a preallocated buffer of
|
||||
// ParticleAnalysisReport structures
|
||||
sort(particles->begin(), particles->end(), CompareParticleSizes);
|
||||
return particles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a binary image to flash.
|
||||
* Writes the binary image to flash on the cRIO for later inspection.
|
||||
* @param fileName the name of the image file written to the flash.
|
||||
*/
|
||||
void BinaryImage::Write(const char *fileName)
|
||||
{
|
||||
RGBValue colorTable[256];
|
||||
memset(colorTable, 0, sizeof(colorTable));
|
||||
colorTable[0].R = 0;
|
||||
colorTable[1].R = 255;
|
||||
colorTable[0].G = colorTable[1].G = 0;
|
||||
colorTable[0].B = colorTable[1].B = 0;
|
||||
colorTable[0].alpha = colorTable[1].alpha = 0;
|
||||
imaqWriteFile(m_imaqImage, fileName, colorTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure a single parameter for an image.
|
||||
* Get the measurement for a single parameter about an image by calling the imaqMeasureParticle
|
||||
* function for the selected parameter.
|
||||
* @param particleNumber which particle in the set of particles
|
||||
* @param whatToMeasure the imaq MeasurementType (what to measure)
|
||||
* @param result the value of the measurement
|
||||
* @returns false on failure, true on success
|
||||
*/
|
||||
bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result)
|
||||
{
|
||||
double resultDouble;
|
||||
bool success = ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble);
|
||||
*result = (int)resultDouble;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure a single parameter for an image.
|
||||
* Get the measurement for a single parameter about an image by calling the imaqMeasureParticle
|
||||
* function for the selected parameter.
|
||||
* @param particleNumber which particle in the set of particles
|
||||
* @param whatToMeasure the imaq MeasurementType (what to measure)
|
||||
* @param result the value of the measurement
|
||||
* @returns true on failure, false on success
|
||||
*/
|
||||
bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result)
|
||||
{
|
||||
int success;
|
||||
success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure, result);
|
||||
wpi_setImaqErrorWithContext(success, "Error measuring particle");
|
||||
return !StatusIsFatal();
|
||||
}
|
||||
|
||||
//Normalizes to [-1,1]
|
||||
double BinaryImage::NormalizeFromRange(double position, int range)
|
||||
{
|
||||
return (position * 2.0 / (double)range) - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The compare helper function for sort.
|
||||
* This function compares two particle analysis reports as a helper for the sort function.
|
||||
* @param particle1 The first particle to compare
|
||||
* @param particle2 the second particle to compare
|
||||
* @returns true if particle1 is greater than particle2
|
||||
*/
|
||||
bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2)
|
||||
{
|
||||
//we want descending sort order
|
||||
return particle1.particleToImagePercent > particle2.particleToImagePercent;
|
||||
}
|
||||
|
||||
BinaryImage *BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions)
|
||||
{
|
||||
BinaryImage *result = new BinaryImage();
|
||||
int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_LARGE, NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage *BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions)
|
||||
{
|
||||
BinaryImage *result = new BinaryImage();
|
||||
int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_SMALL, NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage *BinaryImage::ConvexHull(bool connectivity8)
|
||||
{
|
||||
BinaryImage *result = new BinaryImage();
|
||||
int success = imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);
|
||||
wpi_setImaqErrorWithContext(success, "Error in convex hull operation");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage *BinaryImage::ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount)
|
||||
{
|
||||
BinaryImage *result = new BinaryImage();
|
||||
int numParticles;
|
||||
ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};
|
||||
int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage, criteria, criteriaCount, &filterOptions, NULL, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error in particle filter operation");
|
||||
return result;
|
||||
}
|
||||
|
||||
465
wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp
Normal file
465
wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp
Normal file
@@ -0,0 +1,465 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/ColorImage.h"
|
||||
|
||||
#include "WPIErrors.h"
|
||||
|
||||
ColorImage::ColorImage(ImageType type) : ImageBase(type)
|
||||
{
|
||||
}
|
||||
|
||||
ColorImage::~ColorImage()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold operation on a ColorImage.
|
||||
* Perform a threshold operation on a ColorImage using the ColorMode supplied
|
||||
* as a parameter.
|
||||
* @param colorMode The type of colorspace this operation should be performed in
|
||||
* @returns a pointer to a binary image
|
||||
*/
|
||||
BinaryImage *ColorImage::ComputeThreshold(ColorMode colorMode,
|
||||
int low1, int high1,
|
||||
int low2, int high2,
|
||||
int low3, int high3)
|
||||
{
|
||||
BinaryImage *result = new BinaryImage();
|
||||
Range range1 = {low1, high1},
|
||||
range2 = {low2, high2},
|
||||
range3 = {low3, high3};
|
||||
|
||||
int success = imaqColorThreshold(result->GetImaqImage(), m_imaqImage, 1, colorMode, &range1, &range2, &range3);
|
||||
wpi_setImaqErrorWithContext(success, "ImaqThreshold error");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in RGB space.
|
||||
* @param redLow Red low value
|
||||
* @param redHigh Red high value
|
||||
* @param greenLow Green low value
|
||||
* @param greenHigh Green high value
|
||||
* @param blueLow Blue low value
|
||||
* @param blueHigh Blue high value
|
||||
* @returns A pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_RGB, redLow, redHigh, greenLow, greenHigh, blueLow, blueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in RGB space.
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @returns A pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdRGB(Threshold &t)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_RGB, t.plane1Low, t.plane1High,
|
||||
t.plane2Low, t.plane2High,
|
||||
t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSL space.
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param luminenceLow Low value for luminence
|
||||
* @param luminenceHigh High value for luminence
|
||||
* @returns a pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSL, hueLow, hueHigh, saturationLow, saturationHigh, luminenceLow, luminenceHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSL space.
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @returns A pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSL(Threshold &t)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSL, t.plane1Low, t.plane1High,
|
||||
t.plane2Low, t.plane2High,
|
||||
t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSV space.
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param valueLow Low value
|
||||
* @param valueHigh High value
|
||||
* @returns a pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueLow, int valueHigh)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSV, hueLow, hueHigh, saturationLow, saturationHigh, valueLow, valueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSV space.
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @returns A pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSV(Threshold &t)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSV, t.plane1Low, t.plane1High,
|
||||
t.plane2Low, t.plane2High,
|
||||
t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSI space.
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param valueLow Low intensity
|
||||
* @param valueHigh High intensity
|
||||
* @returns a pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSI, hueLow, hueHigh, saturationLow, saturationHigh, intensityLow, intensityHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSI space.
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @returns A pointer to a BinaryImage that represents the result of the threshold operation.
|
||||
*/
|
||||
BinaryImage *ColorImage::ThresholdHSI(Threshold &t)
|
||||
{
|
||||
return ComputeThreshold(IMAQ_HSI, t.plane1Low, t.plane1High,
|
||||
t.plane2Low, t.plane2High,
|
||||
t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a color plane from the image
|
||||
* @param mode The ColorMode to use for the plane extraction
|
||||
* @param planeNumber Which plane is to be extracted
|
||||
* @returns A pointer to a MonoImage that represents the extracted plane.
|
||||
*/
|
||||
MonoImage *ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber)
|
||||
{
|
||||
MonoImage *result = new MonoImage();
|
||||
if (m_imaqImage == NULL)
|
||||
wpi_setWPIError(NullParameter);
|
||||
int success = imaqExtractColorPlanes(m_imaqImage,
|
||||
mode,
|
||||
(planeNumber == 1) ? result->GetImaqImage() : NULL,
|
||||
(planeNumber == 2) ? result->GetImaqImage() : NULL,
|
||||
(planeNumber == 3) ? result->GetImaqImage() : NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed");
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the first color plane for an image.
|
||||
* @param mode The color mode in which to operate
|
||||
* @returns a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage *ColorImage::ExtractFirstColorPlane(ColorMode mode)
|
||||
{
|
||||
return ExtractColorPlane(mode, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the second color plane for an image.
|
||||
* @param mode The color mode in which to operate
|
||||
* @returns a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage *ColorImage::ExtractSecondColorPlane(ColorMode mode)
|
||||
{
|
||||
return ExtractColorPlane(mode, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the third color plane for an image.
|
||||
* @param mode The color mode in which to operate
|
||||
* @returns a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage *ColorImage::ExtractThirdColorPlane(ColorMode mode)
|
||||
{
|
||||
return ExtractColorPlane(mode, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the red plane from an RGB image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetRedPlane()
|
||||
{
|
||||
return ExtractFirstColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the green plane from an RGB image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetGreenPlane()
|
||||
{
|
||||
return ExtractSecondColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the blue plane from an RGB image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetBluePlane()
|
||||
{
|
||||
return ExtractThirdColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Hue plane from an HSL image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetHSLHuePlane()
|
||||
{
|
||||
return ExtractFirstColorPlane(IMAQ_HSL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Hue plane from an HSV image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetHSVHuePlane()
|
||||
{
|
||||
return ExtractFirstColorPlane(IMAQ_HSV);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Hue plane from an HSI image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetHSIHuePlane()
|
||||
{
|
||||
return ExtractFirstColorPlane(IMAQ_HSI);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Luminance plane from an HSL image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetLuminancePlane()
|
||||
{
|
||||
return ExtractThirdColorPlane(IMAQ_HSL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Value plane from an HSV image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetValuePlane()
|
||||
{
|
||||
return ExtractThirdColorPlane(IMAQ_HSV);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Intensity plane from an HSI image.
|
||||
* @returns a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage *ColorImage::GetIntensityPlane()
|
||||
{
|
||||
return ExtractThirdColorPlane(IMAQ_HSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a plane in the ColorImage with a MonoImage
|
||||
* Replaces a single plane in the image with a MonoImage
|
||||
* @param mode The ColorMode in which to operate
|
||||
* @param plane The pointer to the replacement plane as a MonoImage
|
||||
* @param planeNumber The plane number (1, 2, 3) to replace
|
||||
*/
|
||||
void ColorImage::ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber) {
|
||||
int success = imaqReplaceColorPlanes(m_imaqImage,
|
||||
(const Image*) m_imaqImage,
|
||||
mode,
|
||||
(planeNumber == 1) ? plane->GetImaqImage() : NULL,
|
||||
(planeNumber == 2) ? plane->GetImaqImage() : NULL,
|
||||
(planeNumber == 3) ? plane->GetImaqImage() : NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReplaceColorPlanes failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane)
|
||||
{
|
||||
ReplacePlane(mode, plane, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the second color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane)
|
||||
{
|
||||
ReplacePlane(mode, plane, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the third color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane)
|
||||
{
|
||||
ReplacePlane(mode, plane, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the red color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceRedPlane(MonoImage *plane)
|
||||
{
|
||||
ReplaceFirstColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the green color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceGreenPlane(MonoImage *plane)
|
||||
{
|
||||
ReplaceSecondColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the blue color plane with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceBluePlane(MonoImage *plane)
|
||||
{
|
||||
ReplaceThirdColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace the Hue color plane in a HSL image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSLHuePlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceFirstColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Hue color plane in a HSV image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSVHuePlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceFirstColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first Hue plane in a HSI image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSIHuePlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceFirstColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in an HSL image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSLSaturationPlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceSecondColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in a HSV image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSVSaturationPlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceSecondColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in a HSI image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSISaturationPlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceSecondColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Luminance color plane in an HSL image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceLuminancePlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceThirdColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Value color plane in an HSV with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceValuePlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceThirdColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Intensity color plane in a HSI image with a MonoImage.
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color plane.
|
||||
*/
|
||||
void ColorImage::ReplaceIntensityPlane(MonoImage *plane)
|
||||
{
|
||||
return ReplaceThirdColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
//TODO: frcColorEqualize(Image* dest, const Image* source, int colorEqualization) needs to be modified
|
||||
//The colorEqualization parameter is discarded and is set to TRUE in the call to imaqColorEqualize.
|
||||
void ColorImage::Equalize(bool allPlanes)
|
||||
{
|
||||
// Note that this call uses NI-defined TRUE and FALSE
|
||||
int success = imaqColorEqualize(m_imaqImage, (const Image*) m_imaqImage, (allPlanes) ? TRUE : FALSE);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ColorEqualize error");
|
||||
}
|
||||
|
||||
void ColorImage::ColorEqualize()
|
||||
{
|
||||
Equalize(true);
|
||||
}
|
||||
|
||||
void ColorImage::LuminanceEqualize()
|
||||
{
|
||||
Equalize(false);
|
||||
}
|
||||
1227
wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp
Normal file
1227
wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp
Normal file
28
wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/HSLImage.h"
|
||||
|
||||
/**
|
||||
* Create a new image that uses the Hue, Saturation, and Luminance planes.
|
||||
*/
|
||||
HSLImage::HSLImage() : ColorImage(IMAQ_IMAGE_HSL)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
HSLImage::HSLImage(const char *fileName) : ColorImage(IMAQ_IMAGE_HSL)
|
||||
{
|
||||
int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
|
||||
}
|
||||
|
||||
HSLImage::~HSLImage()
|
||||
{
|
||||
}
|
||||
73
wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp
Normal file
73
wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/ImageBase.h"
|
||||
#include "nivision.h"
|
||||
|
||||
/**
|
||||
* Create a new instance of an ImageBase.
|
||||
* Imagebase is the base of all the other image classes. The constructor
|
||||
* creates any type of image and stores the pointer to it in the class.
|
||||
* @param type The type of image to create
|
||||
*/
|
||||
ImageBase::ImageBase(ImageType type)
|
||||
{
|
||||
m_imaqImage = imaqCreateImage(type, DEFAULT_BORDER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees memory associated with an ImageBase.
|
||||
* Destructor frees the imaq image allocated with the class.
|
||||
*/
|
||||
ImageBase::~ImageBase()
|
||||
{
|
||||
if(m_imaqImage)
|
||||
imaqDispose(m_imaqImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an image to a file with the given filename.
|
||||
* Write the image to a file in the flash on the cRIO.
|
||||
* @param fileName The name of the file to write
|
||||
*/
|
||||
void ImageBase::Write(const char *fileName)
|
||||
{
|
||||
int success = imaqWriteFile(m_imaqImage, fileName, NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq Image writeFile error");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of an image.
|
||||
* @return The height of the image in pixels.
|
||||
*/
|
||||
int ImageBase::GetHeight()
|
||||
{
|
||||
int height;
|
||||
imaqGetImageSize(m_imaqImage, NULL, &height);
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of an image.
|
||||
* @return The width of the image in pixels.
|
||||
*/
|
||||
int ImageBase::GetWidth()
|
||||
{
|
||||
int width;
|
||||
imaqGetImageSize(m_imaqImage, &width, NULL);
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the internal IMAQ Image data structure.
|
||||
*
|
||||
* @return A pointer to the internal IMAQ Image data structure.
|
||||
*/
|
||||
Image *ImageBase::GetImaqImage()
|
||||
{
|
||||
return m_imaqImage;
|
||||
}
|
||||
|
||||
55
wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp
Normal file
55
wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/MonoImage.h"
|
||||
#include "nivision.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
MonoImage::MonoImage() : ImageBase(IMAQ_IMAGE_U8)
|
||||
{
|
||||
}
|
||||
|
||||
MonoImage::~MonoImage()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for ellipses in an image.
|
||||
* Given some input parameters, look for any number of ellipses in an image.
|
||||
* @param ellipseDescriptor Ellipse descriptor
|
||||
* @param curveOptions Curve options
|
||||
* @param shapeDetectionOptions Shape detection options
|
||||
* @param roi Region of Interest
|
||||
* @returns a vector of EllipseMatch structures (0 length vector on no match)
|
||||
*/
|
||||
vector<EllipseMatch> * MonoImage::DetectEllipses(
|
||||
EllipseDescriptor *ellipseDescriptor, CurveOptions *curveOptions,
|
||||
ShapeDetectionOptions *shapeDetectionOptions, ROI *roi)
|
||||
{
|
||||
int numberOfMatches;
|
||||
EllipseMatch *e = imaqDetectEllipses(m_imaqImage, ellipseDescriptor,
|
||||
curveOptions, shapeDetectionOptions, roi, &numberOfMatches);
|
||||
vector<EllipseMatch> *ellipses = new vector<EllipseMatch>;
|
||||
if (e == NULL)
|
||||
{
|
||||
return ellipses;
|
||||
}
|
||||
for (int i = 0; i < numberOfMatches; i++)
|
||||
{
|
||||
ellipses->push_back(e[i]);
|
||||
}
|
||||
imaqDispose(e);
|
||||
return ellipses;
|
||||
}
|
||||
|
||||
vector<EllipseMatch> * MonoImage::DetectEllipses(
|
||||
EllipseDescriptor *ellipseDescriptor)
|
||||
{
|
||||
vector<EllipseMatch> *ellipses = DetectEllipses(ellipseDescriptor, NULL,
|
||||
NULL, NULL);
|
||||
return ellipses;
|
||||
}
|
||||
28
wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp
Normal file
28
wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/RGBImage.h"
|
||||
|
||||
/**
|
||||
* Create a new image that uses Red, Green, and Blue planes.
|
||||
*/
|
||||
RGBImage::RGBImage() : ColorImage(IMAQ_IMAGE_RGB)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
RGBImage::RGBImage(const char *fileName) : ColorImage(IMAQ_IMAGE_RGB)
|
||||
{
|
||||
int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
|
||||
}
|
||||
|
||||
RGBImage::~RGBImage()
|
||||
{
|
||||
}
|
||||
18
wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp
Normal file
18
wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/Threshold.h"
|
||||
|
||||
Threshold::Threshold(int new_plane1Low, int new_plane1High, int new_plane2Low,
|
||||
int new_plane2High, int new_plane3Low, int new_plane3High)
|
||||
{
|
||||
plane1Low = new_plane1Low;
|
||||
plane1High = new_plane1High;
|
||||
plane2Low = new_plane2Low;
|
||||
plane2High = new_plane2High;
|
||||
plane3Low = new_plane3Low;
|
||||
plane3High = new_plane3High;
|
||||
}
|
||||
665
wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp
Normal file
665
wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp
Normal file
@@ -0,0 +1,665 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Vision/BaeUtilities.h"
|
||||
#include "Vision/FrcError.h"
|
||||
#include "Vision/VisionAPI.h"
|
||||
|
||||
int VisionAPI_debugFlag = 1;
|
||||
#define DPRINTF if(VisionAPI_debugFlag)dprintf
|
||||
|
||||
/* Image Management functions */
|
||||
|
||||
/**
|
||||
* @brief Create an image object
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64
|
||||
* The border size is defaulted to 3 so that convolutional algorithms work at the edges.
|
||||
* When you are finished with the created image, dispose of it by calling frcDispose().
|
||||
* To get extended error information, call GetLastError().
|
||||
*
|
||||
* @param type Type of image to create
|
||||
* @return Image* On success, this function returns the created image. On failure, it returns NULL.
|
||||
*/
|
||||
Image* frcCreateImage(ImageType type) { return imaqCreateImage(type, DEFAULT_BORDER_SIZE); }
|
||||
|
||||
/**
|
||||
* @brief Dispose of one object. Supports any object created on the heap.
|
||||
*
|
||||
* @param object object to dispose of
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcDispose(void* object) { return imaqDispose(object); }
|
||||
/**
|
||||
* @brief Dispose of a list of objects. Supports any object created on the heap.
|
||||
*
|
||||
* @param functionName The name of the function
|
||||
* @param ... A list of pointers to structures that need to be disposed of.
|
||||
* The last pointer in the list should always be set to NULL.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcDispose( const char* functionName, ... ) /* Variable argument list */
|
||||
{
|
||||
va_list disposalPtrList; /* Input argument list */
|
||||
void* disposalPtr; /* For iteration */
|
||||
int success, returnValue = 1;
|
||||
|
||||
va_start( disposalPtrList, functionName ); /* start of variable list */
|
||||
disposalPtr = va_arg( disposalPtrList, void* );
|
||||
while( disposalPtr != NULL ) {
|
||||
success = imaqDispose(disposalPtr);
|
||||
if (!success) {returnValue = 0;}
|
||||
disposalPtr = va_arg( disposalPtrList, void* );
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy an image object.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Copy of image. On failure, dest is NULL. Must have already been created using frcCreateImage().
|
||||
* When you are finished with the created image, dispose of it by calling frcDispose().
|
||||
* @param source Image to copy
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcCopyImage(Image* dest, const Image* source) { return imaqDuplicate(dest, source); }
|
||||
|
||||
/**
|
||||
* @brief Crop image without changing the scale.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Modified image
|
||||
* @param source Image to crop
|
||||
* @param rect region to process, or IMAQ_NO_RECT
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcCrop(Image* dest, const Image* source, Rect rect)
|
||||
{
|
||||
return imaqScale(dest, source, 1, 1, IMAQ_SCALE_LARGER, rect);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Scales the entire image larger or smaller.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Modified image
|
||||
* @param source Image to scale
|
||||
* @param xScale the horizontal reduction ratio
|
||||
* @param yScale the vertical reduction ratio
|
||||
* @param scaleMode IMAQ_SCALE_LARGER or IMAQ_SCALE_SMALLER
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode)
|
||||
{
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return imaqScale(dest, source, xScale, yScale, scaleMode, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates image object from the information in a file. The file can be in one of the following formats:
|
||||
* PNG, JPEG, JPEG2000, TIFF, AIPD, or BMP.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* @param image Image read in
|
||||
* @param fileName File to read. Cannot be NULL
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcReadImage(Image* image, const char* fileName)
|
||||
{
|
||||
return imaqReadFile(image, fileName, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write image to a file.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* The file type is determined by the extension, as follows:
|
||||
*
|
||||
* Extension File Type
|
||||
* aipd or .apd AIPD
|
||||
* .bmp BMP
|
||||
* .jpg or .jpeg JPEG
|
||||
* .jp2 JPEG2000
|
||||
* .png PNG
|
||||
* .tif or .tiff TIFF
|
||||
*
|
||||
*
|
||||
*The following are the supported image types for each file type:
|
||||
*
|
||||
* File Types Image Types
|
||||
* AIPD all image types
|
||||
* BMP, JPEG 8-bit, RGB
|
||||
* PNG, TIFF, JPEG2000 8-bit, 16-bit, RGB, RGBU64
|
||||
*
|
||||
* @param image Image to write
|
||||
* @param fileName File to read. Cannot be NULL. The extension determines the file format that is written.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcWriteImage(const Image* image, const char* fileName)
|
||||
{
|
||||
RGBValue* colorTable = NULL;
|
||||
return imaqWriteFile(image, fileName, colorTable);
|
||||
}
|
||||
|
||||
|
||||
/* Measure Intensity functions */
|
||||
|
||||
/**
|
||||
* @brief Measures the pixel intensities in a rectangle of an image.
|
||||
* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* Parameter Discussion :
|
||||
* Relevant parameters of the HistogramReport include:
|
||||
* min, max, mean and stdDev
|
||||
* min/max —Setting both min and max to 0 causes the function to set min to 0
|
||||
* and the max to 255 for 8-bit images and to the actual minimum value and
|
||||
* maximum value of the image for all other image types.
|
||||
* max—Setting both min and max to 0 causes the function to set max to 255
|
||||
* for 8-bit images and to the actual maximum value of the image for
|
||||
* all other image types.
|
||||
*
|
||||
* @param image Image whose histogram the function calculates.
|
||||
* @param numClasses The number of classes into which the function separates the pixels.
|
||||
* Determines the number of elements in the histogram array returned
|
||||
* @param min The minimum pixel value to consider for the histogram.
|
||||
* The function does not count pixels with values less than min.
|
||||
* @param max The maximum pixel value to consider for the histogram.
|
||||
* The function does not count pixels with values greater than max.
|
||||
* @param rect Region of interest in the image. If not included, the entire image is used.
|
||||
* @return On success, this function returns a report describing the pixel value classification.
|
||||
* When you are finished with the report, dispose of it by calling frcDispose().
|
||||
* On failure, this function returns NULL. To get extended error information, call GetLastError().
|
||||
*
|
||||
*/
|
||||
HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max)
|
||||
{
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return frcHistogram(image, numClasses, min, max, rect);
|
||||
}
|
||||
HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max, Rect rect)
|
||||
{
|
||||
int success;
|
||||
int fillValue = 1;
|
||||
|
||||
/* create the region of interest */
|
||||
ROI* pRoi = imaqCreateROI();
|
||||
success = imaqAddRectContour(pRoi, rect);
|
||||
if ( !success ) { GetLastVisionError(); return NULL; }
|
||||
|
||||
/* make a mask from the ROI */
|
||||
Image* pMask = frcCreateImage(IMAQ_IMAGE_U8);
|
||||
success = imaqROIToMask(pMask, pRoi, fillValue, NULL, NULL);
|
||||
if ( !success ) {
|
||||
GetLastVisionError();
|
||||
frcDispose(__FUNCTION__, pRoi, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get a histogram report */
|
||||
HistogramReport* pHr = NULL;
|
||||
pHr = imaqHistogram(image, numClasses, min, max, pMask);
|
||||
|
||||
/* clean up */
|
||||
frcDispose(__FUNCTION__, pRoi, pMask, NULL);
|
||||
|
||||
return pHr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the histogram, or pixel distribution, of a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param image Image whose histogram the function calculates.
|
||||
* @param numClasses The number of classes into which the function separates the pixels.
|
||||
* Determines the number of elements in the histogram array returned
|
||||
* @param mode The color space in which to perform the histogram. Possible values include IMAQ_RGB and IMAQ_HSL.
|
||||
* @param mask An optional mask image. This image must be an IMAQ_IMAGE_U8 image.
|
||||
* The function calculates the histogram using only those pixels in the image whose
|
||||
* corresponding pixels in the mask are non-zero. Set this parameter to NULL to calculate
|
||||
* the histogram of the entire image, or use the simplified call.
|
||||
*
|
||||
* @return On success, this function returns a report describing the classification
|
||||
* of each plane in a HistogramReport.
|
||||
* When you are finished with the report, dispose of it by calling frcDispose().
|
||||
* On failure, this function returns NULL.
|
||||
* To get extended error information, call imaqGetLastError().
|
||||
*/
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode)
|
||||
{
|
||||
return frcColorHistogram(image, numClasses, mode, NULL);
|
||||
}
|
||||
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask)
|
||||
{
|
||||
return imaqColorHistogram2((Image*)image, numClasses, mode, NULL, mask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Measures the pixel intensities in a rectangle of an image.
|
||||
* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value.
|
||||
* Supports IMAQ_IMAGE_U8 (grayscale) IMAQ_IMAGE_RGB (color) IMAQ_IMAGE_HSL (color-HSL).
|
||||
*
|
||||
* @param image The image whose pixel value the function queries
|
||||
* @param pixel The coordinates of the pixel that the function queries
|
||||
* @param value On return, the value of the specified image pixel. This parameter cannot be NULL.
|
||||
* This data structure contains either grayscale, RGB, HSL, Complex or RGBU64Value depending on the type of image.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcGetPixelValue(const Image* image, Point pixel, PixelValue* value)
|
||||
{
|
||||
return imaqGetPixel(image, pixel, value);
|
||||
}
|
||||
|
||||
|
||||
/* Particle Analysis functions */
|
||||
|
||||
/**
|
||||
* @brief Filters particles out of an image based on their measurements.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* @param dest The destination image. If dest is used, it must be the same size as the Source image. It will contain only the filtered particles.
|
||||
* @param source The image containing the particles to filter.
|
||||
* @param criteria An array of criteria to apply to the particles in the source image. This array cannot be NULL.
|
||||
* See the NIVisionCVI.chm help file for definitions of criteria.
|
||||
* @param criteriaCount The number of elements in the criteria array.
|
||||
* @param options Binary filter options, including rejectMatches, rejectBorder, and connectivity8.
|
||||
* @param rect Area of image to filter. If omitted, the default is entire image.
|
||||
* @param numParticles On return, the number of particles left in the image
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options, int* numParticles)
|
||||
{
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return frcParticleFilter(dest, source, criteria, criteriaCount, options, rect, numParticles);
|
||||
}
|
||||
|
||||
int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles)
|
||||
{
|
||||
ROI* roi = imaqCreateROI();
|
||||
imaqAddRectContour(roi, rect);
|
||||
return imaqParticleFilter3(dest, source, criteria, criteriaCount, options, roi, numParticles);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Performs morphological transformations on binary images.
|
||||
* Supports IMAQ_IMAGE_U8.
|
||||
*
|
||||
* @param dest The destination image. The border size of the destination image is not important.
|
||||
* @param source The image on which the function performs the morphological operations. The calculation
|
||||
* modifies the border of the source image. The border must be at least half as large as the larger
|
||||
* dimension of the structuring element. The connected source image for a morphological transformation
|
||||
* must have been created with a border capable of supporting the size of the structuring element.
|
||||
* A 3 by 3 structuring element requires a minimal border of 1, a 5 by 5 structuring element requires a minimal border of 2, and so on.
|
||||
* @param method The morphological transform to apply.
|
||||
* @param structuringElement The structuring element used in the operation. Omit this parameter if you do not want a custom structuring element.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method)
|
||||
{
|
||||
return imaqMorphology(dest, source, method, NULL);
|
||||
}
|
||||
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement)
|
||||
{
|
||||
return imaqMorphology(dest, source, method, structuringElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Eliminates particles that touch the border of the image.
|
||||
* Supports IMAQ_IMAGE_U8.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The source image. If the image has a border, the function sets all border pixel values to 0.
|
||||
* @param connectivity8 specifies the type of connectivity used by the algorithm for particle detection.
|
||||
* The connectivity mode directly determines whether an adjacent pixel belongs to the same particle or a
|
||||
* different particle. Set to TRUE to use connectivity-8 to determine whether particles are touching
|
||||
* Set to FALSE to use connectivity-4 to determine whether particles are touching.
|
||||
* The default setting for the simplified call is TRUE
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcRejectBorder(Image* dest, Image* source)
|
||||
{ return imaqRejectBorder(dest, source, TRUE); }
|
||||
|
||||
int frcRejectBorder(Image* dest, Image* source, int connectivity8)
|
||||
{
|
||||
return imaqRejectBorder(dest, source, connectivity8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Counts the number of particles in a binary image.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
* @param image binary (thresholded) image
|
||||
* @param numParticles On return, the number of particles.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcCountParticles(Image* image, int* numParticles)
|
||||
{
|
||||
return imaqCountParticles(image, 1, numParticles);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Conduct measurements for a single particle in an images.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* @param image image with the particle to analyze. This function modifies the source image.
|
||||
* If you need the original image, create a copy of the image using frcCopy() before using this function.
|
||||
* @param particleNumber The number of the particle to get information on
|
||||
* @param par on return, a particle analysis report containing information about the particle. This structure must be created by the caller.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
/* image information */
|
||||
int height, width;
|
||||
if ( ! imaqGetImageSize(image, &width, &height) ) { return success; }
|
||||
par->imageWidth = width;
|
||||
par->imageHeight = height;
|
||||
par->particleIndex = particleNumber;
|
||||
|
||||
/* center of mass point of the largest particle */
|
||||
double returnDouble;
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_X, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->center_mass_x = (int)returnDouble; // pixel
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_Y, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->center_mass_y = (int)returnDouble; // pixel
|
||||
|
||||
/* particle size statistics */
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->particleArea = returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_TOP, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->boundingRect.top = (int)returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_LEFT, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->boundingRect.left = (int)returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_HEIGHT, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->boundingRect.height = (int)returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_WIDTH, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->boundingRect.width = (int)returnDouble;
|
||||
|
||||
/* particle quality statistics */
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_IMAGE_AREA, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->particleToImagePercent = returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &returnDouble);
|
||||
if ( !success ) { return success; }
|
||||
par->particleQuality = returnDouble;
|
||||
|
||||
/* normalized position (-1 to 1) */
|
||||
par->center_mass_x_normalized = RangeToNormalized(par->center_mass_x, width);
|
||||
par->center_mass_y_normalized = RangeToNormalized(par->center_mass_y, height);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/* Image Enhancement functions */
|
||||
|
||||
/**
|
||||
* @brief Improves contrast on a grayscale image.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16.
|
||||
* @param dest The destination image.
|
||||
* @param source The image to equalize
|
||||
* @param min the smallest value used for processing. After processing, all pixel values that are less than or equal to the Minimum in the original image are set to 0 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the smallest pixel value found in the original image.
|
||||
* @param max the largest value used for processing. After processing, all pixel values that are greater than or equal to the Maximum in the original image are set to 255 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the largest pixel value found in the original image.
|
||||
* @param mask an 8-bit image that specifies the region of the small image that will be copied. Only those pixels in the Image Src (Small) image that correspond to an equivalent non-zero pixel in the mask image are copied. All other pixels keep their original values. The entire image is processed if Image Mask is NULL or this parameter is omitted.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*
|
||||
* option defaults:
|
||||
* searchRect = IMAQ_NO_RECT
|
||||
* minMatchScore = DEFAULT_MINMAX_SCORE (800)
|
||||
*/
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max)
|
||||
{ return frcEqualize(dest, source, min, max, NULL); }
|
||||
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask)
|
||||
{
|
||||
return imaqEqualize(dest, source, min, max, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Improves contrast on a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL
|
||||
*
|
||||
* option defaults: colorEqualization = TRUE to equalize all three planes of the image
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
* @param dest The destination image.
|
||||
* @param source The image to equalize
|
||||
* @param colorEqualization Set this parameter to TRUE to equalize all three planes of the image (the default). Set this parameter to FALSE to equalize only the luminance plane.
|
||||
*/
|
||||
int frcColorEqualize(Image* dest, const Image* source)
|
||||
{
|
||||
return imaqColorEqualize(dest, source, TRUE);
|
||||
}
|
||||
|
||||
int frcColorEqualize(Image* dest, const Image* source, int colorEqualization)
|
||||
{
|
||||
return imaqColorEqualize(dest, source, TRUE);
|
||||
}
|
||||
|
||||
/* Image Conversion functions */
|
||||
|
||||
/**
|
||||
* @brief Automatically thresholds a grayscale image into a binary image for Particle Analysis based on a smart threshold.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param windowWidth The width of the rectangular window around the pixel on which the function
|
||||
* performs the local threshold. This number must be at least 3 and cannot be larger than the width of source
|
||||
* @param windowHeight The height of the rectangular window around the pixel on which the function
|
||||
* performs the local threshold. This number must be at least 3 and cannot be larger than the height of source
|
||||
* @param method Specifies the local thresholding method the function uses. Value can be IMAQ_NIBLACK
|
||||
* (which computes thresholds for each pixel based on its local statistics using the Niblack local thresholding
|
||||
* algorithm.), or IMAQ_BACKGROUND_CORRECTION (which does background correction first to eliminate non-uniform
|
||||
* lighting effects, then performs thresholding using the Otsu thresholding algorithm)
|
||||
* @param deviationWeight Specifies the k constant used in the Niblack local thresholding algorithm, which
|
||||
* determines the weight applied to the variance calculation. Valid k constants range from 0 to 1. Setting
|
||||
* this value to 0 will increase the performance of the function because the function will not calculate the
|
||||
* variance for any of the pixels. The function ignores this value if method is not set to IMAQ_NIBLACK
|
||||
* @param type Specifies the type of objects for which you want to look. Values can be IMAQ_BRIGHT_OBJECTS
|
||||
* or IMAQ_DARK_OBJECTS.
|
||||
* @param replaceValue Specifies the replacement value the function uses for the pixels of the kept objects
|
||||
* in the destination image.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcSmartThreshold(Image* dest, const Image* source,
|
||||
unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type)
|
||||
{
|
||||
float replaceValue = 1.0;
|
||||
return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method,
|
||||
deviationWeight, type, replaceValue);
|
||||
}
|
||||
|
||||
int frcSmartThreshold(Image* dest, const Image* source,
|
||||
unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type, float replaceValue)
|
||||
{
|
||||
return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method,
|
||||
deviationWeight, type, replaceValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a grayscale image to a binary image for Particle Analysis based on a fixed threshold.
|
||||
* The function sets pixels values outside of the given range to 0. The function sets pixel values
|
||||
* within the range to a given value or leaves the values unchanged.
|
||||
* Use the simplified call to leave pixel values unchanged.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param rangeMin The lower boundary of the range of pixel values to keep
|
||||
* @param rangeMax The upper boundary of the range of pixel values to keep.
|
||||
*
|
||||
* @return int - error code: 0 = error. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax)
|
||||
{
|
||||
int newValue = 255;
|
||||
return frcSimpleThreshold(dest, source, rangeMin, rangeMax, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a grayscale image to a binary image for Particle Analysis based on a fixed threshold.
|
||||
* The function sets pixels values outside of the given range to 0. The function sets
|
||||
* pixel values within the range to the given value.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param rangeMin The lower boundary of the range of pixel values to keep
|
||||
* @param rangeMax The upper boundary of the range of pixel values to keep.
|
||||
* @param newValue The replacement value for pixels within the range. Use the simplified call to leave the pixel values unchanged
|
||||
*
|
||||
* @return int - error code: 0 = error. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue)
|
||||
{
|
||||
int useNewValue = TRUE;
|
||||
return imaqThreshold(dest, source, rangeMin, rangeMax, useNewValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image or the Hue,
|
||||
* Saturation, Luminance values for a HSL image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* This simpler version filters based on a hue range in the HSL mode.
|
||||
*
|
||||
* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
|
||||
* @param source The image to threshold
|
||||
* @param mode The color space to perform the threshold in. valid values are: IMAQ_RGB, IMAQ_HSL.
|
||||
* @param plane1Range The selection range for the first plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
* @param plane2Range The selection range for the second plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
* @param plane3Range The selection range for the third plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
* */
|
||||
int frcColorThreshold(Image* dest, const Image* source, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range, const Range* plane3Range)
|
||||
{
|
||||
int replaceValue = 1;
|
||||
return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range, plane2Range, plane3Range);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image or the Hue,
|
||||
* Saturation, Luminance values for a HSL image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* The simpler version filters based on a hue range in the HSL mode.
|
||||
*
|
||||
* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
|
||||
* @param source The image to threshold
|
||||
* @param replaceValue Value to assign to selected pixels. Defaults to 1 if simplified call is used.
|
||||
* @param mode The color space to perform the threshold in. valid values are: IMAQ_RGB, IMAQ_HSL.
|
||||
* @param plane1Range The selection range for the first plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
* @param plane2Range The selection range for the second plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
* @param plane3Range The selection range for the third plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range, const Range* plane3Range)
|
||||
{ return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range, plane2Range, plane3Range);}
|
||||
|
||||
|
||||
/**
|
||||
* @brief A simpler version of ColorThreshold that thresholds hue range in the HSL mode. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param hueRange The selection range for the hue (color).
|
||||
* @param minSaturation The minimum saturation value (1-255). If not used, DEFAULT_SATURATION_THRESHOLD is the default.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange)
|
||||
{ return frcHueThreshold(dest, source, hueRange, DEFAULT_SATURATION_THRESHOLD); }
|
||||
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation)
|
||||
{
|
||||
// assume HSL mode
|
||||
ColorMode mode = IMAQ_HSL;
|
||||
// Set saturation 100 - 255
|
||||
Range satRange; satRange.minValue = minSaturation; satRange.maxValue = 255;
|
||||
// Set luminance 100 - 255
|
||||
Range lumRange; lumRange.minValue = 100; lumRange.maxValue = 255;
|
||||
// Replace pixels with 1 if pass threshold filter
|
||||
int replaceValue = 1;
|
||||
return imaqColorThreshold(dest, source, replaceValue, mode, hueRange, &satRange, &lumRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts the Red, Green, Blue, or Hue, Saturation or Luminance information from a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* @param image The source image that the function extracts the planes from.
|
||||
* @param mode The color space that the function extracts the planes from. Valid values are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, IMAQ_HSI.
|
||||
* @param plane1 On return, the first extracted plane. Set this parameter to NULL if you do not need this information. RGB-Red, HSL/HSV/HSI-Hue.
|
||||
* @param plane2 On return, the second extracted plane. Set this parameter to NULL if you do not need this information. RGB-Green, HSL/HSV/HSI-Saturation.
|
||||
* @param plane3 On return, the third extracted plane. Set this parameter to NULL if you do not need this information. RGB-Blue, HSL-Luminance, HSV-Value, HSI-Intensity.
|
||||
*
|
||||
* @return error code: 0 = error. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcExtractColorPlanes(const Image* image, ColorMode mode,
|
||||
Image* plane1, Image* plane2, Image* plane3)
|
||||
{ return imaqExtractColorPlanes(image, mode, plane1, plane2, plane3); }
|
||||
|
||||
/**
|
||||
* @brief Extracts the Hue information from a color image. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64
|
||||
*
|
||||
* @param image The source image that the function extracts the plane from.
|
||||
* @param huePlane On return, the extracted hue plane.
|
||||
* @param minSaturation the minimum saturation level required 0-255 (try 50)
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
|
||||
*/
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane)
|
||||
{
|
||||
return frcExtractHuePlane(image, huePlane, DEFAULT_SATURATION_THRESHOLD);
|
||||
}
|
||||
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation)
|
||||
{
|
||||
return frcExtractColorPlanes(image, IMAQ_HSL, huePlane, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
// CounterBase interface
|
||||
int32_t Get();
|
||||
int32_t GetRaw();
|
||||
int32_t GetEncodingScale();
|
||||
void Reset();
|
||||
double GetPeriod();
|
||||
void SetMaxPeriod(double maxPeriod);
|
||||
@@ -59,6 +60,11 @@ public:
|
||||
void InitTable(ITable *subTable);
|
||||
ITable * GetTable();
|
||||
|
||||
int32_t FPGAEncoderIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitEncoder(int channelA, int channelB, bool _reverseDirection, EncodingType encodingType);
|
||||
double DecodingScaleFactor();
|
||||
@@ -70,6 +76,7 @@ private:
|
||||
int channelA, channelB;
|
||||
double m_distancePerPulse; // distance of travel for each encoder tick
|
||||
EncodingType m_encodingType; // Encoding type
|
||||
int32_t m_encodingScale; // 1x, 2x, or 4x, per the encodingType
|
||||
PIDSourceParameter m_pidSource; // Encoder parameter that sources a PID controller
|
||||
bool m_reverseDirection;
|
||||
SimEncoder* impl;
|
||||
|
||||
@@ -28,6 +28,9 @@ void Encoder::InitEncoder(int channelA, int channelB, bool reverseDirection, Enc
|
||||
this->channelA = channelA;
|
||||
this->channelB = channelB;
|
||||
m_encodingType = encodingType;
|
||||
m_encodingScale = encodingType == k4X ? 4
|
||||
: encodingType == k2X ? 2
|
||||
: 1;
|
||||
|
||||
int32_t index = 0;
|
||||
m_distancePerPulse = 1.0;
|
||||
@@ -188,6 +191,12 @@ double Encoder::DecodingScaleFactor()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The encoding scale factor 1x, 2x, or 4x, per the requested encodingType.
|
||||
* Used to divide raw edge counts down to spec'd counts.
|
||||
*/
|
||||
int32_t Encoder::GetEncodingScale() { return m_encodingScale; }
|
||||
|
||||
/**
|
||||
* Gets the raw value from the encoder.
|
||||
* The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<excludes>
|
||||
<exclude>edu/wpi/first/wpilibj/image/</exclude>
|
||||
<exclude>edu/wpi/first/wpilibj/camera/</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
@@ -77,7 +76,6 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<sourceFileExcludes>
|
||||
<exclude>edu/wpi/first/wpilibj/image/</exclude>
|
||||
<exclude>edu/wpi/first/wpilibj/camera/</exclude>
|
||||
</sourceFileExcludes>
|
||||
</configuration>
|
||||
|
||||
@@ -25004,6 +25004,16 @@ public class NIVision {
|
||||
}
|
||||
private static native long _imaqRake(long image, long roi, int direction, int process, long options);
|
||||
|
||||
public static void Priv_ReadJPEGString_C(Image image, byte[] string) {
|
||||
int stringLength = string.length;
|
||||
ByteBuffer string_buf = null;
|
||||
string_buf = ByteBuffer.allocateDirect(string.length);
|
||||
putBytes(string_buf, string, 0, string.length);
|
||||
_Priv_ReadJPEGString_C(image.getAddress(), getByteBufferAddress(string_buf), stringLength);
|
||||
|
||||
}
|
||||
private static native void _Priv_ReadJPEGString_C(long image, long string, int stringLength);
|
||||
|
||||
/**
|
||||
* Purpose : Include file for NI-IMAQdx library support.
|
||||
*/
|
||||
|
||||
@@ -10,12 +10,15 @@ import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tInst
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class ADXL345_I2C extends SensorBase implements Accelerometer {
|
||||
public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindowSendable {
|
||||
|
||||
private static final byte kAddress = 0x1D;
|
||||
private static final byte kPowerCtlRegister = 0x2D;
|
||||
@@ -53,7 +56,7 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param port The I2C port the accelerometer is attached to
|
||||
* @param range The range (+ or -) that the accelerometer will measure.
|
||||
*/
|
||||
public ADXL345_I2C(I2C.Port port, Range range) {
|
||||
@@ -65,6 +68,7 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer {
|
||||
setRange(range);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C);
|
||||
LiveWindow.addSensor("ADXL345_I2C", port.getValue(), this);
|
||||
}
|
||||
|
||||
/** {inheritdoc} */
|
||||
@@ -132,7 +136,7 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer {
|
||||
/**
|
||||
* Get the acceleration of all axes in Gs.
|
||||
*
|
||||
* @return Acceleration measured on all axes of the ADXL345 in Gs.
|
||||
* @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
|
||||
*/
|
||||
public AllAxes getAccelerations() {
|
||||
AllAxes data = new AllAxes();
|
||||
@@ -146,5 +150,32 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer {
|
||||
return data;
|
||||
}
|
||||
|
||||
// TODO: Support LiveWindow
|
||||
public String getSmartDashboardType(){
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("X", getX());
|
||||
m_table.putNumber("Y", getY());
|
||||
m_table.putNumber("Z", getZ());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ITable getTable(){
|
||||
return m_table;
|
||||
}
|
||||
|
||||
public void startLiveWindowMode() {}
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,16 @@ import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tInst
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dtjones
|
||||
* @author mwills
|
||||
*/
|
||||
public class ADXL345_SPI extends SensorBase implements Accelerometer {
|
||||
public class ADXL345_SPI extends SensorBase implements Accelerometer, LiveWindowSendable {
|
||||
private static final int kPowerCtlRegister = 0x2D;
|
||||
private static final int kDataFormatRegister = 0x31;
|
||||
private static final int kDataRegister = 0x32;
|
||||
@@ -69,12 +72,13 @@ public class ADXL345_SPI extends SensorBase implements Accelerometer {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param port the Port that the accelerometer is connected to
|
||||
* @param port The SPI port that the accelerometer is connected to
|
||||
* @param range The range (+ or -) that the accelerometer will measure.
|
||||
*/
|
||||
public ADXL345_SPI(SPI.Port port, Range range) {
|
||||
m_spi = new SPI(port);
|
||||
init(range);
|
||||
LiveWindow.addSensor("ADXL345_SPI", port.getValue(), this);
|
||||
}
|
||||
|
||||
public void free(){
|
||||
@@ -170,7 +174,7 @@ public class ADXL345_SPI extends SensorBase implements Accelerometer {
|
||||
/**
|
||||
* Get the acceleration of all axes in Gs.
|
||||
*
|
||||
* @return Acceleration measured on all axes of the ADXL345 in Gs.
|
||||
* @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
|
||||
*/
|
||||
public ADXL345_SPI.AllAxes getAccelerations() {
|
||||
ADXL345_SPI.AllAxes data = new ADXL345_SPI.AllAxes();
|
||||
@@ -190,4 +194,33 @@ public class ADXL345_SPI extends SensorBase implements Accelerometer {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getSmartDashboardType(){
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("X", getX());
|
||||
m_table.putNumber("Y", getY());
|
||||
m_table.putNumber("Z", getZ());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ITable getTable(){
|
||||
return m_table;
|
||||
}
|
||||
|
||||
public void startLiveWindowMode() {}
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
* Create a new instance of an accelerometer.
|
||||
*
|
||||
* The constructor allocates desired analog channel.
|
||||
* @param channel the port that the accelerometer is on
|
||||
* @param channel The channel number for the analog input the accelerometer is connected to
|
||||
*/
|
||||
public AnalogAccelerometer(final int channel) {
|
||||
m_allocatedChannel = true;
|
||||
@@ -52,7 +52,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
* Make a new instance of accelerometer given an AnalogChannel. This is particularly
|
||||
* useful if the port is going to be read as an analog channel as well as through
|
||||
* the Accelerometer class.
|
||||
* @param channel an already initialized analog channel
|
||||
* @param channel The existing AnalogInput object for the analog input the accelerometer is connected to
|
||||
*/
|
||||
public AnalogAccelerometer(AnalogInput channel) {
|
||||
m_allocatedChannel = false;
|
||||
@@ -87,7 +87,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
* Set the accelerometer sensitivity.
|
||||
*
|
||||
* This sets the sensitivity of the accelerometer used for calculating the acceleration.
|
||||
* The sensitivity varys by accelerometer model. There are constants defined for various models.
|
||||
* The sensitivity varies by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param sensitivity The sensitivity of accelerometer in Volts per G.
|
||||
*/
|
||||
@@ -98,7 +98,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
/**
|
||||
* Set the voltage that corresponds to 0 G.
|
||||
*
|
||||
* The zero G voltage varys by accelerometer model. There are constants defined for various models.
|
||||
* The zero G voltage varies by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param zero The zero G voltage.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user