Libbarrett  1.2.4
include/barrett/products/detail/puck-inl.h
00001 
00026 /*
00027  * @file puck-inl.h
00028  * @date 10/05/2010
00029  * @author Dan Cody
00030  * 
00031  */
00032 
00033 #include <boost/thread/locks.hpp>
00034 
00035 #include <barrett/os.h>
00036 #include <barrett/thread/abstract/mutex.h>
00037 #include <barrett/products/puck_group.h>
00038 
00039 
00040 namespace barrett {
00041 
00042 
00043 inline int Puck::getProperty(enum Property prop, bool realtime) const {
00044         return getProperty(bus, id, getPropertyId(prop), realtime);
00045 }
00046 template<typename Parser>
00047 inline void Puck::getProperty(enum Property prop, typename Parser::result_type* result, bool realtime) const {
00048         getProperty<Parser> (bus, id, getPropertyId(prop), result, realtime);
00049 }
00050 
00051 
00052 inline int Puck::getProperty(const bus::CommunicationsBus& bus, int id, int propId, bool realtime)
00053 {
00054         int result;
00055         getProperty<StandardParser>(bus, id, propId, &result, realtime);
00056         return result;
00057 }
00058 // TODO(dc): throw exception if getProperty is called with a group ID?
00059 template<typename Parser>
00060 void Puck::getProperty(const bus::CommunicationsBus& bus, int id, int propId, typename Parser::result_type* result, bool realtime)
00061 {
00062         int ret = getPropertyHelper<Parser>(bus, id, propId, result, true, realtime, 0.0);
00063         if (ret != 0) {
00064                 (logMessage("Puck::%s(): Failed to receive reply. "
00065                                 "Puck::receiveGetPropertyReply() returned error %d.")
00066                                 % __func__ % ret).template raise<std::runtime_error>();
00067         }
00068 }
00069 
00070 inline int Puck::tryGetProperty(const bus::CommunicationsBus& bus, int id, int propId, int* result, double timeout_s)
00071 {
00072         return tryGetProperty<StandardParser>(bus, id, propId, result, timeout_s);
00073 }
00074 template<typename Parser>
00075 int Puck::tryGetProperty(const bus::CommunicationsBus& bus, int id, int propId, typename Parser::result_type* result, double timeout_s)
00076 {
00077         int ret = getPropertyHelper<Parser>(bus, id, propId, result, false, false, timeout_s);
00078         if (ret != 0  &&  ret != 1) {  // some error other than "would block" occurred
00079                 (logMessage("Puck::%s(): Receive error. "
00080                                 "Puck::receiveGetPropertyReply() returned error %d.")
00081                                 % __func__ % ret).template raise<std::runtime_error>();
00082         }
00083         return ret;
00084 }
00085 
00086 template<typename Parser>
00087 int Puck::getPropertyHelper(const bus::CommunicationsBus& bus, int id, int propId, typename Parser::result_type* result, bool blocking, bool realtime, double timeout_s)
00088 {
00089         boost::unique_lock<thread::Mutex> ul(bus.getMutex(), boost::defer_lock);
00090         if (realtime) {
00091                 ul.lock();
00092         }
00093 
00094         int ret = sendGetPropertyRequest(bus, id, propId);
00095         if (ret != 0) {
00096                 (logMessage("Puck::%s(): Failed to send request. "
00097                                 "Puck::sendGetPropertyRequest() returned error %d.")
00098                                 % __func__ % ret).template raise<std::runtime_error>();
00099         }
00100 
00101         if (timeout_s != 0.0) {
00102                 btsleepRT(timeout_s);
00103         }
00104 
00105         return receiveGetPropertyReply<Parser>(bus, id, propId, result, blocking, realtime);
00106 }
00107 
00108 inline void Puck::setProperty(const bus::CommunicationsBus& bus, int id, int propId, int value, bool blocking)
00109 {
00110         static const size_t MSG_LEN = 6;
00111 
00112         unsigned char data[MSG_LEN];
00113         data[0] = (propId & PROPERTY_MASK) | SET_MASK;
00114         data[1] = 0;
00115         data[2] = (value & 0x000000ff);
00116         data[3] = (value & 0x0000ff00) >>  8;
00117         data[4] = (value & 0x00ff0000) >> 16;
00118         data[5] = (value & 0xff000000) >> 24;
00119 
00120         int ret = bus.send(nodeId2BusId(id), data, MSG_LEN);
00121         if (ret != 0) {
00122                 (logMessage("Puck::%s(): Failed to send SET message. "
00123                                 "bus::CommunicationsBus::send() returned error %d.")
00124                                 % __func__ % ret).raise<std::runtime_error>();
00125         }
00126 
00127         if (blocking) {
00128                 // Make sure the command has completed so we don't overflow the Puck's receive buffer.
00129                 getProperty(bus, id, getPropertyId(STAT, PT_Unknown, 0));
00130         }
00131 }
00132 
00133 inline int Puck::sendGetPropertyRequest(const bus::CommunicationsBus& bus, int id, int propId)
00134 {
00135         static const size_t MSG_LEN = 1;
00136 
00137         unsigned char data[MSG_LEN];
00138         data[0] = propId & PROPERTY_MASK;
00139 
00140         return bus.send(nodeId2BusId(id), data, MSG_LEN);
00141 }
00142 
00143 inline int Puck::receiveGetPropertyReply(const bus::CommunicationsBus& bus, int id, int propId, int* result, bool blocking, bool realtime)
00144 {
00145         return receiveGetPropertyReply<StandardParser>(bus, id, propId, result, blocking, realtime);
00146 }
00147 template<typename Parser>
00148 int Puck::receiveGetPropertyReply(const bus::CommunicationsBus& bus, int id, int propId, typename Parser::result_type* result, bool blocking, bool realtime)
00149 {
00150         unsigned char data[bus::CommunicationsBus::MAX_MESSAGE_LEN];
00151         size_t len;
00152 
00153         int ret = bus.receive(Parser::busId(id, propId), data, len, blocking, realtime);
00154         if (ret != 0) {
00155                 return ret;
00156         }
00157 
00158         // Make return code negative to avoid colliding with bus.receive() return codes.
00159         return -Parser::parse(id, propId, result, data, len);
00160 }
00161 
00162 inline int Puck::getPropertyId(enum Property prop, enum PuckType pt, int fwVers)
00163                 throw(std::runtime_error)
00164 {
00165         int propId = getPropertyIdNoThrow(prop, pt, fwVers);
00166         if (propId == -1) {
00167                 (logMessage("Puck::%s(): Invalid property. "
00168                                 "Pucks with type %s and firmware version %d do not respond to property %s.")
00169                                 % __func__ % getPuckTypeStr(pt) % fwVers % getPropertyStr(prop)).raise<std::runtime_error>();
00170         }
00171         return propId;
00172 }
00173 
00174 
00175 inline int Puck::StandardParser::busId(int id, int propId)
00176 {
00177         return Puck::encodeBusId(id, PuckGroup::FGRP_OTHER);
00178 }
00179 
00180 
00181 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Defines