User Tools

Site Tools


robotino_rectangle

Robotino Rectangle Tutorial

This tutorial is part of the Robotino Operation series.

Purpose: to explain how to write a basic robotino program using robotino api2, compile and run it. The program written in this tutorial will take in user specified rectangle and drive around it's perimeter.

Downloads

The completed project ready to upload via ftp: rect.zip

Videos

If you are not interested in learning about the code you can jump straight to the compile video

The finished program running:

Writing the code

boiler plate:

Below is a basic boiler plate for your robotino program. It includes some basic c libraries. More importantly, it includes the api2 library.

boilerplate.cpp
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <stdlib.h>
 
#include "rec/robotino/api2/all.h"    // include the api2 library
 
using namespace rec::robotino::api2;   // we are going to be operating in the api2 namespace for this tutorial
 
float _rect[2]= {0,0};   // this is going to be the size of the rectangle our robotino will drive in.
 
bool _run = true;

Overriding the com class

The API2 com class allows us to communicate with the robotino's microcontroller. It has several virtual functions that we will need to overwrite in order to use it.

MyCom.h
class MyCom : public Com
{
    public:
	MyCom()
  		: Com( "rect" )      //  name our com after our program
  	{
  	}
 
  /*
  ** below we deal with the virtual functions.  for our purposes a simple cout will suffice
 */
 
  	void errorEvent( const char* errorString )
  	{
  		std::cerr << "Error: " << errorString << std::endl;    // remember we are using namespace::api2 so we need to type std:: to access cout and cerr
  	}
 
  	void connectedEvent()
  	{
  		std::cout << "Connected." << std::endl;
  	}
 
  	void connectionClosedEvent()
  	{
  		std::cout << "Connection closed." << std::endl;
  	}
 
  	void logEvent( const char* message, int level )
  	{
  		std::cout << message << std::endl;
  	}
 
  	void pingEvent( float timeMs )
  	{
  		std::cout << "Ping: " << timeMs << "ms" << std::endl;
  	}
};

Setting up our bumper

Once again we need to override a built in API2 class. We want to tell the robotino to stop when the bumper has contact with something.

MyBumper.h
class MyBumper : public Bumper
{
    public:
  	MyBumper()
  		: bumped( false )
  	{
  	}
 
  	void bumperEvent( bool hasContact )
  	{
  		bumped |= hasContact;
  		std::cout << "Bumper has " << ( hasContact ? "contact" : "no contact") << std::endl;
  	}
 
  	bool bumped;
};

Declare instances of our classes:

Now declare instances of the classes you created and an instance of OmniDrive.

 MyCom com;
 OmniDrive omniDrive;
 MyBumper bumper;

init() function:

The init function will be used to set up our robotino when the user launches our executable.

init.cpp
void init( const std::string& hostname )
{
    // Initialize the actors
 
    // Connect
    std::cout << "Connecting... ";
    com.setAddress( hostname.c_str() );
 
    com.connectToServer( true );
 
    if( false == com.isConnected() )
    {
        std::cout << std::endl << "Could not connect to " << com.address() << std::endl;
 
  	rec::robotino::api2::shutdown();
  	exit( 1 );
  }
 
  else
  {
       // if everything goes alright we say success and ask the user the size of the rectangle to trace
       std::cout << "success" << std::endl;
 
       std::cout << "enter rectange x in mm:" << std::endl;    
 
       std::cin >> _rect[0];     // just use std:cin to take in the size of the rectangle.
 
       std::cout << "enter rectange y in mm:" << std::endl;
 
       std::cin >> _rect[1];
 
  }
}

Driving the robotino

The drive() function will be used to move the robotino around using the omniDrive class

drive.cpp
void drive()
{
    float vel[2] = {0.1, 0.0};    // create an array to store our velocity
    float pos[2] = {0,0};          // create an array to store our position
 
    float lastTime=com.msecsElapsed();    // remember last time to measure change in time to calculate position
 
    while( com.isConnected() && false == bumper.value() && _run )
    {
        pos[0]=vel[0]*(com.msecsElapsed()-lastTime)+pos[0];   // update the position
        pos[1]=vel[1]*(com.msecsElapsed()-lastTime)+pos[1];
        std::cout << "Pos:" << pos[0] << "," << pos[1] <<std::endl;   //  print out the position.\
  
  	omniDrive.setVelocity( vel[0], vel[1], 0 );   // set the x and y velocity to our velocity setting set rotational velocity to 0
 
        if(pos[0]>=_rect[0] && pos[1] <= 0){    // this if statement changes the velocity when we reach the first corner of our rectange
            vel[0]=0;
            vel[1]=.1;
        }
 
        if(pos[0]>=_rect[0] && pos[1] >= _rect[1]){   // second corner 
            vel[0]=-0.1;
            vel[1]=0;
        }
 
        if(pos[0]<=0 && pos[1] >= _rect[1]){  // third corner 
            vel[0]=0;
             vel[1]=-0.1;
        }
 
        if(pos[0]<=0 && pos[1] <= 0){  // back to start location
            vel[0]=0.1;
            vel[1]=0;
        }
 
        lastTime=com.msecsElapsed();   // reset the last time variable
        com.processEvents();   // sincronizes the com class and the onboard computer
 	rec::robotino::api2::msleep( 100 );   // wait 100 ms
    }
}

Destroy:

when we are ready to quit we want to run destroy

void destroy()
{
    com.disconnectFromServer();   // simply disconnect the com
}

main program

Now we just need to write our main function to call the functions written above in the proper order.

main.cpp
int main( int argc, char **argv )
{
 
    std::string hostname = "172.26.1.1";  // set our local hostname of our microcontroller
 
    if( argc > 1 )   // boiler plate stuff
    {
  	hostname = argv[1];    
    }
 
    try   // try to run our functions
    {
  	init( hostname );   // these functions explained above
  	drive(); 
  	destroy();
    }
 
    // below we catch any errors that cropped up
    catch( const rec::robotino::api2::RobotinoException& e )
    {
  	std::cerr << "Com Error: " << e.what() << std::endl;
    }
    catch( const std::exception& e )
    {
  	std::cerr << "Error: " << e.what() << std::endl;
    }
    catch( ... )
    {
  	std::cerr << "Unknow Error" << std::endl;
    }
 
  rec::robotino::api2::shutdown();  // shut down API2
}
Compiling

In order to compile your program on your robotino you will need a CMakeLists.txt file. I have included it above for download. rect.zip

Create a folder on your robotino.

mkdir ~/dasl_tutorials/rect

switch to that directory

cd ~/dasl_tutorials/rect

On your pc put main.cpp document and your CMakeLists.txt file into a folder called src. Upload your src file to ~/dasl_tutorials/rect using your favorite ftp. My personal favorite is Transmit by Panic.

FTP username: robotino FTP password: robotino

Now you are all set to follow the video tutorial!

The finished program running:

robotino_rectangle.txt · Last modified: 2016/10/25 15:02 by dwallace