14 #include <yarp/os/Time.h>
15 #include <ace/config.h>
17 #include <ace/Log_Msg.h>
18 #include <ace/Sched_Params.h>
28 #define NTCAN_HANDLE HANDLE
32 #include <yarp/dev/ControlBoardInterfacesImpl.h>
39 typedef int (*
PV) (
const char *fmt, ...);
41 using namespace yarp::os;
49 EsdMessageSnifferParameters::EsdMessageSnifferParameters(
int nj)
52 _axisMap = allocAndCheck<int>(nj);
53 _angleToEncoder = allocAndCheck<double>(nj);
54 _zeros = allocAndCheck<double>(nj);
58 _polling_interval = 10;
69 EsdMessageSnifferParameters::~EsdMessageSnifferParameters()
71 checkAndDestroy<double>(_zeros);
72 checkAndDestroy<double>(_angleToEncoder);
73 checkAndDestroy<int>(_axisMap);
74 checkAndDestroy<unsigned char>(_destinations);
97 short _position_error;
127 bool uninitialize (
void);
129 bool error (
const CMSG& m);
130 bool startPacket (
void);
131 bool addMessage (
int msg_id,
int joint);
132 bool writePacket (
void);
133 bool printMessage (
const CMSG& m);
134 bool dumpBuffers (
void);
139 enum { ESD_TIMEOUT = 20, ESD_POLLING_INTERVAL = 10 };
171 char _printBuffer[16384];
176 _handle = ACE_INVALID_HANDLE;
177 _timeout = ESD_TIMEOUT;
178 _polling_interval = ESD_POLLING_INTERVAL;
182 ACE_OS::memset(_readBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
183 ACE_OS::memset(_writeBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
184 ACE_OS::memset(_replyBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
185 ACE_OS::memset(_destinations, 0,
sizeof(
unsigned char) *
ESD_MAX_CARDS);
194 _bcastRecvBuffer = NULL;
196 _error_status =
false;
206 if (_handle != ACE_INVALID_HANDLE)
210 _handle = ACE_INVALID_HANDLE;
217 _error_status =
false;
232 ACE_ASSERT (_bcastRecvBuffer != 0);
235 memset (_readBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
236 memset (_writeBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
237 memset (_replyBuffer, 0,
sizeof(CMSG)*
BUF_SIZE);
240 int res = canOpen (_networkN, 0, _txQueueSize, _rxQueueSize, _txTimeout, _rxTimeout, &_handle);
241 if (res != NTCAN_SUCCESS)
244 res = canSetBaudrate (_handle, _speed);
245 if (res != NTCAN_SUCCESS)
253 for (i = 0; i < 0xff; i++)
254 canIdAdd (_handle, i);
256 for (i = 0x100; i < 0x1ff; i++)
257 canIdAdd (_handle, i);
265 if (_bcastRecvBuffer != NULL)
267 delete[] _bcastRecvBuffer;
268 _bcastRecvBuffer = NULL;
271 if (_handle != ACE_INVALID_HANDLE)
273 int res = canClose (_handle);
274 if (res != NTCAN_SUCCESS)
276 _handle = ACE_INVALID_HANDLE;
291 int res = canTake (_handle, _readBuffer, &messages);
292 if (res != NTCAN_SUCCESS)
295 _readMessages = messages;
308 memset (&
x, 0,
sizeof(CMSG));
310 x.id = _my_address << 4;
311 x.id = _destinations[joint/2] & 0x0f;
315 if ((joint % 2) == 1)
318 _writeBuffer[_writeMessages] =
x;
326 if (_writeMessages < 1)
330 long len=_writeMessages;
332 int32_t len =_writeMessages;
335 int res = canSend (_handle, _writeBuffer, &len);
336 if (res != NTCAN_SUCCESS || len != _writeMessages)
347 int ret = ACE_OS::sprintf (_printBuffer,
"class: %2d s: %2x d: %2x c: %1d msg: %3d (%x) ",
351 ((m.data[0] & 0x80)==0)?0:1,
357 ret += ACE_OS::sprintf (_printBuffer+ret,
"x: ");
361 for (j = 1; j < m.len; j++)
363 ret += ACE_OS::sprintf (_printBuffer+ret,
"%x ", m.data[j]);
365 ret += ACE_OS::sprintf(_printBuffer+ret,
"st: %x\n", m.msg_lost);
368 (
"%s", _printBuffer);
376 if (!_p)
return false;
381 (*_p) (
"Sniffer: write buffer\n");
382 for (j = 0; j < _writeMessages; j++)
383 printMessage (_writeBuffer[j]);
385 (*_p) (
"Sniffer: reply buffer\n");
386 for (j = 0; j < _writeMessages; j++)
387 printMessage (_replyBuffer[j]);
389 (*_p) (
"Sniffer: read buffer\n");
390 for (j = 0; j < _readMessages; j++)
391 printMessage (_readBuffer[j]);
392 (*_p) (
"Sniffer: -------------\n");
399 if (m.len & NTCAN_NO_DATA)
return true;
400 if (m.msg_lost != 0) { _msg_lost = m.msg_lost;
return true; }
411 EsdMessageSniffer::EsdMessageSniffer(
void) :
431 p.fromString(config.toString());
433 if (!
p.check(
"GENERAL")) {
434 ACE_OS::fprintf(stderr,
"Cannot understand configuration parameters\n");
439 int nj =
p.findGroup(
"GENERAL").find(
"Joints").asInt32();
444 Bottle &xtmp =
p.findGroup(
"CAN").findGroup(
"CanDeviceNum");
447 xtmp =
p.findGroup(
"CAN").findGroup(
"CanMyAddress");
450 xtmp =
p.findGroup(
"CAN").findGroup(
"CanPollingInterval");
453 xtmp =
p.findGroup(
"CAN").findGroup(
"CanTimeout");
454 params.
_timeout=xtmp.get(1).asInt32();
456 xtmp =
p.findGroup(
"CAN").findGroup(
"CanAddresses");
457 for (i = 1; i < xtmp.size(); i++) params.
_destinations[i-1] = (
unsigned char)(xtmp.get(i).asInt32());
460 xtmp =
p.findGroup(
"GENERAL").findGroup(
"AxisMap");
461 ACE_ASSERT (xtmp.size() == nj+1);
462 for (i = 1; i < xtmp.size(); i++) params.
_axisMap[i-1] = xtmp.get(i).asInt32();
463 xtmp =
p.findGroup(
"GENERAL").findGroup(
"Encoder");
464 ACE_ASSERT (xtmp.size() == nj+1);
465 for (i = 1; i < xtmp.size(); i++) params.
_angleToEncoder[i-1] = xtmp.get(i).asFloat64();
466 xtmp =
p.findGroup(
"GENERAL").findGroup(
"Zeros");
467 ACE_ASSERT (xtmp.size() == nj+1);
468 for (i = 1; i < xtmp.size(); i++) params.
_zeros[i-1] = xtmp.get(i).asFloat64();
470 if (
p.findGroup(
"GENERAL").find(
"Verbose").asInt32() == 1)
471 params.
_p = ACE_OS::printf;
480 std::lock_guard<std::mutex> lck(
_mutex);
488 ImplementPidControl<EsdMessageSniffer, IPidControl>::
490 ImplementAmplifierControl<EsdMessageSniffer, IAmplifierControl>::
492 ImplementEncoders<EsdMessageSniffer, IEncoders>::
497 std::unique_lock<std::mutex> lck(
mtx_done);
513 ImplementPidControl<EsdMessageSniffer, IPidControl>::uninitialize();
514 ImplementAmplifierControl<EsdMessageSniffer, IAmplifierControl>::uninitialize();
515 ImplementEncoders<EsdMessageSniffer, IEncoders>::uninitialize();
527 bool messagePending =
false;
529 int remainingMsgs = 0;
530 bool noreply =
false;
543 while (!isStopping() || messagePending)
545 before = Time::now();
548 if (r.
read () !=
true)
550 (*r.
_p) (
"Sniffer: read failed\n");
558 if (m.len & NTCAN_NO_DATA)
561 (*r.
_p) (
"Sniffer: error in message %x len: %d type: %x: %x\n",
562 m.id, m.len, m.data[0], m.msg_lost);
566 if ((m.id & 0x700) == 0x100)
573 const int addr = ((m.id & 0x0f0) >> 4);
584 switch (m.id & 0x00f)
597 case CAN_BCAST_PID_VAL:
609 case CAN_BCAST_STATUS:
622 case CAN_BCAST_CURRENT:
652 if (m.len & NTCAN_NO_DATA)
655 (*r.
_p) (
"Sniffer: error in message %x len: %d type: %x: %x\n",
656 m.id, m.len, m.data[0], m.msg_lost);
661 if (((m.id &0x700) == 0) &&
662 ((m.data[0] & 0x7f) < NUM_OF_MESSAGES))
667 if (((m.id & 0x700) == 0) &&
674 if (((r.
_writeBuffer[j].id & 0x0f) == ((m.id & 0xf0) >> 4)) &&
681 (*r.
_p) (
"Sniffer: message %x was already replied\n", m.id);
689 if (remainingMsgs < 1)
691 messagePending =
false;
706 messagePending =
false;
718 (*r.
_p) (
"Sniffer: timeout - still %d messages unacknowledged\n", remainingMsgs);
722 messagePending =
false;
745 (*r.
_p) (
"Sniffer: write message of %d elments failed\n", r.
_writeMessages);
750 messagePending =
true;
783 if (r.
_p) (*r.
_p)(
"Sniffer: thread can't poll fast enough (time: %f)\n", now-before);
794 std::lock_guard<std::mutex> lck(
_mutex);
796 _p = (int (*) (
const char *fmt, ...))
cmd;
837 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
839 std::lock_guard<std::mutex> lck(
_mutex);
848 std::lock_guard<std::mutex> lck(
_mutex);
859 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
861 lock_guard<mutex> lck(
_mutex);
870 std::lock_guard<std::mutex> lck(
_mutex);
881 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
883 std::lock_guard<std::mutex> lck(
_mutex);
893 std::lock_guard<std::mutex> lck(
_mutex);
906 std::lock_guard<std::mutex> lck(
_mutex);
917 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
919 std::lock_guard<std::mutex> lck(
_mutex);
930 std::lock_guard<std::mutex> lck(
_mutex);
967 std::unique_lock<std::mutex> lck(
mtx_done);
995 std::unique_lock<std::mutex> lck(
mtx_done);
1037 std::unique_lock<std::mutex> lck(
mtx_done);
1042 ACE_OS::memset (
out, 0,
sizeof(
double) * r.
getJoints());
1047 for (i = 0, j = 0; i < r.
getJoints(); i++)
1055 out[i] = *((
short *)(m.data+1));
1087 std::unique_lock<std::mutex> lck(
mtx_done);
1117 std::unique_lock<std::mutex> lck(
mtx_done);
1130 ACE_ASSERT ((axis % 2) == 0);
1150 std::unique_lock<std::mutex> lck(
mtx_done);
1181 std::unique_lock<std::mutex> lck(
mtx_done);
1223 std::unique_lock<std::mutex> lck(
mtx_done);
1228 ACE_OS::memset (
out, 0,
sizeof(
double) * r.
getJoints());
1233 for (i = 0, j = 0; i < r.
getJoints(); i++)
1241 out[i] = *((
int *)(m.data+1));
const int ESD_MAX_CARDS
Max number of addressable cards in this implementation.
EsdResources & RES(void *res)
int(* PV)(const char *fmt,...)
class for interfacing with the ESD can device driver and reading messages.
CMSG _readBuffer[BUF_SIZE]
bool _error_status
number of joints (ncards * 2).
unsigned char _my_address
local storage for bcast messages.
CMSG _replyBuffer[BUF_SIZE]
write buffer.
int _timeout
the actual ddriver handle.
BCastBufferElement * _bcastRecvBuffer
reply buffer.
bool getErrorStatus(void) const
unsigned char _destinations[ESD_MAX_CARDS]
int _polling_interval
this is my thread timeout.
int _speed
thread polling interval.
PV _p
error status of the last packet (true = error).
CMSG _writeBuffer[BUF_SIZE]
size of the write packet.
int getJoints(void) const
long int _txQueueSize
network number.
int _njoints
list of connected cards (and their addresses).
int _networkN
speed of the bus.
bool error(const CMSG &m)
bool addMessage(int msg_id, int joint)
bool initialize(const EsdMessageSnifferParameters &parms)
int _msg_lost
size of the last read buffer.
int _writeMessages
read buffer.
bool printMessage(const CMSG &m)
The EsdMessageSniffer device driver.
virtual bool close(void)
Close the device driver.
bool getBCastPositionErrors(double *cmd)
bool getBCastPositions(double *p)
bool setDebugPrintFunction(void *cmd)
int(* _p)(const char *fmt,...)
pointer to the function printing the device debug information.
bool _readWord16(int msg, int axis, short &value)
virtual bool open(EsdMessageSnifferParameters ¶ms)
Open the device driver.
std::condition_variable cv_done
bool getBCastCurrents(double *p)
virtual ~EsdMessageSniffer()
Destructor.
bool _readWord16Array(int msg, double *out)
reads an array.
bool _writeDWord(int msg, int axis, int value)
write a DWord
bool getBCastFaults(int *p)
bool _writeWord16Ex(int msg, int axis, short s1, short s2)
two shorts in a single Can message (both must belong to the same control card).
virtual bool getAxes(int *axis)
Get the number of controlled axes.
bool getBCastPIDOutput(int i, double *value)
bool getBCastCurrent(int i, double *value)
bool _readDWordArray(int msg, double *out)
reads an array of double words.
bool getBCastPosition(int i, double *value)
reads an array of double from the broadcast message position buffer.
bool _writeNone(int msg, int axis)
helper functions.
bool ENABLED(int axis)
helper function to check whether the enabled flag is on or off.
bool getBCastPIDOutputs(double *p)
bool _writeWord16(int msg, int axis, short s)
helper functions
bool _readDWord(int msg, int axis, int &value)
sends a message and gets a dword back.
bool setBCastMessages(int i, int value)
sets the broadcast policy for a given board (don't need to be called twice).
bool getBCastPositionError(int i, double *value)
#define CAN_BCAST_POSITION
bool read(yarp::os::Searchable &cfgtotal, pc104Data &pc104data)
A container class to pass parameters to the open() method of the device driver.
int _njoints
network number
unsigned char _my_address
number of joints (cards * 2)
int _timeout
thread polling interval [ms]
int(* _p)(const char *fmt,...)
number of cycles before timing out
int _polling_interval
my address
unsigned char * _destinations
printf-like function for spying messages
int * _axisMap
destination addresses
double * _zeros
angle to encoder conversion factors
double * _angleToEncoder
axis remapping lookup-table