demo project

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

RobotArm.cpp

Committer:
henryrawas
Date:
2015-12-28
Revision:
5:36916b1c5a06
Parent:
4:36a4eceb1b7f
Child:
7:6723f6887d00

File content as of revision 5:36916b1c5a06:

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

#include <DynamixelBus.h>
#include <AX12.h>
#include <Terminal.h>
#include <vector>
#include <RobotArm.h>

using namespace std;

DynamixelBus dynbus( PTC17, PTC16, D7, D6, 1000000 );
Terminal* RobotArmPc = NULL;


// set the id for each part in the chain, in order
int PartIds[] = { 2, 3, 4, 6, 1 };

RobotArm::RobotArm()
{
    // build arm
    int i = 0;
    RobotArmPc->printf( "id[%d] = %d\r\n", i, PartIds[i]); 
    AX12* servo1 = new AX12( &dynbus, PartIds[i] );
    servo1->TorqueEnable(true);
    _armParts[i] = dynamic_cast<RobotNode*>(servo1);
    
    i++;
    RobotArmPc->printf( "id[%d] = %d\r\n", i, PartIds[i]);  
    AX12* servo2 = new AX12( &dynbus, PartIds[i] );
    servo2->TorqueEnable(true);
    _armParts[i] = dynamic_cast<RobotNode*>(servo2);
    
    i++;
    RobotArmPc->printf( "id[%d] = %d\r\n", i, PartIds[i]);  
    AX12* servo3 = new AX12( &dynbus, PartIds[i] );
    servo3->TorqueEnable(true);
    _armParts[i] = dynamic_cast<RobotNode*>(servo3);
    
    i++;
    RobotArmPc->printf( "id[%d] = %d\r\n", i, PartIds[i]);  
    AX12* servo4 = new AX12( &dynbus, PartIds[i] );
    servo4->TorqueEnable(true);
    _armParts[i] = dynamic_cast<RobotNode*>(servo4);
    
    i++;
    RobotArmPc->printf( "id[%d] = %d\r\n", i, PartIds[i]);  
    AX12* servo6 = new AX12( &dynbus, PartIds[i] );
    servo6->TorqueEnable(true);
    _armParts[i] = dynamic_cast<RobotNode*>(servo6);
    
    i++;
    _numParts = i;

    numsteps = 0;
    _stepms = 20; // move every 20 ms
}

// move all parts to specified postions in ms time
bool RobotArm::MoveArmPositions(vector<float> positions, int ms, int steps)
{
    _lastErrorPart = 0;
    
    GetArmLastPositions(lastpos);

    for( int ix = 0; ix < _numParts; ix++)
    {
        float difference = positions[ix]- lastpos[ix];
        differentials.push_back( difference );
    }

    if (steps > 1000) steps = 1000;
    if (ms <= 0) ms = 1;
    
    delayms = ms / steps;
    expDelay = delayms;
    
    elapseTimer.start();
    bool ok = true;
    
    // move arm to new position in steps
    for( int step = 1; step <= steps; step++)
    {
        //pc.foreground(Red);
        //pc.background(Black);
        //pc.locate( 0 , 24 );
        float incr = (float)step / (float)steps;
        for( int ix = 0; ix < _numParts; ix++ )
        {
            //pc.printf( "goal[%d] = %f\r\n", servoIndex, goal); 
            if (_armParts[ix]->HasAction(NA_Rotate))
            {
                float goal = lastpos[ix] + (differentials[ix] * incr);
                bool ok = _armParts[ix]->DoAction(NA_Rotate, goal);
                if (!ok)
                {
                    _lastErrorPart = ix;
                    break;
                }
            }
        }
        if (!ok)
            break;
        // adjust delay
        int elapsed = (int)elapseTimer.read_ms();
        expDelay += delayms;
        if (elapsed > expDelay && elapsed - expDelay < delayms)
            wait_ms(elapsed - expDelay);
        else
            wait_ms(delayms);
    }
    
    elapseTimer.stop();
    return ok;
}

// move all parts to specified postions in ms time
bool RobotArm::MoveArmPositionsStart(vector<float> positions, int totms)
{
    _lastErrorPart = 0;

    MoveArmPositionsEnd();
    GetArmPositions(lastpos);

    differentials.clear();
    for( int ix = 0; ix < _numParts; ix++)
    {
        float difference = positions[ix] - lastpos[ix];
        differentials.push_back( difference );
        RobotArmPc->printf( "diff %d = %f\r\n", ix, difference);
    }

    numsteps = totms / _stepms;
    if (numsteps == 0) numsteps = 1;

    curstep = 1;
    
    delayms = _stepms;
    
    elapseTimer.start();
    expDelay = (int)elapseTimer.read_ms() + delayms;
    
    return true;
}

bool RobotArm::MoveArmPositionsHasNext()
{
    return (curstep <= numsteps);
}

bool RobotArm::MoveArmPositionsNext(int& nextdelay)
{
    _lastErrorPart = 0;

    if (curstep > numsteps)
    {
        // no more steps 
        MoveArmPositionsEnd();
        return true;
    }
    
    bool ok = true;
    float incr = (float)curstep / (float)numsteps;
    lastgoals.clear();
    for( int ix = 0; ix < _numParts; ix++ )
    {
        if (_armParts[ix]->HasAction(NA_Rotate))
        {
            float goal = lastpos[ix] + (differentials[ix] * incr);
            lastgoals.push_back(goal);
            bool ok = _armParts[ix]->DoAction(NA_Rotate, goal);
            if (!ok)
            {
                _lastErrorPart = ix;
                break;
            }
        }
    }
    
    if (!ok)
    {
        return false;
    }
    
    curstep++;
    if (curstep > numsteps)
    {
        MoveArmPositionsEnd();
    }
    else
    {    
        // adjust delay
        int elapsed = (int)elapseTimer.read_ms();
    
        if (elapsed < expDelay)
        {
            if (expDelay - elapsed < delayms)
                nextdelay = expDelay - elapsed;
            else
                nextdelay = delayms;
        }
        else
        {
            // no delay before next step
            nextdelay = 0;
        }
        expDelay += delayms;
    }
    
    return true;
}

bool RobotArm::TestArmPosition(int& partix, float& diffpos)
{
    vector<float> curpos;
    GetArmPositions(curpos);
    for( int ix = 0; ix < _numParts; ix++ )
    {
        float diff = abs(curpos[ix]  - lastgoals[ix]);
        if (diff > abs(differentials[ix]) + allowance)
        {
            diffpos = diff;
            partix = ix;
            return false;
        }
    }
    return true;
}
    
bool RobotArm::MoveArmPositionsEnd()
{
    if (numsteps > 0)
    {
        elapseTimer.stop();
        numsteps = 0;
    }
    return true;
}

// move one part to specified postion in ms time
bool RobotArm::MovePartPosition(int partIx, float position, int ms, int steps)
{
    _lastErrorPart = 0;
    if (!_armParts[partIx]->HasAction(NA_Rotate))
        return false;
        
    float lastpos = _armParts[partIx]->GetLastMeasure(NM_Degrees);

    float difference = position- lastpos;

    if (steps > 1000) steps = 1000;
    if (ms <= 0) ms = 1;
    
    int delayms = ms / steps;
    
    bool ok = true;
    
    // move arm to new position in steps
    for( int step = 1; step <= steps; step++)
    {
        //pc.foreground(Red);
        //pc.background(Black);
        //pc.locate( 0 , 24 );
        float incr = (float)step / (float)steps;

        //pc.printf( "goal[%d] = %f\r\n", servoIndex, goal); 
        float goal = lastpos + (difference * incr);
        bool ok = _armParts[partIx]->DoAction(NA_Rotate, goal);
        if (!ok)
        {
            _lastErrorPart = partIx;
            break;
        }
            
        wait_ms(delayms);
    }
    return ok;
}

// get all parts positions
bool RobotArm::GetArmPositions(vector<float>& outPos)
{
    outPos.clear();
    for( int ix = 0; ix < _numParts; ix++)
    {
        float pos = _armParts[ix]->GetMeasure(NM_Degrees);
        outPos.push_back( pos );
    }
    return true;
}

// get all parts positions
bool RobotArm::GetArmLastPositions(vector<float>& outPos)
{
    outPos.clear();
    for( int ix = 0; ix < _numParts; ix++)
    {
        float pos = _armParts[ix]->GetLastMeasure(NM_Degrees);
        outPos.push_back( pos );
    }
    return true;
}

// get one part position
float RobotArm::GetPartPosition(int partIx)
{
    return _armParts[partIx]->GetMeasure(NM_Degrees);
}


// get all parts positions
bool RobotArm::GetArmMeasure(int measureId, vector<float>& outPos)
{
    outPos.clear();
    for( int ix = 0; ix < _numParts; ix++)
    {
        float pos = _armParts[ix]->GetMeasure(measureId);
        outPos.push_back( pos );
    }
    return true;
}

// get all parts positions
bool RobotArm::GetArmLastMeasure(int measureId, vector<float>& outPos)
{
    outPos.clear();
    for( int ix = 0; ix < _numParts; ix++)
    {
        float pos = _armParts[ix]->GetLastMeasure(measureId);
        outPos.push_back( pos );
    }
    return true;
}

// get one part position
float RobotArm::GetPartMeasure(int measureId, int partIx)
{
    return _armParts[partIx]->GetMeasure(measureId);
}

int RobotArm::GetNumParts()
{
    return _numParts;
}

void RobotArm::SetStepMs(int stepms)
{
    if (stepms > 0 && stepms < 5000)
        _stepms = stepms;
}

void RobotArm::SetThreadId(osThreadId tid)
{
    _tid = tid;
}

// get part by position
RobotNode* RobotArm::GetArmPart(int partIx)
{
    return _armParts[partIx];
}

unsigned char RobotArm::GetLastError()
{
    return _armParts[_lastErrorPart]->GetLastError();
}

int RobotArm::GetLastErrorPart()
{
    return _lastErrorPart;
}