Merge "Java CANJaguar changes"

This commit is contained in:
Brad Miller (WPI)
2014-06-25 07:01:35 -07:00
committed by Gerrit Code Review
11 changed files with 1707 additions and 1513 deletions

View File

@@ -135,6 +135,8 @@ void CANJaguar::InitCANJaguar()
requestMessage(CAN_IS_FRAME_REMOTE | CAN_MSGID_API_FIRMVER);
requestMessage(LM_API_HWVER);
Wait(0.003);
if(getMessage(CAN_MSGID_API_FIRMVER, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
m_firmwareVersion = unpackint32_t(dataBuffer);
else

View File

@@ -109,6 +109,7 @@ TEST_F(CANJaguarTest, EncoderPositionPID) {
TEST_F(CANJaguarTest, FakePotentiometerPosition) {
m_jaguar->SetPositionReference(CANJaguar::kPosRef_Potentiometer);
m_jaguar->ConfigPotentiometerTurns(1);
m_jaguar->EnableControl();
m_fakePotentiometer->SetVoltage(0.0f);
Wait(kPotentiometerSettlingTime);

View File

@@ -13,7 +13,6 @@ import java.nio.ByteOrder;
import edu.wpi.first.wpilibj.hal.PDPJNI;
import edu.wpi.first.wpilibj.hal.HALUtil;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.can.CANTimeoutException;
/**
* Class for getting voltage, current, and temperature from the CAN PDP
@@ -22,54 +21,42 @@ import edu.wpi.first.wpilibj.can.CANTimeoutException;
public class PowerDistributionPanel extends SensorBase {
public PowerDistributionPanel() {
}
/**
* @return The voltage of the PDP
*/
public double getVoltage() throws CANTimeoutException {
public double getVoltage() {
ByteBuffer status = ByteBuffer.allocateDirect(4);
status.order(ByteOrder.LITTLE_ENDIAN);
double voltage = PDPJNI.getPDPVoltage(status.asIntBuffer());
if(status.asIntBuffer().get(0) != 0) {
throw new CANTimeoutException();
}
return voltage;
}
/**
* @return The temperature of the PDP in degrees Celsius
*/
public double getTemperature() throws CANTimeoutException {
public double getTemperature() {
ByteBuffer status = ByteBuffer.allocateDirect(4);
status.order(ByteOrder.LITTLE_ENDIAN);
double temperature = PDPJNI.getPDPTemperature(status.asIntBuffer());
if(status.asIntBuffer().get(0) != 0) {
throw new CANTimeoutException();
}
return temperature;
}
/**
* @return The current of one of the PDP channels (channels 1-16) in Amperes
*/
public double getCurrent(int channel) throws CANTimeoutException {
public double getCurrent(int channel) {
ByteBuffer status = ByteBuffer.allocateDirect(4);
status.order(ByteOrder.LITTLE_ENDIAN);
double current = PDPJNI.getPDPChannelCurrent((byte)channel, status.asIntBuffer());
checkPDPChannel(channel);
if(status.asIntBuffer().get(0) != 0) {
throw new CANTimeoutException();
}
return current;
}
}

View File

@@ -7,7 +7,6 @@
package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.can.CANNotInitializedException;
import edu.wpi.first.wpilibj.can.CANTimeoutException;
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tInstances;
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
import edu.wpi.first.wpilibj.communication.UsageReporting;
@@ -503,7 +502,7 @@ public class RobotDrive implements MotorSafety, IUtility {
CANJaguar.updateSyncGroup(syncGroup);
} catch (CANNotInitializedException e) {
m_isCANInitialized = false;
} catch (CANTimeoutException e) {}
}
}
if (m_safetyHelper != null) m_safetyHelper.feed();
@@ -555,7 +554,7 @@ public class RobotDrive implements MotorSafety, IUtility {
CANJaguar.updateSyncGroup(syncGroup);
} catch (CANNotInitializedException e) {
m_isCANInitialized = false;
} catch (CANTimeoutException e) {}
}
}
if (m_safetyHelper != null) m_safetyHelper.feed();
@@ -605,7 +604,7 @@ public class RobotDrive implements MotorSafety, IUtility {
CANJaguar.updateSyncGroup(syncGroup);
} catch (CANNotInitializedException e) {
m_isCANInitialized = false;
} catch (CANTimeoutException e) {}
}
}
if (m_safetyHelper != null) m_safetyHelper.feed();

View File

@@ -10,35 +10,30 @@ package edu.wpi.first.wpilibj.can;
import edu.wpi.first.wpilibj.communication.NIRioStatus;
import edu.wpi.first.wpilibj.util.UncleanStatusException;
/**
* Exception indicating that the Jaguar CAN Driver layer refused to send a
* restricted message ID to the CAN bus.
*/
public class CANExceptionFactory {
// FRC Error codes
static final int ERR_JaguarCANDriver_InvalidBuffer = -44086;
static final int ERR_JaguarCANDriver_TimedOut = -44087;
static final int ERR_JaguarCANDriver_NotAllowed = -44088;
static final int ERR_JaguarCANDriver_NotInitialized = -44089;
static final int ERR_CANSessionMux_InvalidBuffer = -44086;
static final int ERR_CANSessionMux_MessageNotFound = -44087;
static final int ERR_CANSessionMux_NotAllowed = -44088;
static final int ERR_CANSessionMux_NotInitialized = -44089;
public static void checkStatus(int status, int messageID) throws
CANInvalidBufferException, CANTimeoutException,
CANMessageNotAllowedException, CANNotInitializedException,
UncleanStatusException {
CANInvalidBufferException, CANMessageNotAllowedException,
CANNotInitializedException, UncleanStatusException {
switch (status) {
case NIRioStatus.kRioStatusSuccess:
// Everything is ok... don't throw.
return;
case ERR_JaguarCANDriver_InvalidBuffer:
case ERR_CANSessionMux_InvalidBuffer:
case NIRioStatus.kRIOStatusBufferInvalidSize:
throw new CANInvalidBufferException();
case ERR_JaguarCANDriver_TimedOut:
case ERR_CANSessionMux_MessageNotFound:
case NIRioStatus.kRIOStatusOperationTimedOut:
throw new CANTimeoutException();
case ERR_JaguarCANDriver_NotAllowed:
throw new CANMessageNotFoundException();
case ERR_CANSessionMux_NotAllowed:
case NIRioStatus.kRIOStatusFeatureNotSupported:
throw new CANMessageNotAllowedException("MessageID = " + Integer.toString(messageID));
case ERR_JaguarCANDriver_NotInitialized:
case ERR_CANSessionMux_NotInitialized:
case NIRioStatus.kRIOStatusResourceNotInitialized:
throw new CANNotInitializedException();
default:

View File

@@ -16,12 +16,6 @@ import java.nio.IntBuffer;
* For help, please visit <a href="http://nativelibs4java.googlecode.com/">NativeLibs4Java</a> , <a href="http://rococoa.dev.java.net/">Rococoa</a>, or <a href="http://jna.dev.java.net/">JNA</a>.
*/
public class CANJNI extends JNIWrapper{
//public static final String JNA_LIBRARY_NAME = LibraryExtractor.getLibraryPath("CAN", true, CANLibrary.class);
//public static final NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(CANLibrary.JNA_LIBRARY_NAME, MangledFunctionMapper.DEFAULT_OPTIONS);
//static {
// System.loadLibrary("JNIWrappers");
//Native.register(CANLibrary.class, CANLibrary.JNA_NATIVE_LIB);
//}
/** <i>native declaration : src\main\include\CAN\can_proto.h</i> */
public static final int LM_STATUS_LIMIT_REV = 0x02;
/** <i>native declaration : src\main\include\CAN\can_proto.h</i> */
@@ -452,6 +446,13 @@ public class CANJNI extends JNIWrapper{
public static final int LM_API_VCOMP_T_EN = ((0x00020000 | 0x02000000 | 0x00000800) | (5 << 6));
/** <i>native declaration : src\main\include\CAN\can_proto.h</i> */
public static final int LM_STATUS_LIMIT_STKY_SFWD = 0x40;
public static final int CAN_SEND_PERIOD_NO_REPEAT = 0;
public static final int CAN_SEND_PERIOD_STOP_REPEATING = -1;
/* Flags in the upper bits of the messageID */
public static final int CAN_IS_FRAME_REMOTE = 0x80000000;
public static final int CAN_IS_FRAME_11BIT = 0x40000000;
public static native void FRCNetworkCommunicationCANSessionMuxSendMessage(int messageID, ByteBuffer data, int periodMs, IntBuffer status);
public static native ByteBuffer FRCNetworkCommunicationCANSessionMuxReceiveMessage(IntBuffer messageID, int messageIDMask, ByteBuffer timeStamp, IntBuffer status);

View File

@@ -7,17 +7,13 @@
package edu.wpi.first.wpilibj.can;
import java.io.IOException;
/**
* Exception indicating that the CAN device did not respond
* within the timeout period specified.
* Exception indicating that a can message is not available from Network
* Communications. This usually just means we already have the most recent
* value cached locally.
*/
public class CANTimeoutException extends IOException {
public CANTimeoutException() {
public class CANMessageNotFoundException extends RuntimeException {
public CANMessageNotFoundException() {
super();
}
public CANTimeoutException(String message) {
super(message);
}
}

View File

@@ -11,7 +11,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import edu.wpi.first.wpilibj.can.CANTimeoutException;
import edu.wpi.first.wpilibj.can.CANMessageNotFoundException;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
@@ -19,14 +19,14 @@ public class PDPTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(PCMTest.class.getName());
/* The current returned when the motor is not being driven */
protected static final double kLowCurrent = 1.52;
protected static final double kCurrentTolerance = 0.1;
private static PowerDistributionPanel pdp;
private static Talon talon;
private static Victor victor;
private static Jaguar jaguar;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
pdp = new PowerDistributionPanel();
@@ -54,7 +54,7 @@ public class PDPTest extends AbstractComsSetup {
@After
public void tearDown() throws Exception {
}
/**
* Test if the current changes when the motor is driven using a talon
*/
@@ -62,27 +62,27 @@ public class PDPTest extends AbstractComsSetup {
public void CheckCurrentTalon() {
/* The Current should be kLowCurrent */
try {
assertEquals("The low current was not within the expected range.",
assertEquals("The low current was not within the expected range.",
kLowCurrent, pdp.getCurrent(TestBench.kTalonPDPChannel), kCurrentTolerance);
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Timer.delay(0.02);
/* Set the motor to full forward */
talon.set(1.0);
Timer.delay(0.02);
/* The current should now be greater than the low current */
try {
assertThat("The driven current is not greater than the resting current.",
assertThat("The driven current is not greater than the resting current.",
pdp.getCurrent(TestBench.kTalonPDPChannel), is(greaterThan(kLowCurrent)));
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Test if the current changes when the motor is driven using a victor
*/
@@ -90,27 +90,27 @@ public class PDPTest extends AbstractComsSetup {
public void CheckCurrentVictor() {
/* The Current should be kLowCurrent */
try {
assertEquals("The low current was not within the expected range.",
assertEquals("The low current was not within the expected range.",
kLowCurrent, pdp.getCurrent(TestBench.kVictorPDPChannel), kCurrentTolerance);
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Timer.delay(0.02);
/* Set the motor to full forward */
victor.set(1.0);
Timer.delay(0.02);
/* The current should now be greater than the low current */
try {
assertThat("The driven current is not greater than the resting current.",
assertThat("The driven current is not greater than the resting current.",
pdp.getCurrent(TestBench.kVictorPDPChannel), is(greaterThan(kLowCurrent)));
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Test if the current changes when the motor is driven using a jaguar
*/
@@ -118,23 +118,23 @@ public class PDPTest extends AbstractComsSetup {
public void CheckCurrentJaguar() {
/* The Current should be kLowCurrent */
try {
assertEquals("The low current was not within the expected range.",
assertEquals("The low current was not within the expected range.",
kLowCurrent, pdp.getCurrent(TestBench.kJaguarPDPChannel), kCurrentTolerance);
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Timer.delay(0.02);
/* Set the motor to full forward */
jaguar.set(1.0);
Timer.delay(0.02);
/* The current should now be greater than the low current */
try {
assertThat("The driven current is not greater than the resting current.",
assertThat("The driven current is not greater than the resting current.",
pdp.getCurrent(TestBench.kJaguarPDPChannel), is(greaterThan(kLowCurrent)));
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

View File

@@ -24,7 +24,7 @@ import edu.wpi.first.wpilibj.Servo;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.Talon;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.can.CANTimeoutException;
import edu.wpi.first.wpilibj.can.CANMessageNotFoundException;
import edu.wpi.first.wpilibj.fixtures.AnalogCrossConnectFixture;
import edu.wpi.first.wpilibj.fixtures.DIOCrossConnectFixture;
import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
@@ -47,7 +47,7 @@ public final class TestBench {
* completely stopped
*/
public static final double MOTOR_STOP_TIME = 0.20;
/* PowerDistributionPanel channels */
public static final int kJaguarPDPChannel = 7;
public static final int kVictorPDPChannel = 11;
@@ -164,7 +164,7 @@ public final class TestBench {
// have a free method
try {
canJag = new CANJaguar(1);
} catch (CANTimeoutException e) {
} catch (CANMessageNotFoundException e) {
e.printStackTrace();
}
}
@@ -230,14 +230,14 @@ public final class TestBench {
//NOTE: IF MORE DIOCROSSCONNECT PAIRS ARE ADDED ADD THEM HERE
return pairs;
}
public static AnalogCrossConnectFixture getAnalogCrossConnectFixture(){
AnalogCrossConnectFixture analogIO = new AnalogCrossConnectFixture() {
@Override
protected AnalogOutput giveAnalogOutput() {
return new AnalogOutput(0);
}
@Override
protected AnalogInput giveAnalogInput() {
return new AnalogInput(2);
@@ -245,20 +245,20 @@ public final class TestBench {
};
return analogIO;
}
public static RelayCrossConnectFxiture getRelayCrossConnectFixture(){
RelayCrossConnectFxiture relay = new RelayCrossConnectFxiture() {
@Override
protected Relay giveRelay() {
return new Relay(0);
}
@Override
protected DigitalInput giveInputTwo() {
return new DigitalInput(14);
}
@Override
protected DigitalInput giveInputOne() {
return new DigitalInput(15);

View File

@@ -8,7 +8,8 @@
#include "NetworkCommunication/CANSessionMux.h"
// set the logging level
TLogLevel canJNILogLevel = logDEBUG;
//TLogLevel canJNILogLevel = logDEBUG;
TLogLevel canJNILogLevel = logERROR;
#define CANJNI_LOG(level) \
if (level > canJNILogLevel) ; \
@@ -20,34 +21,44 @@ TLogLevel canJNILogLevel = logDEBUG;
* Signature: (ILjava/nio/ByteBuffer;ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_can_CANJNI_FRCNetworkCommunicationCANSessionMuxSendMessage
(JNIEnv * env, jclass, jint messageID, jobject data, jint periodMs, jobject status){
CANJNI_LOG(logDEBUG) << "Calling CANJNI JaguarCANDriverSendMessage";
CANJNI_LOG(logDEBUG) << "MessageID = " << std::hex << messageID;
jbyte * dataPtr = NULL;
jlong dataCapacity = 0;
(JNIEnv * env, jclass, jint messageID, jobject data, jint periodMs, jobject status)
{
CANJNI_LOG(logDEBUG) << "Calling CANJNI FRCNetworkCommunicationCANSessionMuxSendMessage";
if(data != 0){
dataPtr = (jbyte*)env->GetDirectBufferAddress(data);
dataCapacity = env->GetDirectBufferCapacity(data);
}
CANJNI_LOG(logDEBUG) << "MessageSize = " << dataCapacity;
uint8_t *dataBuffer = (uint8_t *)(data? env->GetDirectBufferAddress(data) : 0);
uint8_t dataSize = (uint8_t)(data? env->GetDirectBufferCapacity(data) : 0);
int32_t *statusPtr = (int32_t *)env->GetDirectBufferAddress(status);
if( logDEBUG <= canJNILogLevel )
{
std::ostringstream str;
str << std::setfill('0') << std::hex;
for( int dataIndex = 0; dataIndex < dataCapacity; dataIndex++)
{
str << std::setw(2) << static_cast<unsigned int>(dataPtr[dataIndex]) << " ";
}
Log().Get(logDEBUG) << "MSG: " << str.str();
}
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
//CANJNI_LOG(logDEBUG) << "Status Ptr = " << statusPtr;
FRC_NetworkCommunication_CANSessionMux_sendMessage((uint32_t) messageID, (const uint8_t*)dataPtr, periodMs, (uint8_t)dataCapacity, statusPtr);
CANJNI_LOG(logDEBUG) << "Status = " << *statusPtr;
CANJNI_LOG(logDEBUG) << "Message ID " << std::hex << messageID;
if(logDEBUG <= canJNILogLevel)
{
if(dataBuffer)
{
std::ostringstream str;
str << std::setfill('0') << std::hex;
for(int i = 0; i < dataSize; i++)
{
str << std::setw(2) << (int)dataBuffer[i] << ' ';
}
Log().Get(logDEBUG) << "Data: " << str.str();
}
else
{
CANJNI_LOG(logDEBUG) << "Data: null";
}
}
CANJNI_LOG(logDEBUG) << "Period: " << periodMs;
FRC_NetworkCommunication_CANSessionMux_sendMessage(messageID, dataBuffer, dataSize, periodMs, statusPtr);
CANJNI_LOG(logDEBUG) << "Status: " << *statusPtr;
}
static uint8_t buffer[8];
/*
* Class: edu_wpi_first_wpilibj_can_CANJNI
* Method: FRCNetworkCommunicationCANSessionMuxReceiveMessage
@@ -56,43 +67,32 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_can_CANJNI_FRCNetworkCommunica
JNIEXPORT jobject JNICALL Java_edu_wpi_first_wpilibj_can_CANJNI_FRCNetworkCommunicationCANSessionMuxReceiveMessage
(JNIEnv * env, jclass, jobject messageID, jint messageIDMask, jobject timeStamp, jobject status)
{
CANJNI_LOG(logDEBUG) << "Calling CANJNI JaguarCANDriverReceiveMessage";
jint * messageIDPtr = (jint*)env->GetDirectBufferAddress(messageID);
CANJNI_LOG(logDEBUG) << "MessageID In = " << std::hex << *messageIDPtr;
jbyte * timeStampPtr = (jbyte*) env->GetDirectBufferAddress(timeStamp);
CANJNI_LOG(logDEBUG) << "TimeStamp In = " << *timeStampPtr;
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
//CANJNI_LOG(logDEBUG) << "Status Ptr = " << statusPtr;
uint8_t dataSize = 8;
jbyte* dataPtr = new jbyte[8];
//CANJNI_LOG(logDEBUG) << "Original MessageSize = " << (jint)dataSize;
//CANJNI_LOG(logDEBUG) << "Original MessagePtr = " << (jint*)dataPtr;
FRC_NetworkCommunication_CANSessionMux_receiveMessage((uint32_t*)messageIDPtr, (uint32_t)messageIDMask,(uint8_t*)dataPtr, &dataSize, (uint32_t*)timeStampPtr, statusPtr);
CANJNI_LOG(logDEBUG) << "Calling CANJNI FRCNetworkCommunicationCANSessionMuxReceiveMessage";
//CANJNI_LOG(logDEBUG) << "MessageID Out = " << std::hex << *messageIDPtr;
CANJNI_LOG(logDEBUG) << "MessageSize = " << (jint)dataSize;
CANJNI_LOG(logDEBUG) << "MessagePtr = " << (jint*)dataPtr;
uint32_t *messageIDPtr = (uint32_t *)env->GetDirectBufferAddress(messageID);
uint32_t *timeStampPtr = (uint32_t *)env->GetDirectBufferAddress(timeStamp);
int32_t *statusPtr = (int32_t *)env->GetDirectBufferAddress(status);
if( logDEBUG <= canJNILogLevel )
{
std::ostringstream str;
str << std::setfill('0') << std::hex;
for( int dataIndex = 0; dataIndex < dataSize; dataIndex++)
{
str << std::setw(2) << static_cast<unsigned int>(dataPtr[dataIndex]) << " ";
}
Log().Get(logDEBUG) << "MSG: " << str.str();
}
uint8_t dataSize = 0;
CANJNI_LOG(logDEBUG) << "Status = " << *statusPtr;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(messageIDPtr, messageIDMask, buffer, &dataSize, timeStampPtr, statusPtr);
if( dataSize > 0 )
{
return env->NewDirectByteBuffer( dataPtr, dataSize);
}
else
{
return 0;
}
CANJNI_LOG(logDEBUG) << "Message ID " << std::hex << *messageIDPtr;
if(logDEBUG <= canJNILogLevel)
{
std::ostringstream str;
str << std::setfill('0') << std::hex;
for(int i = 0; i < dataSize; i++)
{
str << std::setw(2) << (int)buffer[i] << ' ';
}
Log().Get(logDEBUG) << "Data: " << str.str();
}
CANJNI_LOG(logDEBUG) << "Timestamp: " << *timeStampPtr;
CANJNI_LOG(logDEBUG) << "Status: " << *statusPtr;
return env->NewDirectByteBuffer(buffer, dataSize);
}