canopen.h
Go to the documentation of this file.
00001 #ifndef CANOPEN_H
00002 #define CANOPEN_H
00003 
00004 #include <iostream>
00005 #include <map>
00006 #include <vector>
00007 #include <string>
00008 #include <chrono>
00009 #include <unordered_map>
00010 #include <functional>
00011 #include <cstdlib>
00012 #include <thread>
00013 #include <math.h>
00014 #include <libpcan.h>
00015 #include <utility>
00016 #include <fcntl.h>    // for O_RDWR
00017 #include <stdint.h>
00018 #include <inttypes.h>
00019 
00020 namespace canopen {
00021 
00022   extern std::chrono::milliseconds syncInterval; 
00023   extern bool atFirstInit;
00024   // ^ true only at first call of the init() function, to prevent 
00025   // from launching the listener thread twice
00026   extern HANDLE h; // PCAN device handle
00027 
00028   // ---------------- incoming message handlers: ----------------
00029 
00030   struct SDOkey {
00031     uint16_t index;
00032     uint8_t subindex;
00033     inline SDOkey(TPCANRdMsg m) : index((m.Msg.DATA[2] << 8) + m.Msg.DATA[1]),
00034                                   subindex(m.Msg.DATA[3]) {}
00035     inline SDOkey(uint16_t i, uint8_t s) : index(i), subindex(s) {};
00036   };
00037   inline bool operator<(const SDOkey &a, const SDOkey&b) {
00038     return a.index < b.index || (a.index == b.index && a.subindex < b.subindex); }
00039 
00040   extern std::map<SDOkey, std::function<void (uint8_t CANid, BYTE data[8])> >
00041     incomingDataHandlers;
00042   extern std::map<uint16_t, std::function<void (const TPCANRdMsg m)> >
00043     incomingPDOHandlers;
00044 
00045   void incomingNodeguardHandler(uint8_t CANid, BYTE data[8]);
00046   void statusword_incoming(uint8_t CANid, BYTE data[8]);
00047   void modes_of_operation_display_incoming(uint8_t CANid, BYTE data[8]);
00048 
00049   // ----------------- CAN device representations: --------------
00050 
00051   class Device {
00052   public:
00053     Device() {};
00054   Device(uint8_t CANid) : CANid_(CANid), desiredVel_(0), actualVel_(0),
00055       actualPos_(0), desiredPos_(0), initialized(false), motorState_("not initialized") {};
00056   Device(uint8_t CANid, std::string name, std::string group, std::string bus) : 
00057     CANid_(CANid), name_(name), group_(group), deviceFile_(bus), 
00058       desiredVel_(0), actualVel_(0),
00059       actualPos_(0), desiredPos_(0), initialized(false) {};
00060 
00061     std::string motorState_;
00062     
00063 
00064     inline void setVel(double vel) { desiredVel_ = vel; }
00065     inline void updateDesiredPos() { 
00066       desiredPos_ += desiredVel_ * (syncInterval.count() / 1000.0); }
00067 
00068     uint8_t CANid_;
00069     // uint16_t motorState_;
00070     std::string deviceFile_;
00071     std::string group_;
00072     std::string name_;
00073     bool initialized;
00074     bool voltage_enabled_;
00075     bool driveReferenced_;
00076     double actualPos_; // unit = rad
00077     double desiredPos_; // unit = rad
00078     double actualVel_; // unit = rad/sec
00079     double desiredVel_; // unit = rad/sec
00080     std::chrono::milliseconds timeStamp_msec_; 
00081     std::chrono::microseconds timeStamp_usec_; 
00082   };
00083 
00084   extern std::map<uint8_t, Device> devices; // CANid->Device object
00085 
00086   class DeviceGroup {
00087   public:
00088     DeviceGroup() {};
00089   DeviceGroup(std::vector<uint8_t> CANids) : CANids_(CANids) {};
00090   DeviceGroup(std::vector<uint8_t> CANids, std::vector<std::string> names) : 
00091     CANids_(CANids), names_(names) {};
00092 
00093     inline std::vector<double> getActualPos() {
00094       std::vector<double> actualPos;
00095       for (uint8_t CANid : CANids_)
00096         actualPos.push_back(devices[CANid].actualPos_);
00097       return actualPos;
00098     }
00099     inline std::vector<double> getDesiredPos() {
00100       std::vector<double> desiredPos;
00101       for (auto CANid : CANids_)
00102         desiredPos.push_back(devices[CANid].desiredPos_);
00103       return desiredPos;
00104     }
00105     inline std::vector<double> getActualVel() {
00106       std::vector<double> actualVel;
00107       for (auto CANid : CANids_)
00108         actualVel.push_back(devices[CANid].actualVel_);
00109       return actualVel;
00110     }
00111     inline std::vector<double> getDesiredVel() {
00112       std::vector<double> desiredVel;
00113       for (auto CANid : CANids_)
00114         desiredVel.push_back(devices[CANid].desiredVel_);
00115       return desiredVel;
00116     }
00117     inline void setVel(std::vector<double> velocities) {
00118       for (int i=0; i<velocities.size(); i++) {
00119         devices[CANids_[i]].desiredVel_ = velocities[i];
00120         std::cout << "setVel CANID " << (int) CANids_[i] 
00121                   << " name: " << names_[i] << " vel: " << velocities[i] << std::endl;
00122       }
00123     }
00124 
00125     std::vector<uint8_t> CANids_;
00126     std::vector<std::string> names_;
00127   };
00128 
00129   
00130   extern std::map<std::string, DeviceGroup> deviceGroups;
00131   // ^ DeviceGroup name (e.g. "tray", "arm1", etc.) -> DeviceGroup object
00132 
00133   // ----------------- Constants: --------------
00134   
00135   const uint8_t NMT_stop = 0x02;
00136   const uint8_t NMT_start = 0x01;
00137   const uint8_t NMT_reset = 0x81;
00138 
00139   const SDOkey statusword(0x6041, 0x0);
00140   const SDOkey controlword(0x6040, 0x0);
00141   const SDOkey sync_timeout_factor(0x200e, 0x0);
00142   const SDOkey ip_time_units(0x60C2, 0x1);
00143   const SDOkey ip_time_index(0x60C2, 0x2);
00144   const int8_t ip_time_index_milliseconds = 0xFD;
00145   const int8_t ip_time_index_hundredmicroseconds = 0xFC;
00146   const uint8_t sync_timeout_factor_disable_timeout = 0;
00147 
00148   const SDOkey modes_of_operation(0x6060, 0x0);
00149   const SDOkey modes_of_operation_display(0x6061, 0x0);
00150   const uint8_t modes_of_operation_homing_mode = 0x6;
00151   const uint8_t modes_of_operation_profile_position_mode = 0x1;
00152   const uint8_t modes_of_operation_velocity_mode = 0x2;
00153   const uint8_t modes_of_operation_profile_velocity_mode = 0x3;
00154   const uint8_t modes_of_operation_torque_profile_mode = 0x4;
00155   const uint8_t modes_of_operation_interpolated_position_mode = 0x7;
00156 
00157   const uint16_t controlword_shutdown = 6;
00158   const uint16_t controlword_switch_on = 7;
00159   const uint16_t controlword_start_homing = 16;
00160   const uint16_t controlword_enable_operation = 15;
00161   const uint16_t controlword_enable_ip_mode = 16;
00162   const uint16_t controlword_fault_reset_0 = 0x00;
00163   const uint16_t controlword_fault_reset_1 = 0x80;
00164 
00165   // ----------------- CAN communication functions: --------------
00166 
00167   bool openConnection(std::string devName);
00168   void init(std::string deviceFile, std::chrono::milliseconds syncInterval);
00169   void initListenerThread(std::function<void ()> const& listener);
00170   void defaultListener();
00171   void initDeviceManagerThread(std::function<void ()> const& deviceManager);
00172   void deviceManager();
00173   void setMotorState(uint16_t CANid, std::string targetState);
00174 
00175   void sendSDO(uint8_t CANid, SDOkey sdo);
00176   void sendSDO(uint8_t CANid, SDOkey sdo, uint32_t value);
00177   void sendSDO(uint8_t CANid, SDOkey sdo, int32_t value);
00178   void sendSDO(uint8_t CANid, SDOkey sdo, uint16_t value);
00179   void sendSDO(uint8_t CANid, SDOkey sdo, uint8_t value);
00180 
00181   extern std::function< void (uint16_t CANid, double positionValue) > sendPos;
00182 
00183   // ----------------- manufacturer-specific PDOs: --------------
00184 
00185   void schunkDefaultPDO_incoming(uint8_t CANid, const TPCANRdMsg m);
00186   void schunkDefaultPDOOutgoing(uint16_t CANid, double positionValue);
00187 
00188   // ----------------- prep-prepared CAN messages: --------------
00189 
00190   extern TPCANMsg syncMsg;
00191   extern TPCANMsg NMTmsg;
00192   extern TPCANMsg nodeguardMsg;
00193   inline void sendSync() {
00194     CAN_Write(h, &syncMsg);
00195   }
00196   inline void sendNMT(uint8_t command, uint8_t CANid) {
00197     NMTmsg.DATA[1] = command;
00198     NMTmsg.DATA[0] = CANid;
00199     CAN_Write(h, &NMTmsg);
00200   }
00201   inline void sendNodeguard(uint8_t CANid) {
00202     nodeguardMsg.ID = 0x700 + CANid;
00203     CAN_Write(h, &nodeguardMsg);
00204   }
00205 
00206   // ----------------- type conversions: --------------
00207 
00208   inline int32_t rad2mdeg(double phi) {
00209     return static_cast<int32_t>( round( phi/(2*M_PI)*360000.0 ) ); }
00210   inline double mdeg2rad(int32_t alpha) {
00211     return static_cast<double>( static_cast<double>(alpha)/360000.0*2*M_PI ); }
00212 
00213 }
00214 
00215 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


ipa_canopen_core
Author(s): Tobias Sing
autogenerated on Fri Mar 1 2013 18:36:29