Ryan Lober

Introduction

In this guide we will show you how to get OCRA and it’s iCub plugins installed and running as well as write our very first client. For an overview on how OCRA works and the server-client paradigm please check out this article: [link].

Installation

With iCub, installing OCRA is a snap thanks to the codyco-superbuild. First you need to follow their installation instructions depending on your particular platform. For now OCRA for iCub has only been tested on OSX (see Eigen 3.3 Warning below) and Linux, so Windows users be aware that you may have significant difficulty getting everything working.

Assuming all of the codyco-superbuild dependencies are installed you have cloned codyco-superbuild somewhere, all that remains is to run the following:

cd [path_to_where_you_cloned_superbuild]/codyco-superbuild
mkdir build
cd build/
cmake .. -DCODYCO_BUILD_OCRA_MODULES=1
make

Once superbuild completes you are all set. If you already have built codyco-superbuild, just run the cmake command above and rebuild everything.

Warning about Eigen 3.3

The latest release of the linear algebra library Eigen is currently incompatible with OCRA and if you have it installed then you will need to remove it and replace it with 3.2.X. We are working on a fix.

Test the install

To test OCRA on iCub we need to open a few terminals…

Terminal 1

yarpserver --write

Terminal 2

cd [path_to_where_you_cloned_icub_gazebo]/icub-gazebo/world
gazebo icub.world

Terminal 3

ocra-icub-server --floatingBase --taskSet wholeBodyTaskSet

If all goes well you should see the the following output in Terminal 3

[photo here]

and the robot should not move. Hurray!

Launching a client

Assuming that your controller-server is still running from the installation test, we can now launch a client to see the robot actually move.

Terminal 4

example-client

You should see the left hand start to move in a square pattern. If this is the case then you are all ready to build your own client, but first, be sure to ctrl+c the example-client.

Creating your own clients

With OCRA and iCub, creating your own controller clients is easy-peasy. First, navigate to where you would like to build your client project. Then all that is left is to pick a snazzy client name, like, “hello-world”, and use the icub-client-generator to scaffold out the project for you.

cd /home/user_name/ocra_clients/
icub-client-generator hello-world

You should get the following output:

Scaffolding client code for: hello-world
-- Client class will be named: HelloWorldClient

iCub client structure

When you create a new client project you will automatically have the following project structure:

hello-world/
├── CMakeLists.txt
├── build
├── cmake
│   └── Modules
│       └── AddUninstallTarget.cmake
├── include
│   └── hello-world
│       └── HelloWorldClient.h
└── src
    ├── HelloWorldClient.cpp
    └── main.cpp

This is compilable “as is” but won’t do anything until you fill in the functionality. To make sure that your cmake paths are correct run,

cd hello-world/build
cmake ..
make 

If everything builds, then we are good. Otherwise you probably are missing some environment variables from the codyco-superbuild installation steps.

Now the bread and butter of the clients are the inherited iCubClient classes, which in this case is simply, HelloWorldClient.cpp and HelloWorldClient.h. This is where we will make our changes.

Make a reaching movement

So for our first client we simply want the iCub to reach down towards the floor with its right hand. To do so we will need to control the RightHandCartesian task which was added by the wholeBodyTaskSet.xml, and make a trajectory for it to follow. These two objectives are made easy by TaskConnection and TrajectoryThread.

HelloWorldClient.h

#ifndef HELLOWORLDCLIENT_H
#define HELLOWORLDCLIENT_H

#include <ocra-icub/IcubClient.h>
#include <ocra-recipes/TrajectoryThread.h>
#include <ocra-recipes/ControllerClient.h>


class HelloWorldClient : public ocra_recipes::ControllerClient
{
DEFINE_CLASS_POINTER_TYPEDEFS(HelloWorldClient)

public:
    HelloWorldClient (std::shared_ptr<ocra::Model> modelPtr, const int loopPeriod);
    virtual ~HelloWorldClient ();

protected:
    virtual bool initialize();
    virtual void release();
    virtual void loop();

private:
    ocra_recipes::TaskConnection::Ptr rightHandTask;
    ocra_recipes::TrajectoryThread::Ptr rightHandTrajectory;
};


#endif // HELLOWORLDCLIENT_H

Code explained

HelloWorldClient.cpp

#include "hello-world/HelloWorldClient.h"
HelloWorldClient::HelloWorldClient(std::shared_ptr<ocra::Model> modelPtr, const int loopPeriod)
: ocra_recipes::ControllerClient(modelPtr, loopPeriod)
{
    // add your code here...
}

HelloWorldClient::~HelloWorldClient()
{
    // add your code here...
}

bool HelloWorldClient::initialize()
{
    // Set the task name
    std::string rightHandTaskName("RightHandCartesian");

    // Create the TaskConnection to communicate with the right hand task
    rightHandTask = std::make_shared<ocra_recipes::TaskConnection>(rightHandTaskName);

    // Get the current position of the right hand task frame
    Eigen::Vector3d rightHandStartPosition = rightHandTask->getTaskState().getPosition().getTranslation();

    // Make an end position for the right hand which is the same as the start position but with the "z" component 30cm above the ground.
    Eigen::Vector3d rightHandEndPosition = rightHandStartPosition;
    rightHandEndPosition(2) = 0.3;

    // Create the right hand TrajectoryThread
    rightHandTrajectory = std::make_shared<ocra_recipes::TrajectoryThread>(10, rightHandTaskName, rightHandEndPosition, ocra_recipes::TRAJECTORY_TYPE::MIN_JERK, ocra_recipes::TERMINATION_STRATEGY::REVERSE_STOP);

    rightHandTrajectory->start();

    return true;
}

void HelloWorldClient::release()
{
    // add your code here...
}

void HelloWorldClient::loop()
{
    // When the trajectory thread is finshed, stop the client and close.
    if (!rightHandTrajectory->isRunning()) {
        std::cout << "Closing the hello-world client." << std::endl;
        stop()
    }
}

Code explained