====== Robotino Rectangle Tutorial ======
**This tutorial is part of the [[robotino_operation|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: {{dylanw:rect.zip}}
===== Videos =====
If you are not interested in learning about the code you can jump straight to the compile video
{{youtube>wy88DKn-6x4?large}}
The finished program running:
{{youtube>sw0jyGtzqhg?large}}
===== 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.
#define _USE_MATH_DEFINES
#include
#include
#include
#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.
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.
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.
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
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] <=_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.
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. [[:File: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 [[http://panic.com/transmit/|Transmit]] by Panic.
FTP username: robotino
FTP password: robotino
Now you are all set to follow the video tutorial!
{{youtube>wy88DKn-6x4?large}}
The finished program running:
{{youtube>sw0jyGtzqhg?large}}