diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Events/EventRouter.cc ./Events/EventRouter.cc --- ../Tekkotsu_2.4/Events/EventRouter.cc Thu Jul 7 18:34:15 2005 +++ ./Events/EventRouter.cc Tue Aug 16 14:43:04 2005 @@ -1,5 +1,7 @@ #include "EventRouter.h" #include "Shared/Profiler.h" +#include "Behaviors/BehaviorBase.h" +#include "Shared/ProjectInterface.h" #include EventRouter * erouter=NULL; @@ -26,8 +28,28 @@ sort(timers.begin(),last_it,TimerEntryPtrCmp()); //re-sort the timers we're processing (at the beginning of timers) inplace_merge(timers.begin(),last_it,timers.end(),TimerEntryPtrCmp()); //now do a merge of the sorted processed stuff and the rest of the list (which is still sorted) // if(process.size()>0) chkTimers(); - for(timer_it_t it=process.begin(); it!=process.end(); it++) // process the timers we say we're going to, can no longer assume anything about the state of the world - (*it)->el->processEvent(EventBase(EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next)); + for(timer_it_t it=process.begin(); it!=process.end(); it++) { // process the timers we say we're going to, can no longer assume anything about the state of the world + EventBase e(EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next); + try { + (*it)->el->processEvent(e); + } catch(const std::exception& ex) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast((*it)->el)) + msg+="listener "+beh->getName(); + else + msg+="unnamed EventListener"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex)) + throw; + } catch(...) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast((*it)->el)) + msg+="listener "+beh->getName(); + else + msg+="unnamed EventListener"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL)) + throw; + } + } // if(process.size()>0) chkTimers(); static const TimerEntry deadTimer((unsigned int)-1); // matches all the dead ones as set in the incrementation phase last_it=lower_bound(timers.begin(),timers.end(),&deadTimer,TimerEntryPtrCmp()); //find the beginning of all the non-repeating timers we're clearing @@ -345,14 +367,52 @@ std::vector t; trappers.getMapping(e,t); for(std::vector::iterator it=t.begin(); it!=t.end(); it++) - if(trappers.verifyMapping(*it,e)) - if((*it)->trapEvent(e)) - return; + if(trappers.verifyMapping(*it,e)) { + try { + if((*it)->trapEvent(e)) + return; + } catch(const std::exception& ex) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast(*it)) + msg+="trapper "+beh->getName(); + else + msg+="unnamed EventTrapper"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex)) + throw; + } catch(...) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast(*it)) + msg+="trapper "+beh->getName(); + else + msg+="unnamed EventTrapper"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL)) + throw; + } + } std::vector l; listeners.getMapping(e,l); for(std::vector::iterator it=l.begin(); it!=l.end(); it++) - if(listeners.verifyMapping(*it,e)) - (*it)->processEvent(e); + if(listeners.verifyMapping(*it,e)) { + try { + (*it)->processEvent(e); + } catch(const std::exception& ex) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast(*it)) + msg+="listener "+beh->getName(); + else + msg+="unnamed EventListener"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex)) + throw; + } catch(...) { + std::string msg="Occurred while processing event "+e.getName()+" by "; + if(BehaviorBase * beh=dynamic_cast(*it)) + msg+="listener "+beh->getName(); + else + msg+="unnamed EventListener"; + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL)) + throw; + } + } // cout << "done." << flush; } diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/ProjectInterface.cc ./Shared/ProjectInterface.cc --- ../Tekkotsu_2.4/Shared/ProjectInterface.cc Wed Jun 1 01:47:49 2005 +++ ./Shared/ProjectInterface.cc Tue Aug 16 14:00:17 2005 @@ -1,37 +1,63 @@ #include "ProjectInterface.h" -#include "Events/VisionObjectEvent.h" +#include "Wireless/Socket.h" +#include -FilterBankGenerator * ProjectInterface::defRawCameraGenerator=0; -FilterBankGenerator * ProjectInterface::defInterleavedYUVGenerator=0; -JPEGGenerator * ProjectInterface::defColorJPEGGenerator=0; -JPEGGenerator * ProjectInterface::defGrayscaleJPEGGenerator=0; -SegmentedColorGenerator * ProjectInterface::defSegmentedColorGenerator=0; -RLEGenerator * ProjectInterface::defRLEGenerator=0; -RegionGenerator * ProjectInterface::defRegionGenerator=0; +namespace ProjectInterface { -unsigned int ProjectInterface::visRawCameraSID=0; + bool displayException(const char * file, int line, const char * message, const std::exception* ex) { + if(file!=NULL) { + serr->printf("Exception caught at %s:%d => ",file,line); + } else { + serr->printf("Exception => "); + } + if(ex!=NULL) { + serr->printf("'%s'",ex->what()); + } else { + serr->printf("'%s'","Unknown type"); + } + if(message!=NULL) { + serr->printf(" (%s)\n",message); + } else { + serr->printf("\n"); + } + return true; + } + bool (*uncaughtException)(const char * file, int line, const char * message, const std::exception* ex)=&displayException; -unsigned int ProjectInterface::visInterleaveSID=0; -unsigned int ProjectInterface::visColorJPEGSID=0; -unsigned int ProjectInterface::visGrayscaleJPEGSID=1; + FilterBankGenerator * defRawCameraGenerator=0; + FilterBankGenerator * defInterleavedYUVGenerator=0; + JPEGGenerator * defColorJPEGGenerator=0; + JPEGGenerator * defGrayscaleJPEGGenerator=0; + SegmentedColorGenerator * defSegmentedColorGenerator=0; + RLEGenerator * defRLEGenerator=0; + RegionGenerator * defRegionGenerator=0; -unsigned int ProjectInterface::visSegmentSID=0; + unsigned int visRawCameraSID=0; -unsigned int ProjectInterface::visRLESID=0; + unsigned int visInterleaveSID=0; -unsigned int ProjectInterface::visRegionSID=0; + unsigned int visColorJPEGSID=0; + unsigned int visGrayscaleJPEGSID=1; -unsigned int ProjectInterface::visPinkBallSID=0; -unsigned int ProjectInterface::visBlueBallSID=1; -unsigned int ProjectInterface::visHandSID=2; + unsigned int visSegmentSID=0; -unsigned int ProjectInterface::doubleLayer=5; -unsigned int ProjectInterface::fullLayer=4; -unsigned int ProjectInterface::halfLayer=3; -unsigned int ProjectInterface::quarterLayer=2; -unsigned int ProjectInterface::eighthLayer=1; -unsigned int ProjectInterface::sixteenthLayer=0; + unsigned int visRLESID=0; + + unsigned int visRegionSID=0; + + unsigned int visPinkBallSID=0; + unsigned int visBlueBallSID=1; + unsigned int visHandSID=2; + + unsigned int doubleLayer=5; + unsigned int fullLayer=4; + unsigned int halfLayer=3; + unsigned int quarterLayer=2; + unsigned int eighthLayer=1; + unsigned int sixteenthLayer=0; + +} /*! @file * @brief Provides instantiation of the non-required members of ProjectInterface diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/ProjectInterface.h ./Shared/ProjectInterface.h --- ../Tekkotsu_2.4/Shared/ProjectInterface.h Wed Jun 1 01:47:49 2005 +++ ./Shared/ProjectInterface.h Tue Aug 16 14:00:17 2005 @@ -8,6 +8,9 @@ class RLEGenerator; class RegionGenerator; class JPEGGenerator; +namespace std { + class exception; +} //! A collection of the global variables which should be set by a project to use the Tekkotsu framework /*! You don't necessarily need to define all of these, but if you want @@ -39,6 +42,27 @@ * (Each call should return the same behavior) */ BehaviorBase& startupBehavior(); + //! The exception handler for exceptions which have fallen through to base Tekkotsu functions + /*! You can override this to install your own handler by assigning a + * new function. This defaults to displayException(), which + * does not call abort() (which would otherwise be the + * default if the exception fell through). + * @param file The file where the exception was caught (usually just pass __FILE__), or NULL + * @param line The line number where the exception was caught (usually just pass __LINE__), if @a file is NULL, @a line is ignored + * @param message An addition message, or NULL + * @param ex The exception which was caught, or NULL if it is was not a std::exception subclass + * @return true if the exception was handled, false if the exception should be rethrown */ + extern bool (*uncaughtException)(const char * file, int line, const char * message, const std::exception* ex); + + //! Displays information about an exception on #serr, provides a default value for #uncaughtException + /*! You can call this directly from your own code any time you would like an exception error message. + * @param file The file where the exception was caught (usually just pass __FILE__), or NULL + * @param line The line number where the exception was caught (usually just pass __LINE__), if @a file is NULL, @a line is ignored + * @param message An addition message, or NULL + * @param ex The exception which was caught, or NULL if it is was not a std::exception subclass + * @return true, indicating the exception was handled adequately */ + bool displayException(const char * file, int line, const char * message, const std::exception* ex); + //! A collection of the various stages of vision processing. None of these are absolutely required, but are needed to run included demo behaviors and TekkotsuMon modules /*! @name Vision Setup */ //! pointer to generator diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/debuget.h ./Shared/debuget.h --- ../Tekkotsu_2.4/Shared/debuget.h Sun Aug 7 00:11:04 2005 +++ ./Shared/debuget.h Tue Aug 16 17:23:43 2005 @@ -2,6 +2,7 @@ #define INCLUDED_debuget_h #include +#include #ifdef DEBUG #include @@ -101,8 +102,6 @@ } } -#include - //! displays hex and ascii values of @a size bytes from @a p inline void hexout3(const char* buf, size_t size) { const unsigned int linelen=24; diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Vision/BufferedImageGenerator.cc ./Vision/BufferedImageGenerator.cc --- ../Tekkotsu_2.4/Vision/BufferedImageGenerator.cc Fri Aug 5 17:56:21 2005 +++ ./Vision/BufferedImageGenerator.cc Mon Aug 15 19:19:01 2005 @@ -243,8 +243,8 @@ void BufferedImageGenerator::freeCaches() { FilterBankGenerator::freeCaches(); - for(unsigned int i=0; imainProfile); - +try { //pass the destination buffer and buffer size here jpeg_mem_dest(&cinfo, images[layer][chan], widths[layer]*heights[layer]*3+JPEG_HEADER_PAD); @@ -274,6 +274,13 @@ // results bytesUsed[layer][chan]=jpeg_mem_size(&cinfo); imageValids[layer][chan]=true; +} catch(const std::exception& ex) { + std::cerr << "Exception while compressing JPEG: " << ex.what() << std::endl; //really, can only be bad_alloc + std::cerr << "layer==" << layer << " channel==" << chan << " image==" << (void*)images[layer][chan] << std::endl; + std::cerr << "width==" << widths[layer] << " height==" << heights[layer] << std::endl; + std::cerr << "row_stride==" << src->getStride(layer) << " next_scanline==" << (void*)cinfo.next_scanline << " image_height==" << cinfo.image_height << std::endl; + jpeg_destroy_compress(&cinfo); +} } void diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Wireless/Wireless.cc ./Wireless/Wireless.cc --- ../Tekkotsu_2.4/Wireless/Wireless.cc Mon Aug 1 19:17:59 2005 +++ ./Wireless/Wireless.cc Tue Aug 16 14:37:05 2005 @@ -1,6 +1,7 @@ #include "Wireless.h" #include "Socket.h" #include +#include "Shared/ProjectInterface.h" Wireless *wireless=NULL; @@ -184,6 +185,7 @@ void Wireless::ListenCont(void* msg) { +try { antEnvMsg * Msg = ( antEnvMsg * ) msg; int sock = ( int )( Msg->continuation ); @@ -206,11 +208,20 @@ //cout << "Listen set lip: " << local_ipaddr << endl; receive( sock ); } + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",NULL)) + throw; +} } void Wireless::ConnectCont(void *msg) { +try { antEnvMsg * Msg = ( antEnvMsg * ) msg; int sock = ( int )( Msg->continuation ); @@ -228,11 +239,20 @@ //cout << "Connect set lip: " << local_ipaddr << endl; receive( sock ); } + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",NULL)) + throw; +} } void Wireless::BindCont(void *msg) { +try { UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*)msg; int sock = (int)bindMsg->continuation; @@ -248,6 +268,14 @@ } else { //cout << "Bind got 0" << endl; }*/ + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",NULL)) + throw; +} } void @@ -282,6 +310,7 @@ void Wireless::SendCont(void* msg) { +try { antEnvMsg * Msg = ( antEnvMsg * ) msg; int sock = ( int )( Msg->continuation ); @@ -310,6 +339,14 @@ } sockets[sock]->flush(); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",NULL)) + throw; +} } /*! @bug This doesn't actually seem to block until the message is @@ -397,6 +434,7 @@ void Wireless::ReceiveCont(void* msg) { +try { // get the socket index before casting the message into UDP or TCP form antEnvMsg * Msg = ( antEnvMsg * ) msg; int sock = ( int )( Msg->continuation ); @@ -460,6 +498,14 @@ } receive( sock ); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",NULL)) + throw; +} } void @@ -522,6 +568,7 @@ void Wireless::CloseCont(void* msg) { +try { antEnvMsg * closeMsg = ( antEnvMsg * ) msg; int sock = ( int )( closeMsg->continuation ); if ( sockets[sock] == NULL ) @@ -546,6 +593,14 @@ break; } } + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",NULL)) + throw; +} } #else // PLATFORM_LOCAL @@ -944,8 +999,17 @@ // clear this message from the receiving buffer if ( sockets[*it]->state != CONNECTION_CONNECTED ) connect( *it, sockets[*it]->getPeerAddressAsString().c_str(), sockets[*it]->getPeerPort() ); - } else if ( sockets[*it]->rcvcbckfn != NULL ) - sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize ); + } else if ( sockets[*it]->rcvcbckfn != NULL ) { + try { + sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize ); + } catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",&ex)) + throw; + } catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",NULL)) + throw; + } + } sockets[*it]->recvSize = 0; } } @@ -971,8 +1035,17 @@ continue; } else { //cout << "Read " << sockets[*it]->recvSize << " bytes " << sockets[*it]->rcvcbckfn << endl; - if ( sockets[*it]->rcvcbckfn != NULL ) - sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize ); + if ( sockets[*it]->rcvcbckfn != NULL ) { + try { + sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize ); + } catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",&ex)) + throw; + } catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",NULL)) + throw; + } + } sockets[*it]->recvSize = 0; } } else { diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/aperios/MMCombo/MMCombo.cc ./aperios/MMCombo/MMCombo.cc --- ../Tekkotsu_2.4/aperios/MMCombo/MMCombo.cc Thu Aug 4 17:10:11 2005 +++ ./aperios/MMCombo/MMCombo.cc Tue Aug 16 14:27:58 2005 @@ -38,6 +38,7 @@ soundManagerMemRgn(NULL), runLevel(0), num_open(0), etrans(NULL), isStopped(true) { +try { for(unsigned int i=0; i(); EventTranslator::registerPrototype(); EventTranslator::registerPrototype(); +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo construction",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo construction",NULL)) + throw; +} } OStatus MMCombo::DoInit(const OSystemEvent&) { +try { cout << objectName << "::DoInit() " << endl; isStopped=false; @@ -161,11 +170,21 @@ cout << objectName << "::DoInit()-DONE" << endl; return oSUCCESS; + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoInit()",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoInit()",NULL)) + throw; +} +return oSUCCESS; } OStatus MMCombo::DoStart(const OSystemEvent&) { +try { cout << objectName << "::DoStart() " << endl; // initialize the current power status, doesn't always give us @@ -192,11 +211,21 @@ cout << objectName << "::DoStart()-DONE" << endl; return oSUCCESS; + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStart()",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStart()",NULL)) + throw; +} +return oSUCCESS; } OStatus MMCombo::DoStop(const OSystemEvent&) { +try { cout << objectName << "::DoStop()..." << endl; if(strcmp(objectName,"MainObj")==0) { ProjectInterface::startupBehavior().DoStop(); @@ -208,11 +237,21 @@ isStopped=true; cout << objectName << "::DoStop()-DONE" << endl; return oSUCCESS; + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStop()",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStop()",NULL)) + throw; +} +return oSUCCESS; } OStatus MMCombo::DoDestroy(const OSystemEvent&) { +try { cout << objectName << "::DoDestroy()..." << endl; delete etrans; etrans=NULL; @@ -228,6 +267,15 @@ DELETE_ALL_SUBJECT_AND_OBSERVER; cout << objectName << "::DoDestroy()-DONE" << endl; return oSUCCESS; + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoDestroy()",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoDestroy()",NULL)) + throw; +} +return oSUCCESS; } /*! Called when MotoObj is initially ready as well as when it has finished @@ -298,6 +346,8 @@ void MMCombo::GotInterProcessEvent(const ONotifyEvent& event){ + EventBase* evt=NULL; +try { //cout << objectName << "-GOTInterProcessEvent " << event.NumOfData() << "..." << flush; //cout << TimeET() << endl; // PROFSECTION("GotMemRegion()",state->mainProfile); @@ -305,17 +355,34 @@ return; for(int i=0; idecodeEvent(msg->Base(),msg->Size()); + evt=etrans->decodeEvent(msg->Base(),msg->Size()); if(evt!=NULL) erouter->postEvent(evt); } observer[obsEventTranslatorComm]->AssertReady(); //cout << "done" << endl; + +} catch(const std::exception& ex) { + observer[obsEventTranslatorComm]->AssertReady(); + std::string msg("Occurred during inter-process event processing"); + if(evt!=NULL) + msg+=": "+evt->getName(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex)) + throw; +} catch(...) { + observer[obsEventTranslatorComm]->AssertReady(); + std::string msg("Occurred during inter-process event processing"); + if(evt!=NULL) + msg+=": "+evt->getName(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL)) + throw; +} } void MMCombo::ReadySendJoints(const OReadyEvent& sysevent) { +try { if(isStopped) { //cout << "BAH!ReadySendJoints" << endl; @@ -472,10 +539,28 @@ ReadySendJoints(sysevent); } else //recursive base case subject[sbjMoveJoint]->NotifyObservers(); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during joint angle updates",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during joint angle updates",NULL)) + throw; +} } void MMCombo::GotSensorFrame(const ONotifyEvent& event){ +try { + erouter->processTimers(); +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL)) + throw; +} +try { // if(state && state->buttons[RFrPawOffset]) // cout << "SENSOR..."<(event.RCData(0)->Base()); state->read(rawsensor[0],erouter); - erouter->processTimers(); static unsigned int throwaway=1; //i thought the first few sensor updates might be flakey, but now i think not. But a good way to delay startup. if(throwaway!=0) { throwaway--; @@ -518,6 +602,16 @@ observer[obsSensorFrame]->AssertReady(); // if(state && state->buttons[RFrPawOffset]) // cout << "done" << endl; + +} catch(const std::exception& ex) { + observer[obsSensorFrame]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor update processing",&ex)) + throw; +} catch(...) { + observer[obsSensorFrame]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor update processing",NULL)) + throw; +} } void @@ -527,9 +621,17 @@ return; } +try { + erouter->processTimers(); +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL)) + throw; +} +try { PROFSECTION("GotImage()",state->mainProfile); - - erouter->processTimers(); WMvari(int, frame_counter, 0); ++frame_counter; @@ -538,13 +640,31 @@ erouter->postEvent(new DataEvent(reinterpret_cast(event.Data(0)),EventBase::visOFbkEGID,0,EventBase::statusETID)); erouter->postEvent(new DataEvent(reinterpret_cast(event.Data(0)),EventBase::visOFbkEGID,0,EventBase::deactivateETID)); - erouter->processTimers(); - observer[obsImage]->AssertReady(); + +} catch(const std::exception& ex) { + observer[obsImage]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera image processing",&ex)) + throw; +} catch(...) { + observer[obsImage]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera image processing",NULL)) + throw; +} +try { + erouter->processTimers(); +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL)) + throw; +} } void MMCombo::GotAudio(const ONotifyEvent& event){ +try { if(isStopped) { //cout << "BAH!GotAudio" << endl; return; @@ -554,10 +674,28 @@ for (int i = 0; i < event.NumOfData(); i++) { erouter->postEvent(new DataEvent(reinterpret_cast(event.Data(i)),EventBase::micOSndEGID,0,EventBase::statusETID)); - erouter->processTimers(); + try { + erouter->processTimers(); + } catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex)) + throw; + } catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL)) + throw; + } } observer[obsMic]->AssertReady(); + +} catch(const std::exception& ex) { + observer[obsMic]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during audio processing",&ex)) + throw; +} catch(...) { + observer[obsMic]->AssertReady(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during audio processing",NULL)) + throw; +} } void @@ -566,6 +704,16 @@ //cout << "BAH!GotPowerEvent" << endl; return; } +try { + erouter->processTimers(); +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL)) + throw; +} +try { // cout << "POWER..."<mainProfile); @@ -577,7 +725,6 @@ } const OPowerStatus* result = &static_cast(msg)->powerStatus; state->read(*result,erouter); - erouter->processTimers(); // this part watches to see if the power button is pressed to shutdown the robot // i'm leaving this low-level because there's not much else you can do anyway... // the hardware kills power to the motors, and as far as we can tell, you can't @@ -588,6 +735,14 @@ OPENR::Shutdown(bc); } // cout << "done" << endl; + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during power status update",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during power status update",NULL)) + throw; +} } void @@ -748,9 +903,17 @@ MMCombo::addRunLevel() { runLevel++; if(runLevel==readyLevel) { - cout << "START UP BEHAVIOR..." << flush; - ProjectInterface::startupBehavior().DoStart(); - cout << "START UP BEHAVIOR-DONE" << endl; + try { + cout << "START UP BEHAVIOR..." << flush; + ProjectInterface::startupBehavior().DoStart(); + cout << "START UP BEHAVIOR-DONE" << endl; + } catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during StartupBehavior construction and startup",&ex)) + throw; + } catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during StartupBehavior construction and startup",NULL)) + throw; + } } } diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/doxygencfg ./docs/doxygencfg --- ../Tekkotsu_2.4/docs/doxygencfg Sun Aug 7 00:11:04 2005 +++ ./docs/doxygencfg Tue Aug 16 14:57:19 2005 @@ -23,7 +23,7 @@ # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 2.4 +PROJECT_NUMBER = 2.4.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/doxygenhead.html ./docs/doxygenhead.html --- ../Tekkotsu_2.4/docs/doxygenhead.html Tue Jul 19 19:35:22 2005 +++ ./docs/doxygenhead.html Fri Aug 12 14:51:53 2005 @@ -25,15 +25,15 @@
Downloads
- Tutorials + Dev. Resources
Reference
- Credits + Credits - +
+ href="../development.html" target="_top">Dev. Resources @@ -46,7 +46,7 @@ style="vertical-align: top; background-color: rgb(0, 0, 0);">
+ href="../acknowledgments.html" target="_top">Credits
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/html/index.html ./docs/html/index.html --- ../Tekkotsu_2.4/docs/html/index.html Sun Aug 7 00:11:04 2005 +++ ./docs/html/index.html Fri Aug 12 14:52:52 2005 @@ -36,7 +36,7 @@ style="vertical-align: top; background-color: rgb(0, 0, 0);">
Tutorials
Credits
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/local/sim/Main.cc ./local/sim/Main.cc --- ../Tekkotsu_2.4/local/sim/Main.cc Wed Jul 6 18:53:10 2005 +++ ./local/sim/Main.cc Tue Aug 16 14:24:43 2005 @@ -64,6 +64,8 @@ void Main::DoStart() { +try { + Process::DoStart(); //These are constructed by other processes, so need to wait //until the construction runlevel is complete @@ -75,9 +77,19 @@ wireless_thread.start(); evtrecv=new MessageReceiver(*events,gotEvent,false); visrecv=new MessageReceiver(*cameraFrames,gotCamera,false); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStart",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStart",NULL)) + throw; +} } void Main::run() { +try { + ProjectInterface::startupBehavior().DoStart(); evtrecv->start(); @@ -89,9 +101,19 @@ evtrecv->finish(); ProjectInterface::startupBehavior().DoStop(); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",NULL)) + throw; +} } void Main::DoStop() { +try { + events->close(); delete visrecv; @@ -115,6 +137,14 @@ curimg->RemoveReference(); Process::DoStop(); + +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStop",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStop",NULL)) + throw; +} } bool Main::canManuallyAdvance() { @@ -164,6 +194,7 @@ bool Main::gotCamera(RCRegion* msg) { +try { if(msg==NULL) return true; msg->AddReference(); @@ -184,16 +215,39 @@ erouter->postEvent(new DataEvent(img,EventBase::visOFbkEGID,0,EventBase::statusETID)); erouter->postEvent(new DataEvent(img,EventBase::visOFbkEGID,0,EventBase::deactivateETID)); return isRealtime; +} catch(const std::exception& ex) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",&ex)) + throw; +} catch(...) { + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",NULL)) + throw; +} +return true; } bool Main::gotEvent(RCRegion* msg) { - EventBase* evt=EventTranslator::decodeEvent(msg->Base(),msg->Size()); +EventBase* evt=NULL; +try { + evt=EventTranslator::decodeEvent(msg->Base(),msg->Size()); if(evt==NULL) { cerr << "ERROR: Main::gotEvent() failed to decode message" << endl; return true; } erouter->postEvent(evt); - return true; +} catch(const std::exception& ex) { + std::string emsg("Occurred during inter-process event processing"); + if(evt!=NULL) + emsg+=": "+evt->getName(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),&ex)) + throw; +} catch(...) { + std::string emsg("Occurred during inter-process event processing"); + if(evt!=NULL) + emsg+=": "+evt->getName(); + if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),NULL)) + throw; +} +return true; } /*! @file diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/Makefile ./tools/Makefile --- ../Tekkotsu_2.4/tools/Makefile Tue Aug 9 21:58:36 2005 +++ ./tools/Makefile Tue Aug 16 17:11:04 2005 @@ -17,10 +17,14 @@ printf "Checking tool $$dir:\n"; \ $(MAKE) -C "$$dir" clean; \ if [ $$? -ne 0 ] ; then \ - exit $$?; \ + exit 1; \ fi; \ - $(MAKE) -C "$$dir" all; \ + $(MAKE) -C "$$dir"; \ if [ $$? -ne 0 ] ; then \ - exit $$?; \ + exit 1; \ + fi; \ + $(MAKE) -C "$$dir" test; \ + if [ $$? -ne 0 ] ; then \ + exit 1; \ fi; \ done diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/binstrswap/Makefile ./tools/binstrswap/Makefile --- ../Tekkotsu_2.4/tools/binstrswap/Makefile Sun Aug 24 17:19:21 2003 +++ ./tools/binstrswap/Makefile Tue Aug 16 16:47:42 2005 @@ -1,4 +1,4 @@ -.PHONY: all clean +.PHONY: all clean test all: binstrswap @@ -7,4 +7,6 @@ clean: rm -f binstrswap + +test: diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/easytrain/Makefile ./tools/easytrain/Makefile --- ../Tekkotsu_2.4/tools/easytrain/Makefile Thu Aug 4 16:58:05 2005 +++ ./tools/easytrain/Makefile Tue Aug 16 16:48:09 2005 @@ -9,7 +9,7 @@ SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi ) CXXFLAGS=-deprecation -classpath ".$(SEP)../mon/ftp.jar" -.PHONY: all clean msg build clearbuildlist +.PHONY: all clean msg build clearbuildlist test all: clearbuildlist build @@ -33,3 +33,6 @@ clean: rm -f $(OBJS) *~ + +test: + Binary files ../Tekkotsu_2.4/tools/easytrain/test2.png and ./tools/easytrain/test2.png differ diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/evenmodtime/Makefile ./tools/evenmodtime/Makefile --- ../Tekkotsu_2.4/tools/evenmodtime/Makefile Sun Aug 24 17:19:27 2003 +++ ./tools/evenmodtime/Makefile Tue Aug 16 16:48:11 2005 @@ -1,4 +1,4 @@ -.PHONY: all clean +.PHONY: all clean test all: evenmodtime @@ -7,4 +7,6 @@ clean: rm -f evenmodtime + +test: diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/filtersyswarn/Makefile ./tools/filtersyswarn/Makefile --- ../Tekkotsu_2.4/tools/filtersyswarn/Makefile Sun Aug 24 17:19:32 2003 +++ ./tools/filtersyswarn/Makefile Tue Aug 16 16:48:15 2005 @@ -1,4 +1,4 @@ -.PHONY: all clean +.PHONY: all clean test all: filtersyswarn @@ -7,4 +7,6 @@ clean: rm -f filtersyswarn + +test: diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/mipaltools/Makefile ./tools/mipaltools/Makefile --- ../Tekkotsu_2.4/tools/mipaltools/Makefile Thu Oct 9 15:51:28 2003 +++ ./tools/mipaltools/Makefile Tue Aug 16 16:48:15 2005 @@ -1,4 +1,4 @@ -.PHONY: all +.PHONY: all clean test all: StackedIt @@ -7,3 +7,6 @@ clean: make -C src clean + +test: + diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/mon/Makefile ./tools/mon/Makefile --- ../Tekkotsu_2.4/tools/mon/Makefile Thu Mar 31 16:54:08 2005 +++ ./tools/mon/Makefile Tue Aug 16 16:48:15 2005 @@ -14,7 +14,7 @@ SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi ) CXXFLAGS=-deprecation -classpath ".$(SEP)./ftp.jar$(SEP)./jargs.jar" -.PHONY: all clean build clearbuildlist +.PHONY: all clean build clearbuildlist test all: clearbuildlist build @@ -60,3 +60,6 @@ rm -f tmp_buildList.txt "$(AIBO3DCACHE)" find . -name "*.class" -exec rm \{\} \; find . -name "*~" -exec rm \{\} \; + +test: + diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/seg/Makefile ./tools/seg/Makefile --- ../Tekkotsu_2.4/tools/seg/Makefile Wed Oct 8 14:26:51 2003 +++ ./tools/seg/Makefile Tue Aug 16 16:48:15 2005 @@ -9,7 +9,7 @@ SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi ) CXXFLAGS=-deprecation -classpath ".$(SEP)../mon/ftp.jar" -.PHONY: all clean msg build clearbuildlist +.PHONY: all clean msg build clearbuildlist test all: clearbuildlist build @@ -33,3 +33,6 @@ clean: rm -f $(OBJS) *~ + +test: + diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/base64/Makefile ./tools/test/base64/Makefile --- ../Tekkotsu_2.4/tools/test/base64/Makefile Wed Jun 1 01:48:09 2005 +++ ./tools/test/base64/Makefile Tue Aug 16 16:13:22 2005 @@ -1,45 +1,49 @@ +# This Makefile will handle most aspects of compiling and +# linking a tool against the Tekkotsu framework. You probably +# won't need to make any modifications, but here's the major controls -#if you want to change the target model, it is recommended -#to set the TEKKOTSU_TARGET_MODEL environment variable +# Executable name, defaults to: +# `basename \`pwd\``-$(TEKKOTSU_TARGET_MODEL) +TEKKOTSU_TARGET_MODEL?=TGT_ERS7 +BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL))) -.PHONY: all tk +# Build directory +PROJECT_BUILDDIR:=build -# We use this TK_RT instead of TEKKOTSU_ROOT so things will -# still work if TEKKOTSU_ROOT is a relative path from some -# unknown project directory (and thus would be invalid from -# this subdirectory of 'tools') -TK_RT:=../../.. +# Source files, defaults to all files ending matching *$(SRCSUFFIX) +SRCSUFFIX:=.cc +PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)") -TEMPLATE_PROJECT:=$(TK_RT)/project +# We use a hard-coded TEKKOTSU_ROOT so this tool is always linked against the +# the framework directory which contains it +TEKKOTSU_ROOT=../../.. + +.PHONY: all test + +TEMPLATE_PROJECT:=$(TEKKOTSU_ROOT)/project TEKKOTSU_ENVIRONMENT_CONFIGURATION?=$(TEMPLATE_PROJECT)/Environment.conf -$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found. You may need to edit TK_RT in the Makefile)) +$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found. You may need to edit TEKKOTSU_ROOT in the Makefile)) TEKKOTSU_TARGET_PLATFORM:=PLATFORM_LOCAL -PROJECT_BUILDDIR:=build include $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) -FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(FILTERSYSWARN)) -COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(COLORFILT)) +FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(FILTERSYSWARN)) +COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(COLORFILT)) $(shell mkdir -p $(PROJ_BD)) -BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL))) - -SRCSUFFIX:=.cc - -PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)") - PROJ_OBJ:=$(patsubst ./%$(SRCSUFFIX),$(PROJ_BD)/%.o,$(PROJ_SRC)) LIBS:= $(TK_BD)/libtekkotsu.a $(TK_BD)/../Motion/roboop/libroboop.a $(TK_BD)/../Shared/newmat/libnewmat.a DEPENDS:=$(PROJ_OBJ:.o=.d) -CXXFLAGS=-g -Wall -O2 \ - -I$(TK_RT) \ +CXXFLAGS:=-g -Wall -O2 \ + -I$(TEKKOTSU_ROOT) \ + -I../../Shared/jpeg-6b $(shell xml2-config --cflags) \ -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) -all: tk $(BIN) +all: $(BIN) $(BIN): $(PROJ_OBJ) $(LIBS) @echo "Linking $@..." @@ -49,9 +53,6 @@ -include $(DEPENDS) endif -tk : - export TEKKOTSU_TARGET_PLATFORM=PLATFORM_LOCAL; $(MAKE) -C $(TK_RT) compile - %.a : @echo "ERROR: $@ was not found. You may need to compile the Tekkotsu framework." @echo "Press return to attempt to build it, ctl-C to cancel." @@ -74,5 +75,17 @@ test $$retval -eq 0; \ clean: - rm -rf $(BIN) $(PROJECT_BUILDDIR) *~ + rm -rf $(BIN) $(PROJECT_BUILDDIR) test-* *~ +test: $(BIN) + ./$(BIN) encode binary.gif > test-encoded_b64.txt + ./$(BIN) decode encoded_b64.txt > test-binary.gif + @for x in * ; do \ + if [ -r "test-$$x" ] ; then \ + if diff -u "test-$$x" "$$x" ; then \ + echo "Test '$$x' passed"; \ + else \ + echo "Test output '$$x' does not match ideal"; \ + fi; \ + fi; \ + done \ No newline at end of file diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/base64/base64.cc ./tools/test/base64/base64.cc --- ../Tekkotsu_2.4/tools/test/base64/base64.cc Wed Jun 1 01:48:09 2005 +++ ./tools/test/base64/base64.cc Tue Aug 16 15:37:11 2005 @@ -7,6 +7,7 @@ #include #include #include +#include using namespace std; using namespace minisim; @@ -14,7 +15,7 @@ int main(int argc, char** argv) { initialize(); - if(argc<2 || strcmp(argv[1],"encode") && strcmp(argv[1],"decode")) { + if(argc<3 || strcmp(argv[1],"encode") && strcmp(argv[1],"decode")) { cerr << "Usage: " << argv[0] << " (encode|decode) filename" << endl; exit(2); } @@ -34,7 +35,7 @@ exit(1); } unsigned int r=0; - while(r + numeric - fooF 3.1415927410125732421875 + fooF 3.1415927410125732 fooI 42 diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/plist/ideal-vision.event ./tools/test/plist/ideal-vision.event --- ../Tekkotsu_2.4/tools/test/plist/ideal-vision.event Thu Jul 28 13:10:38 2005 +++ ./tools/test/plist/ideal-vision.event Tue Aug 16 16:16:15 2005 @@ -1,5 +1,5 @@ - +