demo project

Dependencies:   AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL

main.cpp

Committer:
henryrawas
Date:
2015-12-23
Revision:
4:36a4eceb1b7f
Parent:
2:37021fb3b45b
Child:
5:36916b1c5a06

File content as of revision 4:36a4eceb1b7f:

#include "mbed.h"
#include "rtos.h"

#include "EthernetInterface.h"
#include "mbed/logging.h"
#include "mbed/mbedtime.h"
#include <NTPClient.h>
#include <DynamixelBus.h>
#include <AX12.h>
#include <Terminal.h>
#include <vector>
#include <RobotArm.h>
#include <MeasureBuf.h>
#include <IothubRobotArm.h>
#include <ActionBuf.h>

using namespace std;

DigitalOut myled(LED_GREEN);
Terminal pc(USBTX, USBRX);

extern Terminal* RobotArmPc;
extern Terminal* AX12Pc;

const float UpPos = 150.0f;


void PushMeasurements(MeasureGroup measureGroup, int partSize, RobotArm robotArm)
{
    vector<float> lastVals;
    
    robotArm.GetArmMeasure(NM_Temperature, lastVals);
    pc.printf( "Temperatures: ");
    for( int servoIndex = 0; servoIndex < partSize; servoIndex++ )
    {
        pc.printf( "%d:%f ", servoIndex, lastVals[servoIndex]); 
    }
    pc.printf( "\r\n");
    measureGroup.SetMeasure(NM_Temperature, lastVals);
    MeasureBuf.push(measureGroup);
    
    robotArm.GetArmMeasure(NM_Voltage, lastVals);
    pc.printf( "Voltage: ");
    for( int servoIndex = 0; servoIndex < partSize; servoIndex++ )
    {
        pc.printf( "%d:%f ", servoIndex, lastVals[servoIndex]); 
    }
    pc.printf( "\r\n");
    measureGroup.SetMeasure(NM_Voltage, lastVals);
    MeasureBuf.push(measureGroup);
    
    robotArm.GetArmMeasure(NM_Degrees, lastVals);
    pc.printf( "Rotation: ");
    for( int servoIndex = 0; servoIndex < partSize; servoIndex++ )
    {
        pc.printf( "%d:%f ", servoIndex, lastVals[servoIndex]); 
    }
    pc.printf( "\r\n");
    measureGroup.SetMeasure(NM_Degrees, lastVals);
    MeasureBuf.push(measureGroup);
}


int setupRealTime(void)
{
    int result;

    (void)printf("setupRealTime begin\r\n");
    if (EthernetInterface::connect())
    {
        (void)printf("Error initializing EthernetInterface.\r\n");
        result = __LINE__;
    }
    else
    {
        (void)printf("setupRealTime NTP begin\r\n");
        NTPClient ntp;
        if (ntp.setTime("0.pool.ntp.org") != 0)
        {
            (void)printf("Failed setting time.\r\n");
            result = __LINE__;
        }
        else
        {
            (void)printf("set time correctly!\r\n");
            result = 0;
        }
        (void)printf("setupRealTime NTP end\r\n");
        EthernetInterface::disconnect();
    }
    (void)printf("setupRealTime end\r\n");

    return result;
}

int InitEthernet()
{
    (void)printf("Initializing mbed specific things...\r\n");

        /* These are needed in order to initialize the time provider for Proton-C */
    mbed_log_init();
    mbedtime_init();

    if (EthernetInterface::init())
    {
        (void)printf("Error initializing EthernetInterface.\r\n");
        return -1;
    }

    if (setupRealTime() != 0)
    {
        (void)printf("Failed setting up real time clock\r\n");
        return -1;
    }

    if (EthernetInterface::connect())
    {
        (void)printf("Error connecting EthernetInterface.\r\n");
        return -1;
    }
    
    return 0;
}


vector<float> upPositions;
vector<float> homePositions;

void MakeDemoSeq(vector<ActionSequence>& actions)
{
    // define actions
    ActionSequence moveUp(SA_SetGoal, upPositions, 3000);
    ActionSequence report(SA_Status);
    ActionSequence pause(SA_Delay);
    pause.SetDelay(5000);
    ActionSequence moveDown(SA_SetGoal, homePositions, 3000);
    ActionSequence rep(SA_Repeat);  

    // add actions into a sequence
    actions.push_back(moveUp);
    actions.push_back(report);
    actions.push_back(pause);
    actions.push_back(moveDown);
    actions.push_back(report);
    actions.push_back(pause);
    actions.push_back(rep);
}


enum MainStates
{
    MS_Idle           = 0x0,
    MS_Running        = 0x1,
    MS_Paused         = 0x2,
    MS_Stopping       = 0x3,
    MS_Error          = 0x4,
    MS_CancelOne      = 0x5,
    MS_CancelAll      = 0x6,
    MS_CancelToM      = 0x7
};

Queue<vector<ActionSequence>, 16> SequenceQ;
MainStates MainState;
bool RunInSequence;
bool RunInMoveStep;
bool RunInDelay;
void* CancelToMatch;


// run sequence thread timer routine
void NextSeq(void const * tid)
{
    RunInDelay = false;
    osSignalSet((osThreadId)tid, AS_Action);
}

void run()
{
    // init robot arm
    RobotArm robotArm;
    
    int partSize = robotArm.GetNumParts();

    for( int servoIndex = 0; servoIndex < partSize; servoIndex++)
    {
        upPositions.push_back(UpPos);
    }
    
    // set running state
    MainState = MS_Idle;
    RunInSequence = false;
    RunInMoveStep = false;
    RunInDelay = false;
     
    // get initial positions
    MeasureGroup measureGroup;
    robotArm.GetArmPositions(homePositions);
    
    vector<float> lastVals;
    
    // do inital status report
    PushMeasurements(measureGroup, partSize, robotArm);
    SendIothubMeasurements();
 
    // Prepare main thread
    osThreadId mainTid = osThreadGetId();
    int32_t signals = AS_Action;
    
    // create a sequence for demo
    vector<ActionSequence> actions;
    MakeDemoSeq(actions);
    
    // add to queue
    SequenceQ.put(&actions);
    
    // state for sequence
    vector<ActionSequence> *curseq = NULL;
    int curseqIx = 0;

    // signal to run the default action for demo
    osSignalSet(mainTid, AS_Action);
    
    RtosTimer delayTimer(NextSeq, osTimerOnce, (void *)osThreadGetId());    
    
    MainState = MS_Running;
    
    while( true )
    {
        osEvent mainEvent = osSignalWait(signals, osWaitForever);
        
        switch (MainState)
        {
            case MS_Idle:
                break;
                
            case MS_Paused:
                pc.printf( "Paused\r\n"); 
                break;
                
            case MS_Stopping:
                pc.printf( "Stopping\r\n"); 
                break;
                
            case MS_Error:
                pc.printf( "Error\r\n"); 
                break;
                
            case MS_CancelOne:
                pc.printf( "Cancel sequence\r\n"); 
                RunInSequence = false;
                RunInMoveStep = false;
                if (RunInDelay)
                {
                    RunInDelay = false;
                    delayTimer.stop();
                }
                MainState = MS_Running;
                osSignalSet(mainTid, AS_Action);
                break;
                
            case MS_CancelAll:
                RunInSequence = false;
                RunInMoveStep = false;
                if (RunInDelay)
                {
                    RunInDelay = false;
                    delayTimer.stop();
                }
                while (1) {
                    osEvent evt = SequenceQ.get(0);
                    if (evt.status != osEventMessage)
                        break;
                }
                MainState = MS_Running;
                break;
                
            case MS_CancelToM:
                RunInSequence = false;
                RunInMoveStep = false;
                if (RunInDelay)
                {
                    RunInDelay = false;
                    delayTimer.stop();
                }
                while (1) {
                    osEvent evt = SequenceQ.get(0);
                    if (evt.status != osEventMessage)
                        break;
                    else if (evt.value.p == CancelToMatch)
                    {
                        curseq = (vector<ActionSequence> *)evt.value.p;
                        curseqIx = 0;
                        RunInSequence = true;
                    }
                }
                MainState = MS_Running;
                osSignalSet(mainTid, AS_Action);
                break;
                
            case MS_Running:
                if (RunInDelay)
                {
                    // waiting for timer to fire. do nothing
                    break;
                }
                if (!RunInSequence)
                {
                    osEvent evt = SequenceQ.get(0);
                    if (evt.status == osEventMessage)
                    {
                        pc.printf( "New Seq \r\n"); 
                        curseq = (vector<ActionSequence> *)evt.value.p;
                        curseqIx = 0;
                        RunInSequence = true;
                        RunInMoveStep = false;
                    }
                }
                
                if (RunInSequence)
                {
                    if (RunInMoveStep)
                    {
                        if (robotArm.MoveArmPositionsHasNext())
                        {
                            //pc.printf( "Next Step\r\n");
                            int delaystep = 0;
                            bool ok = robotArm.MoveArmPositionsNext(delaystep);
                            if (ok)
                            {
                                if (delaystep > 0)
                                {
                                    RunInDelay = true;
                                    delayTimer.start(delaystep);
                                }
                                else
                                    osSignalSet(mainTid, AS_Action);
                            }
                        }
                        else
                        {
                            pc.printf( "No more Step\r\n");
                            RunInMoveStep = false;
                        }
                    }
                    if (!RunInMoveStep)
                    {
                        pc.printf( "Next Seq %d\r\n", curseqIx); 
            
                        if (curseq != NULL)
                        {
                            ActionSequence aseq = (*curseq)[curseqIx];
                            curseqIx++;
                            
                            bool ok;
                            switch (aseq.ActionType)
                            {
                                case SA_SetGoal:
                                    pc.printf( " - Move arm start\r\n"); 
                                    ok = robotArm.MoveArmPositionsStart(aseq.GoalVals, aseq.Ms);
                                    if (ok)
                                    {
                                        RunInMoveStep = true;
                                        osSignalSet(mainTid, AS_Action);
                                    }
                                    else
                                    {
                                        // TODO: send alert
                                    }
                                    break;
                                case SA_Delay:
                                    pc.printf( " - Delay\r\n");
                                    RunInDelay = true;
                                    delayTimer.start(aseq.Ms);
                                    break;

                                case SA_Status:
                                    pc.printf( " - Status\r\n"); 
                                    robotArm.GetArmPositions(lastVals);
                                    
                                    PushMeasurements(measureGroup, partSize, robotArm);
                             
                                    SendIothubMeasurements();
            
                                    osSignalSet(mainTid, AS_Action);
                                    break;
                                case SA_Repeat:
                                    pc.printf( " - Repeat\r\n"); 
                                    curseqIx = 0;
                                    osSignalSet(mainTid, AS_Action);
                                    break;
                                    
                            }
                        }
                        
                        if (curseqIx >= curseq->size())
                        {
                            RunInSequence = false;
                        }
                    }
 
                }
                break;
        }

    }
}

int main()
{
    pc.baud(115200); 

    pc.cls();
    pc.foreground(Yellow);
    pc.background(Black);

    pc.locate( 0, 0 );
    pc.printf("**********************\r\n");
    pc.printf("RobotArmDemo start\r\n");
    pc.printf("**********************\r\n");

    pc.foreground(Teal);
    pc.background(Black);

    InitEthernet();
    
    // start IotHub connection
    StartIothubThread();
    
    // time delay is to allow the position encoders to come online after initial power supply event ~ 5 secs
    // and to allow IoTHub SSL connection established
    // TODO: test for connection established
    Thread::wait(15000);
    
    pc.printf( "Initialization done. Ready to run. \r\n");

    RobotArmPc = &pc;
    AX12Pc = &pc;
    
    run(); 

}