EthercatMasterWithThread.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2011
00004  * All rights reserved.
00005  *
00006  * Hochschule Bonn-Rhein-Sieg
00007  * University of Applied Sciences
00008  * Computer Science Department
00009  *
00010  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00011  *
00012  * Author:
00013  * Jan Paulus, Nico Hochgeschwender, Michael Reckhaus, Azamat Shakhimardanov
00014  * Supervised by:
00015  * Gerhard K. Kraetzschmar
00016  *
00017  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00018  *
00019  * This sofware is published under a dual-license: GNU Lesser General Public 
00020  * License LGPL 2.1 and BSD license. The dual-license implies that users of this
00021  * code may choose which terms they prefer.
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Hochschule Bonn-Rhein-Sieg nor the names of its
00034  *       contributors may be used to endorse or promote products derived from
00035  *       this software without specific prior written permission.
00036  *
00037  * This program is free software: you can redistribute it and/or modify
00038  * it under the terms of the GNU Lesser General Public License LGPL as
00039  * published by the Free Software Foundation, either version 2.1 of the
00040  * License, or (at your option) any later version or the BSD license.
00041  *
00042  * This program is distributed in the hope that it will be useful,
00043  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00044  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00045  * GNU Lesser General Public License LGPL and the BSD license for more details.
00046  *
00047  * You should have received a copy of the GNU Lesser General Public
00048  * License LGPL and BSD license along with this program.
00049  *
00050  ****************************************************************/
00051 extern "C" {
00052 #include "ethercattype.h"
00053 #include "nicdrv.h"
00054 #include "ethercatbase.h"
00055 #include "ethercatmain.h"
00056 #include "ethercatconfig.h"
00057 #include "ethercatcoe.h"
00058 #include "ethercatdc.h"
00059 #include "ethercatprint.h"
00060 }
00061 #include "youbot/EthercatMasterWithThread.hpp"
00062 #include "youbot/DataTrace.hpp"
00063 
00064 namespace youbot {
00065 
00066 EthercatMasterWithThread::EthercatMasterWithThread(const std::string& configFile, const std::string& configFilePath) {
00067   // Bouml preserved body begin 00041171
00068 
00069     this->ethercatConnectionEstablished = false;
00070     ethernetDevice = "eth0";
00071     timeTillNextEthercatUpdate = 1000; //usec
00072     mailboxTimeout = 4000; //micro sec
00073     ethercatTimeout = 500; //micro sec
00074     communicationErrors = 0;
00075     maxCommunicationErrors = 100;
00076     stopThread = false;
00077     this->automaticSendOn = true;
00078     this->automaticReceiveOn = true;
00079     this->configFileName = configFile;
00080     this->configFilepath = configFilePath;
00081     configfile = NULL;
00082 
00083     //initialize to zero
00084     for (unsigned int i = 0; i < 4096; i++) {
00085       IOmap_[i] = 0;
00086     }
00087     //read ethercat parameters form config file
00088     configfile = new ConfigFile(this->configFileName, this->configFilepath);
00089 
00090     // configfile.setSection("EtherCAT");
00091     configfile->readInto(ethernetDevice, "EtherCAT", "EthernetDevice");
00092     configfile->readInto(timeTillNextEthercatUpdate, "EtherCAT", "EtherCATUpdateRate_[usec]");
00093     configfile->readInto(ethercatTimeout, "EtherCAT", "EtherCATTimeout_[usec]");
00094     configfile->readInto(mailboxTimeout, "EtherCAT", "MailboxTimeout_[usec]");
00095     configfile->readInto(maxCommunicationErrors, "EtherCAT", "MaximumNumberOfEtherCATErrors");
00096 
00097     this->initializeEthercat();
00098 
00099 
00100   // Bouml preserved body end 00041171
00101 }
00102 
00103 EthercatMasterWithThread::~EthercatMasterWithThread() {
00104   // Bouml preserved body begin 000411F1
00105     stopThread = true;
00106     threads.join_all();
00107     this->closeEthercat();
00108     if (configfile != NULL)
00109       delete configfile;
00110   // Bouml preserved body end 000411F1
00111 }
00112 
00113 bool EthercatMasterWithThread::isThreadActive() {
00114   // Bouml preserved body begin 000E6AF1
00115     return true;
00116   // Bouml preserved body end 000E6AF1
00117 }
00118 
00119 ///return the quantity of ethercat slave which have an input/output buffer
00120 unsigned int EthercatMasterWithThread::getNumberOfSlaves() const {
00121   // Bouml preserved body begin 00044A71
00122     return this->nrOfSlaves;
00123   // Bouml preserved body end 00044A71
00124 }
00125 
00126 void EthercatMasterWithThread::AutomaticSendOn(const bool enableAutomaticSend) {
00127   // Bouml preserved body begin 000775F1
00128     this->automaticSendOn = enableAutomaticSend;
00129 
00130     if (this->automaticSendOn == true) {
00131       unsigned int slaveNo = 0;
00132 
00133       for (unsigned int i = 0; i < automaticSendOffBufferVector.size(); i++) {
00134         slaveNo = automaticSendOffBufferVector[i].jointNumber - 1;
00135         slaveMessages[slaveNo].stctInput.Set(automaticSendOffBufferVector[i].stctInput);
00136         slaveMessages[slaveNo].stctOutput.Set(automaticSendOffBufferVector[i].stctOutput);
00137         slaveMessages[slaveNo].jointNumber.Set(automaticSendOffBufferVector[i].jointNumber);
00138       }
00139 
00140       automaticSendOffBufferVector.clear();
00141     } else {
00142       return;
00143     }
00144     return;
00145   // Bouml preserved body end 000775F1
00146 }
00147 
00148 void EthercatMasterWithThread::AutomaticReceiveOn(const bool enableAutomaticReceive) {
00149   // Bouml preserved body begin 0008FB71
00150     this->automaticReceiveOn = enableAutomaticReceive;
00151 
00152 
00153     if (this->automaticReceiveOn == false) {
00154       
00155 
00156       for (unsigned int i = 0; i < slaveMessages.size(); i++) {
00157         slaveMessages[i].stctInput.Get(automaticReceiveOffBufferVector[i].stctInput);
00158         slaveMessages[i].stctOutput.Get(automaticReceiveOffBufferVector[i].stctOutput);
00159         slaveMessages[i].jointNumber.Get(automaticReceiveOffBufferVector[i].jointNumber);
00160       }
00161     }
00162 
00163     return;
00164   // Bouml preserved body end 0008FB71
00165 }
00166 
00167 ///provides all ethercat slave informations from the SOEM driver
00168 ///@param ethercatSlaveInfos ethercat slave informations
00169 void EthercatMasterWithThread::getEthercatDiagnosticInformation(std::vector<ec_slavet>& ethercatSlaveInfos) {
00170   // Bouml preserved body begin 00061EF1
00171     ethercatSlaveInfos = this->ethercatSlaveInfo;
00172     for (unsigned int i = 0; i < ethercatSlaveInfos.size(); i++) {
00173       ethercatSlaveInfos[i].inputs = NULL;
00174       ethercatSlaveInfos[i].outputs = NULL;
00175     }
00176   // Bouml preserved body end 00061EF1
00177 }
00178 
00179 ///sends ethercat messages to the motor controllers
00180 /// returns a true if everything it OK and returns false if something fail
00181 bool EthercatMasterWithThread::sendProcessData() {
00182   // Bouml preserved body begin 000E68F1
00183     throw std::runtime_error("When using the EthercatMaster with thread there is not need to send process data manual.");
00184     return false;
00185   // Bouml preserved body end 000E68F1
00186 }
00187 
00188 /// receives ethercat messages from the motor controllers
00189 /// returns a true if everything it OK and returns false if something fail
00190 bool EthercatMasterWithThread::receiveProcessData() {
00191   // Bouml preserved body begin 000E6971
00192     throw std::runtime_error("When using the EthercatMaster with thread there is not need to receive process data manual");
00193     return false;
00194   // Bouml preserved body end 000E6971
00195 }
00196 
00197 /// checks if an error has occurred in the soem driver
00198 /// returns a true if an error has occurred
00199 bool EthercatMasterWithThread::isErrorInSoemDriver() {
00200   // Bouml preserved body begin 000E69F1
00201 
00202     return ec_iserror();
00203 
00204   // Bouml preserved body end 000E69F1
00205 }
00206 
00207 void EthercatMasterWithThread::registerJointTrajectoryController(JointTrajectoryController* object, const unsigned int JointNumber) {
00208   // Bouml preserved body begin 000EBCF1
00209     {
00210       boost::mutex::scoped_lock trajectoryControllerMutex(trajectoryControllerVectorMutex);
00211       if (this->trajectoryControllers[JointNumber - 1] != NULL)
00212         throw std::runtime_error("A joint trajectory controller is already register for this joint!");
00213       if ((JointNumber - 1) >= this->trajectoryControllers.size())
00214         throw std::out_of_range("Invalid joint number");
00215 
00216       this->trajectoryControllers[JointNumber - 1] = object;
00217     }
00218     LOG(debug) << "register joint trajectory controller for joint: " << JointNumber;
00219   // Bouml preserved body end 000EBCF1
00220 }
00221 
00222 void EthercatMasterWithThread::deleteJointTrajectoryControllerRegistration(const unsigned int JointNumber) {
00223   // Bouml preserved body begin 000F06F1
00224     {
00225       boost::mutex::scoped_lock trajectoryControllerMutex(trajectoryControllerVectorMutex);
00226       if ((JointNumber - 1) >= this->trajectoryControllers.size())
00227         throw std::out_of_range("Invalid joint number");
00228 
00229       this->trajectoryControllers[JointNumber - 1] = NULL;
00230     }
00231     LOG(debug) << "delete joint trajectory controller registration for joint: " << JointNumber;
00232   // Bouml preserved body end 000F06F1
00233 }
00234 
00235 unsigned int EthercatMasterWithThread::getNumberOfThreadCyclesPerSecond() {
00236   // Bouml preserved body begin 000F41F1
00237 
00238     return static_cast<unsigned int> (1.0 / ((double) timeTillNextEthercatUpdate / 1000 / 1000));
00239   // Bouml preserved body end 000F41F1
00240 }
00241 
00242 bool EthercatMasterWithThread::isEtherCATConnectionEstablished() {
00243   // Bouml preserved body begin 000F7771
00244     return this->ethercatConnectionEstablished;
00245   // Bouml preserved body end 000F7771
00246 }
00247 
00248 void EthercatMasterWithThread::registerJointLimitMonitor(JointLimitMonitor* object, const unsigned int JointNumber) {
00249   // Bouml preserved body begin 000FB071
00250     {
00251       boost::mutex::scoped_lock limitMonitorMutex(jointLimitMonitorVectorMutex);
00252       if (this->jointLimitMonitors[JointNumber - 1] != NULL)
00253         LOG(warning) << "A joint limit monitor is already register for this joint!";
00254       if ((JointNumber - 1) >= this->jointLimitMonitors.size())
00255         throw std::out_of_range("Invalid joint number");
00256 
00257       this->jointLimitMonitors[JointNumber - 1] = object;
00258     }
00259     LOG(debug) << "register a joint limit monitor for joint: " << JointNumber;
00260   // Bouml preserved body end 000FB071
00261 }
00262 
00263 void EthercatMasterWithThread::registerDataTrace(void* object, const unsigned int JointNumber) {
00264   // Bouml preserved body begin 00105871
00265     {
00266       boost::mutex::scoped_lock datatraceM(dataTracesMutex);
00267       if (this->dataTraces[JointNumber - 1] != NULL)
00268         throw std::runtime_error("A data trace is already register for this joint!");
00269       if ((JointNumber - 1) >= this->dataTraces.size())
00270         throw std::out_of_range("Invalid joint number");
00271 
00272       this->dataTraces[JointNumber - 1] = (DataTrace*)object;
00273     }
00274     LOG(debug) << "register a data trace for joint: " << JointNumber;
00275   // Bouml preserved body end 00105871
00276 }
00277 
00278 void EthercatMasterWithThread::deleteDataTraceRegistration(const unsigned int JointNumber) {
00279   // Bouml preserved body begin 001058F1
00280     {
00281       boost::mutex::scoped_lock datatraceM(dataTracesMutex);
00282       if ((JointNumber - 1) >= this->dataTraces.size())
00283         throw std::out_of_range("Invalid joint number");
00284 
00285       this->dataTraces[JointNumber - 1] = NULL;
00286 
00287     }
00288     LOG(debug) << "removed data trace for joint: " << JointNumber;
00289   // Bouml preserved body end 001058F1
00290 }
00291 
00292 ///establishes the ethercat connection
00293 void EthercatMasterWithThread::initializeEthercat() {
00294   // Bouml preserved body begin 000410F1
00295 
00296     /* initialise SOEM, bind socket to ifname */
00297     if (ec_init(ethernetDevice.c_str())) {
00298       LOG(info) << "Initializing EtherCAT on " << ethernetDevice << " with communication thread";
00299       /* find and auto-config slaves */
00300       if (ec_config(TRUE, &IOmap_) > 0) {
00301 
00302         LOG(trace) << ec_slavecount << " EtherCAT slaves found and configured.";
00303 
00304         /* wait for all slaves to reach Pre OP state */
00305         /*ec_statecheck(0, EC_STATE_PRE_OP,  EC_TIMEOUTSTATE);
00306         if (ec_slave[0].state != EC_STATE_PRE_OP ){
00307         LOG(debug) << "Not all slaves reached pre operational state.";
00308         ec_readstate();
00309         //If not all slaves operational find out which one
00310           for(int i = 1; i<=ec_slavecount ; i++){
00311             if(ec_slave[i].state != EC_STATE_PRE_OP){
00312               printf("Slave %d State=%2x StatusCode=%4x : %s\n",
00313               i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
00314             }
00315           }
00316         }
00317          */
00318 
00319         /* distributed clock is not working
00320         //Configure distributed clock
00321         if(!ec_configdc()){
00322           LOG(warning) << "no distributed clock is available";
00323         }else{
00324 
00325           uint32 CyclTime = 4000000;
00326           uint32 CyclShift = 0;
00327           for (int i = 1; i <= ec_slavecount; i++) {
00328             ec_dcsync0(i, true, CyclTime, CyclShift);
00329           }
00330 
00331         }
00332          */
00333 
00334         /* wait for all slaves to reach SAFE_OP state */
00335         ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE);
00336         if (ec_slave[0].state != EC_STATE_SAFE_OP) {
00337           LOG(warning) << "Not all EtherCAT slaves reached safe operational state.";
00338           ec_readstate();
00339           //If not all slaves operational find out which one
00340           for (int i = 1; i <= ec_slavecount; i++) {
00341             if (ec_slave[i].state != EC_STATE_SAFE_OP) {
00342               LOG(info) << "Slave " << i << " State=" << ec_slave[i].state << " StatusCode=" << ec_slave[i].ALstatuscode << " : " << ec_ALstatuscode2string(ec_slave[i].ALstatuscode);
00343 
00344             }
00345           }
00346         }
00347 
00348 
00349         //Read the state of all slaves
00350         //ec_readstate();
00351 
00352         LOG(trace) << "Request operational state for all EtherCAT slaves";
00353 
00354         ec_slave[0].state = EC_STATE_OPERATIONAL;
00355         // request OP state for all slaves
00356         /* send one valid process data to make outputs in slaves happy*/
00357         ec_send_processdata();
00358         ec_receive_processdata(EC_TIMEOUTRET);
00359         /* request OP state for all slaves */
00360         ec_writestate(0);
00361         // wait for all slaves to reach OP state
00362 
00363         ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);
00364         if (ec_slave[0].state == EC_STATE_OPERATIONAL) {
00365           LOG(trace) << "Operational state reached for all EtherCAT slaves.";
00366         } else {
00367           throw std::runtime_error("Not all EtherCAT slaves reached operational state.");
00368 
00369         }
00370 
00371       } else {
00372         throw std::runtime_error("No EtherCAT slaves found!");
00373       }
00374 
00375     } else {
00376       throw std::runtime_error("No socket connection on " + ethernetDevice + "\nExcecute as root");
00377     }
00378 
00379 
00380 
00381     std::string baseJointControllerName = "TMCM-174";
00382     std::string baseJointControllerNameAlternative = "TMCM-1632";
00383     std::string manipulatorJointControllerName = "TMCM-174";
00384     std::string ManipulatorJointControllerNameAlternative = "TMCM-1610";
00385     std::string actualSlaveName;
00386     nrOfSlaves = 0;
00387     YouBotSlaveMsg emptySlaveMsg;
00388     YouBotSlaveMsgThreadSafe emptySlaveMsgThreadSafe;
00389 
00390     configfile->readInto(baseJointControllerName, "BaseJointControllerName");
00391     configfile->readInto(baseJointControllerNameAlternative, "BaseJointControllerNameAlternative");
00392     configfile->readInto(manipulatorJointControllerName, "ManipulatorJointControllerName");
00393     configfile->readInto(ManipulatorJointControllerNameAlternative, "ManipulatorJointControllerNameAlternative");
00394 
00395     //reserve memory for all slave with a input/output buffer
00396     for (int cnt = 1; cnt <= ec_slavecount; cnt++) {
00397            LOG(trace) << "Slave: " << cnt  << " Name: " << ec_slave[cnt].name  << " Output size: " << ec_slave[cnt].Obits
00398                    << "bits Input size: " << ec_slave[cnt].Ibits << "bits State: " << ec_slave[cnt].state  
00399                    << " delay: " << ec_slave[cnt].pdelay; //<< " has dclock: " << (bool)ec_slave[cnt].hasdc;
00400 
00401       ethercatSlaveInfo.push_back(ec_slave[cnt]);
00402 
00403       actualSlaveName = ec_slave[cnt].name;
00404       if ((actualSlaveName == baseJointControllerName || actualSlaveName == baseJointControllerNameAlternative || 
00405               actualSlaveName == manipulatorJointControllerName || actualSlaveName == ManipulatorJointControllerNameAlternative
00406               ) && ec_slave[cnt].Obits > 0 && ec_slave[cnt].Ibits > 0) {
00407         nrOfSlaves++;
00408         ethercatOutputBufferVector.push_back((SlaveMessageOutput*) (ec_slave[cnt].outputs));
00409         ethercatInputBufferVector.push_back((SlaveMessageInput*) (ec_slave[cnt].inputs));
00410         YouBotSlaveMailboxMsgThreadSafe emptyMailboxSlaveMsg(cnt);
00411         mailboxMessages.push_back(emptyMailboxSlaveMsg);
00412         pendingMailboxMsgsReply.push_back(false);
00413         trajectoryControllers.push_back(NULL);
00414         jointLimitMonitors.push_back(NULL);
00415         slaveMessages.push_back(emptySlaveMsgThreadSafe);
00416         outstandingMailboxMsgFlag.push_back(false);
00417         newInputMailboxMsgFlag.push_back(false);
00418         dataTraces.push_back(NULL);
00419       }
00420     }
00421     automaticReceiveOffBufferVector.reserve(slaveMessages.size());
00422 
00423     if (nrOfSlaves > 0) {
00424       LOG(info) << nrOfSlaves << " EtherCAT slaves found";
00425     } else {
00426       throw std::runtime_error("No EtherCAT slave could be found");
00427       return;
00428     }
00429 
00430     stopThread = false;
00431     threads.create_thread(boost::bind(&EthercatMasterWithThread::updateSensorActorValues, this));
00432 
00433     SLEEP_MILLISEC(10); //needed to start up thread and EtherCAT communication
00434 
00435     this->ethercatConnectionEstablished = true;
00436     return;
00437   // Bouml preserved body end 000410F1
00438 }
00439 
00440 ///closes the ethercat connection
00441 bool EthercatMasterWithThread::closeEthercat() {
00442   // Bouml preserved body begin 00041271
00443 
00444     this->ethercatConnectionEstablished = false;
00445     // Request safe operational state for all slaves
00446     ec_slave[0].state = EC_STATE_SAFE_OP;
00447 
00448     /* request SAFE_OP state for all slaves */
00449     ec_writestate(0);
00450 
00451     //stop SOEM, close socket
00452     ec_close();
00453 
00454     return true;
00455   // Bouml preserved body end 00041271
00456 }
00457 
00458 ///stores a ethercat message to the buffer
00459 ///@param msgBuffer ethercat message
00460 ///@param jointNumber joint number of the sender joint
00461 void EthercatMasterWithThread::setMsgBuffer(const YouBotSlaveMsg& msgBuffer, const unsigned int jointNumber) {
00462   // Bouml preserved body begin 000414F1
00463 
00464     if (this->automaticSendOn == true) {
00465       slaveMessages[jointNumber - 1].stctOutput.Set(msgBuffer.stctOutput);
00466     } else {
00467       YouBotSlaveMsg localMsg;
00468       localMsg.stctInput = msgBuffer.stctInput;
00469       localMsg.stctOutput = msgBuffer.stctOutput;
00470       localMsg.jointNumber = jointNumber;
00471       automaticSendOffBufferVector.push_back(localMsg);
00472     }
00473 
00474   // Bouml preserved body end 000414F1
00475 }
00476 
00477 ///get a ethercat message form the buffer
00478 ///@param msgBuffer ethercat message
00479 ///@param jointNumber joint number of the receiver joint
00480 void EthercatMasterWithThread::getMsgBuffer(const unsigned int jointNumber, YouBotSlaveMsg& returnMsg) {
00481   // Bouml preserved body begin 00041571
00482 
00483     if (this->automaticReceiveOn == true) {
00484       slaveMessages[jointNumber - 1].stctInput.Get(returnMsg.stctInput);
00485       slaveMessages[jointNumber - 1].stctOutput.Get(returnMsg.stctOutput);
00486       slaveMessages[jointNumber - 1].jointNumber.Get(returnMsg.jointNumber);
00487     } else {
00488       returnMsg = this->automaticReceiveOffBufferVector[jointNumber - 1];
00489     }
00490 
00491   // Bouml preserved body end 00041571
00492 }
00493 
00494 ///stores a mailbox message in a buffer which will be sent to the motor controllers
00495 ///@param msgBuffer ethercat mailbox message
00496 ///@param jointNumber joint number of the sender joint
00497 void EthercatMasterWithThread::setMailboxMsgBuffer(const YouBotSlaveMailboxMsg& msgBuffer, const unsigned int jointNumber) {
00498   // Bouml preserved body begin 00049D71
00499     this->mailboxMessages[jointNumber - 1].stctOutput.Set(msgBuffer.stctOutput);
00500     outstandingMailboxMsgFlag[jointNumber - 1] = true;
00501     return;
00502   // Bouml preserved body end 00049D71
00503 }
00504 
00505 ///gets a mailbox message form the buffer which came form the motor controllers
00506 ///@param msgBuffer ethercat mailbox message
00507 ///@param jointNumber joint number of the receiver joint
00508 bool EthercatMasterWithThread::getMailboxMsgBuffer(YouBotSlaveMailboxMsg& mailboxMsg, const unsigned int jointNumber) {
00509   // Bouml preserved body begin 00049DF1
00510     if (newInputMailboxMsgFlag[jointNumber - 1] == true) {
00511       this->mailboxMessages[jointNumber - 1].stctInput.Get(mailboxMsg.stctInput);
00512       newInputMailboxMsgFlag[jointNumber - 1] = false;
00513       return true;
00514     }
00515     return false;
00516   // Bouml preserved body end 00049DF1
00517 }
00518 
00519 ///sends the mailbox Messages which have been stored in the buffer
00520 ///@param mailboxMsg ethercat mailbox message
00521 bool EthercatMasterWithThread::sendMailboxMessage(const YouBotSlaveMailboxMsg& mailboxMsg) {
00522   // Bouml preserved body begin 00052F71
00523     //  LOG(trace) << "send mailbox message (buffer two) slave " << mailboxMsg.getSlaveNo();
00524     mailboxBufferSend[0] = mailboxMsg.stctOutput.moduleAddress;
00525     mailboxBufferSend[1] = mailboxMsg.stctOutput.commandNumber;
00526     mailboxBufferSend[2] = mailboxMsg.stctOutput.typeNumber;
00527     mailboxBufferSend[3] = mailboxMsg.stctOutput.motorNumber;
00528     mailboxBufferSend[4] = mailboxMsg.stctOutput.value >> 24;
00529     mailboxBufferSend[5] = mailboxMsg.stctOutput.value >> 16;
00530     mailboxBufferSend[6] = mailboxMsg.stctOutput.value >> 8;
00531     mailboxBufferSend[7] = mailboxMsg.stctOutput.value & 0xff;
00532     if (ec_mbxsend(mailboxMsg.slaveNumber, &mailboxBufferSend, mailboxTimeout)) {
00533       return true;
00534     } else {
00535       return false;
00536     }
00537   // Bouml preserved body end 00052F71
00538 }
00539 
00540 ///receives mailbox messages and stores them in the buffer
00541 ///@param mailboxMsg ethercat mailbox message
00542 bool EthercatMasterWithThread::receiveMailboxMessage(YouBotSlaveMailboxMsg& mailboxMsg) {
00543   // Bouml preserved body begin 00052FF1
00544     if (ec_mbxreceive(mailboxMsg.slaveNumber, &mailboxBufferReceive, mailboxTimeout)) {
00545       //    LOG(trace) << "received mailbox message (buffer two) slave " << mailboxMsg.getSlaveNo();
00546       mailboxMsg.stctInput.replyAddress = (int) mailboxBufferReceive[0];
00547       mailboxMsg.stctInput.moduleAddress = (int) mailboxBufferReceive[1];
00548       mailboxMsg.stctInput.status = (int) mailboxBufferReceive[2];
00549       mailboxMsg.stctInput.commandNumber = (int) mailboxBufferReceive[3];
00550       mailboxMsg.stctInput.value = (mailboxBufferReceive[4] << 24 | mailboxBufferReceive[5] << 16 | mailboxBufferReceive[6] << 8 | mailboxBufferReceive[7]);
00551       return true;
00552     }
00553     return false;
00554   // Bouml preserved body end 00052FF1
00555 }
00556 
00557 ///sends and receives ethercat messages and mailbox messages to and from the motor controllers
00558 ///this method is executed in a separate thread
00559 void EthercatMasterWithThread::updateSensorActorValues() {
00560   // Bouml preserved body begin 0003F771
00561 
00562     long timeToWait = 0;
00563     boost::posix_time::ptime startTime = boost::posix_time::microsec_clock::local_time();
00564     boost::posix_time::time_duration pastTime;
00565     //  int counter = 0;
00566     boost::posix_time::time_duration realperiode;
00567     boost::posix_time::time_duration timeSum = startTime - startTime;
00568     SlaveMessageOutput trajectoryContollerOutput;
00569     YouBotSlaveMailboxMsg tempMsg;
00570 
00571 
00572     while (!stopThread) {
00573 
00574       pastTime = boost::posix_time::microsec_clock::local_time() - startTime;
00575       timeToWait = timeTillNextEthercatUpdate - pastTime.total_microseconds() - 100;
00576 
00577       if (timeToWait < 0 || timeToWait > (int) timeTillNextEthercatUpdate) {
00578         //    printf("Missed communication period of %d  microseconds it have been %d microseconds \n",timeTillNextEthercatUpdate, (int)pastTime.total_microseconds()+ 100);
00579       } else {
00580         boost::this_thread::sleep(boost::posix_time::microseconds(timeToWait));
00581       }
00582 
00583       // realperiode = boost::posix_time::microsec_clock::local_time() - startTime;
00584       startTime = boost::posix_time::microsec_clock::local_time();
00585 
00586       /*
00587             counter++;
00588             timeSum  = timeSum + realperiode;
00589 
00590             if(counter == 1000){
00591 
00592               double dtotaltime = (double)timeSum.total_microseconds()/counter;
00593               printf("TotalTime %7.0lf us\n", dtotaltime);
00594               counter = 0;
00595               timeSum = startTime - startTime;
00596             }
00597        */
00598 
00599 
00600 
00601 
00602       //send and receive data from ethercat
00603       if (ec_send_processdata() == 0) {
00604         LOG(warning) << "Sending process data failed";
00605       }
00606 
00607       if (ec_receive_processdata(this->ethercatTimeout) == 0) {
00608         if (communicationErrors == 0) {
00609           LOG(warning) << "Receiving data failed";
00610         }
00611         communicationErrors++;
00612       } else {
00613         communicationErrors = 0;
00614       }
00615 
00616       if (communicationErrors > maxCommunicationErrors) {
00617         LOG(error) << "Lost EtherCAT connection";
00618         this->closeEthercat();
00619         stopThread = true;
00620         break;
00621       }
00622 
00623       if (ec_iserror())
00624         LOG(warning) << "there is an error in the soem driver";
00625 
00626 
00627       for (unsigned int i = 0; i < nrOfSlaves; i++) {
00628 
00629         //send data
00630         if(automaticSendOn == true)
00631           slaveMessages[i].stctOutput.Get(*(ethercatOutputBufferVector[i]));
00632 
00633         //receive data
00634         if(automaticReceiveOn == true)
00635           slaveMessages[i].stctInput.Set(*(ethercatInputBufferVector[i]));
00636 
00637 
00638         // Limit checker
00639         if (jointLimitMonitors[i] != NULL) {
00640           this->jointLimitMonitors[i]->checkLimitsProcessData(*(ethercatInputBufferVector[i]), *(ethercatOutputBufferVector[i]));
00641           //copy back changed velocity for limit checker
00642           slaveMessages[i].stctOutput.Set(*(ethercatOutputBufferVector[i]));
00643         }
00644         // this->parseYouBotErrorFlags(secondBufferVector[i]);
00645 
00646         //send mailbox messages from first buffer
00647         if (outstandingMailboxMsgFlag[i]) { 
00648           this->mailboxMessages[i].stctOutput.Get(tempMsg.stctOutput);
00649           this->mailboxMessages[i].slaveNumber.Get(tempMsg.slaveNumber);
00650           sendMailboxMessage(tempMsg);
00651           outstandingMailboxMsgFlag[i] = false;
00652           pendingMailboxMsgsReply[i] = true;
00653         }
00654 
00655         //receive mailbox messages to first buffer
00656         if (pendingMailboxMsgsReply[i]) {
00657           this->mailboxMessages[i].slaveNumber.Get(tempMsg.slaveNumber);
00658           if (receiveMailboxMessage(tempMsg)) {
00659             this->mailboxMessages[i].stctInput.Set(tempMsg.stctInput);
00660             newInputMailboxMsgFlag[i] = true;
00661             pendingMailboxMsgsReply[i] = false;
00662           }
00663         }
00664       }
00665       
00666       // Trajectory Controller
00667       {
00668         boost::mutex::scoped_lock trajectoryControllerMutex(trajectoryControllerVectorMutex);
00669         for (unsigned int i = 0; i < nrOfSlaves; i++) {
00670           if (this->trajectoryControllers[i] != NULL) {
00671             if (this->trajectoryControllers[i]->updateTrajectoryController(*(ethercatInputBufferVector[i]), trajectoryContollerOutput)) {
00672               //   printf("send vel slave: %d", i);
00673               (*(ethercatOutputBufferVector[i])).controllerMode = trajectoryContollerOutput.controllerMode;
00674               (*(ethercatOutputBufferVector[i])).value = trajectoryContollerOutput.value;
00675               //copy back
00676               slaveMessages[i].stctOutput.Set(*(ethercatOutputBufferVector[i]));
00677             }
00678           }
00679         }
00680       }
00681       // update Data Traces
00682       for (unsigned int i = 0; i < nrOfSlaves; i++) {
00683         {
00684           boost::mutex::scoped_lock datatraceM(dataTracesMutex);
00685           if (dataTraces[i] != NULL) {
00686             ((DataTrace*)dataTraces[i])->updateTrace();
00687           }
00688         }
00689       }
00690     }
00691   // Bouml preserved body end 0003F771
00692 }
00693 
00694 void EthercatMasterWithThread::parseYouBotErrorFlags(const YouBotSlaveMsg& messageBuffer) {
00695   // Bouml preserved body begin 000A9E71
00696     std::stringstream errorMessageStream;
00697     errorMessageStream << " ";
00698     std::string errorMessage;
00699     errorMessage = errorMessageStream.str();
00700 
00701 
00702     if (messageBuffer.stctInput.errorFlags & OVER_CURRENT) {
00703       LOG(error) << errorMessage << "got over current";
00704       //    throw JointErrorException(errorMessage + "got over current");
00705     }
00706 
00707     if (messageBuffer.stctInput.errorFlags & UNDER_VOLTAGE) {
00708       LOG(error) << errorMessage << "got under voltage";
00709       //    throw JointErrorException(errorMessage + "got under voltage");
00710     }
00711 
00712     if (messageBuffer.stctInput.errorFlags & OVER_VOLTAGE) {
00713       LOG(error) << errorMessage << "got over voltage";
00714       //   throw JointErrorException(errorMessage + "got over voltage");
00715     }
00716 
00717     if (messageBuffer.stctInput.errorFlags & OVER_TEMPERATURE) {
00718       LOG(error) << errorMessage << "got over temperature";
00719       //   throw JointErrorException(errorMessage + "got over temperature");
00720     }
00721 
00722     if (messageBuffer.stctInput.errorFlags & MOTOR_HALTED) {
00723       //   LOG(info) << errorMessage << "is halted";
00724       //   throw JointErrorException(errorMessage + "is halted");
00725     }
00726 
00727     if (messageBuffer.stctInput.errorFlags & HALL_SENSOR_ERROR) {
00728       LOG(error) << errorMessage << "got hall sensor problem";
00729       //   throw JointErrorException(errorMessage + "got hall sensor problem");
00730     }
00731 
00732     //    if (messageBuffer.stctInput.errorFlags & ENCODER_ERROR) {
00733     //      LOG(error) << errorMessage << "got encoder problem";
00734     //      //   throw JointErrorException(errorMessage + "got encoder problem");
00735     //    }
00736     //
00737     //     if (messageBuffer.stctInput.errorFlags & INITIALIZATION_ERROR) {
00738     //      LOG(error) << errorMessage << "got inizialization problem";
00739     //      //   throw JointErrorException(errorMessage + "got motor winding problem");
00740     //    }
00741 
00742 //    if (messageBuffer.stctInput.errorFlags & PWM_MODE_ACTIVE) {
00743     //  LOG(error) << errorMessage << "has PWM mode active";
00744       //   throw JointErrorException(errorMessage + "the cycle time is violated");
00745 //    }
00746 
00747     if (messageBuffer.stctInput.errorFlags & VELOCITY_MODE) {
00748       //   LOG(info) << errorMessage << "has velocity mode active";
00749       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00750     }
00751 
00752     if (messageBuffer.stctInput.errorFlags & POSITION_MODE) {
00753       //   LOG(info) << errorMessage << "has position mode active";
00754       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00755     }
00756 
00757     if (messageBuffer.stctInput.errorFlags & TORQUE_MODE) {
00758       //   LOG(info) << errorMessage << "has torque mode active";
00759       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00760     }
00761 
00762     //    if (messageBuffer.stctInput.errorFlags & EMERGENCY_STOP) {
00763     //      LOG(info) << errorMessage << "has emergency stop active";
00764     //      //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00765     //    }
00766     //
00767     //    if (messageBuffer.stctInput.errorFlags & FREERUNNING) {
00768     //   //   LOG(info) << errorMessage << "has freerunning active";
00769     //      //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00770     //    }
00771 
00772     if (messageBuffer.stctInput.errorFlags & POSITION_REACHED) {
00773       //    LOG(info) << errorMessage << "has position reached";
00774       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00775     }
00776 
00777     if (messageBuffer.stctInput.errorFlags & INITIALIZED) {
00778       //  LOG(info) << errorMessage << "is initialized";
00779       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00780     }
00781 
00782     if (messageBuffer.stctInput.errorFlags & TIMEOUT) {
00783       LOG(error) << errorMessage << "has a timeout";
00784       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00785     }
00786 
00787     if (messageBuffer.stctInput.errorFlags & I2T_EXCEEDED) {
00788       LOG(error) << errorMessage << "exceeded I2t";
00789       //   throw JointErrorException(errorMessage + "need to initialize the sinus commutation");
00790     }
00791 
00792   // Bouml preserved body end 000A9E71
00793 }
00794 
00795 std::string EthercatMasterWithThread::configFileName;
00796 
00797 std::string EthercatMasterWithThread::configFilepath;
00798 
00799 
00800 } // namespace youbot
Generated by  doxygen 1.6.3