martes, 28 de mayo de 2013

[UPDATED] A simple but pretty complete Linux C++ example for Bioloid

[Jun 12, 2013, Some source code typos fixed and code updated]:

.
.
.
.
.

[sourcecode language="cpp"]
bool nonValidOption(int option)
{
return (optionMaxOption);
}
[/sourcecode]

This is a very simple but pretty complete example, trying to use the least possible dependencies. I have tested in a just installed Ubuntu and you only needed the AXControl library (I created and use it because then there were no Robotis library and because it can use serial port, Dynamixel bus, Zigbee, BT (Robotis or other adaptors)

It use the terminal, no QT, to avoid library dependencies. But you should add the AXControl_v2 lib files to your /usr/lib folder as administrator (sudo). Click here if you want one unique executable for Linux (tested with Linux Mint 14) using these sources files

When executed, it shows the values configured in the HexaWheels.conf file and any problem it founds, like SerialPort2Dynamixel.open(ss)=> [Serial port NOT opened]:


ubuntu@A3820 ~/projects/trunk/bioloid/Herramientas/CommandLine $ ./commandline
init to load configuration(ss)=> [./HexaWheels.conf]
Configuration file=> (ss)=> [./HexaWheels.conf]
Tiempo_Espera_ms(ss)=> [35]
Tiempo_Espera_Sensores_ms(ss)=> [60]
Nombre_Puerto_Serie(ss)=> [/dev/ttyUSB0]
Baudios_Puerto_Serie(ss)=> [1000000]
Motion_File_Name(ss)=> [HexaWheels_2.0.mtn]
UmbralContacto(ss)=> [550]
UmbralDeteccion(ss)=> [200]
loadConfigurationValues: (si)=> [134529476]
getIntValue: (ss)=> [Tiempo_Espera_ms]
getIntValue: (ss)=> [Tiempo_Espera_Sensores_ms]
getIntValue: (ss)=> [Baudios_Puerto_Serie]
getStringValue: (ss)=> [Nombre_Puerto_Serie]


Device /dev/ttyUSB0, Speed B1000000
SerialPort2Dynamixel.open(ss)=> [Serial port NOT opened]
SerialPort2Dynamixel.open, serialPortName(ss)=> [/dev/ttyUSB0]
SerialPort2Dynamixel.open, baudRate(si)=> [4104]
I can't open DynamixelCommunication, name: (ss)=> [/dev/ttyUSB0]
terminate called after throwing an instance of 'std::exception*'
Aborted

If it can connect an there are no problem you should see:


ubuntu@A3820 ~/projects/trunk/bioloid/Herramientas/CommandLine $ ./commandline
init to load configuration(ss)=> [./HexaWheels.conf]
Configuration file=> (ss)=> [./HexaWheels.conf]
Tiempo_Espera_ms(ss)=> [35]
Tiempo_Espera_Sensores_ms(ss)=> [60]
Nombre_Puerto_Serie(ss)=> [/dev/ttyUSB0]
Baudios_Puerto_Serie(ss)=> [1000000]
Motion_File_Name(ss)=> [HexaWheels_2.0.mtn]
UmbralContacto(ss)=> [550]
UmbralDeteccion(ss)=> [200]
loadConfigurationValues: (si)=> [134529476]
getIntValue: (ss)=> [Tiempo_Espera_ms]
getIntValue: (ss)=> [Tiempo_Espera_Sensores_ms]
getIntValue: (ss)=> [Baudios_Puerto_Serie]
getStringValue: (ss)=> [Nombre_Puerto_Serie]


Device /dev/ttyUSB0, Speed B1000000
SerialPort2Dynamixel.open, serialPortName(ss)=> [/dev/ttyUSB0]
SerialPort2Dynamixel.open, baudRate(si)=> [4104]
V01
2.- Toggle AX-12 LED
3.- Query AX-12
4.- Move AX-12
5.- Torque AX-12
6.- Query CM-510 sensor
7.- Show menu
8.- Beep
9.- Quit
Select option (2-9)

[sourcecode language="cpp"]

/*------------------------------------------------------------------------------*\
* This source file is subject to the GPLv3 license that is bundled with this *
* package in the file COPYING. *
* It is also available through the world-wide-web at this URL: *
* http://www.gnu.org/licenses/gpl-3.0.txt *
* If you did not receive a copy of the license and are unable to obtain it *
* through the world-wide-web, please send an email to *
* siempre.aprendiendo@gmail.com so we can send you a copy immediately. *
* *
* @category Robotics *
* @copyright Copyright (c) 2011 Jose Cortes (<a href="https://plus.google.com/105007891378677151287/about">https://plus.google.com/105007891378677151287/about</a>) *
* @license http://www.gnu.org/licenses/gpl-3.0.txt GNU v3 Licence *
* *
\*------------------------------------------------------------------------------*/

#include "stdafx.h"
#include
#include "BasicSystem.h"
#include "Util.h"

using namespace std;

class UI
{
public:
static const int OptionQuit=8;

UI(MyBasicSystem::BasicSystem& aMySystem) : mySystem(aMySystem) {}

void showMenu();
int selectOption();
bool executeSelectedOption(int selected);
void doBeep();

private:
MyBasicSystem::BasicSystem mySystem;

static const int OptionSetLEDOnOff=1;
static const int OptionQueryAX12=2;
static const int OptionMoveAX12=3;
static const int OptionTorqueAX12=4;
static const int OptionQuerySensor=5;
static const int OptionShowMenu=6;
static const int OptionBeep=7;

static const int MinOption=OptionSetLEDOnOff;
static const int MaxOption=OptionQuit;

bool validRange(int value, int MinValue, int MaxValue);
bool nonValidOption(int option);
int getPosition();
int getId();
int getSensorPort();
void doGetPosition();
void doSetPosition();
void doQuerySensor();
void doSetLEDOnOff();
void doSetTorqueOnOff();

};

void UI::showMenu()
{
cout << "V02" << endl;

cout << OptionSetLEDOnOff << ".- Toggle AX-12 LED" << endl;
cout << OptionQueryAX12 << ".- Query AX-12" << endl;
cout << OptionMoveAX12 << ".- Move AX-12" << endl;
cout << OptionTorqueAX12 << ".- Torque AX-12" << endl;
cout << OptionQuerySensor << ".- Query CM-510 sensor" << endl;
cout << OptionShowMenu << ".- Show menu" << endl;
cout << OptionBeep << ".- Beep" << endl;
cout << OptionQuit << ".- Quit" << endl;
}

bool UI::nonValidOption(int option)
{
return (optionMaxOption);
}

int UI::selectOption()
{
int option=-1;

while (nonValidOption(option))
{
cout << "Select option (" << MinOption << "-" << MaxOption << ")" << endl; cin >> option;
if (nonValidOption(option))
{
cout << endl;
cout << endl;
cout << "(" << option << ") is NOT a valid option" << endl; } } return option; } bool UI::validRange(int value, int MinValue, int MaxValue) { return (value>=MinValue && value<=MaxValue);
}

int UI::getPosition()
{
int position=0;

do
{
cout << "Type a value between 0 and 1023 to set the AX-12 in that position" << endl; cin>>position;

}while(!validRange(position, 0, 1023));

cout << "Position:" << position << endl; return position; } int UI::getId() { int ax12Id=1; do { puts ("Type the ID of the AX-12 to use, a value between 1 and 18, "); cin >> ax12Id;

}while(!validRange(ax12Id, 1, 18));

cout << "AX12 Id:" << ax12Id << endl; return ax12Id; } int UI::getSensorPort() { int sensorPort=1; do { puts ("Type the sensor Port to read, a value between 1 and 6, "); cin >> sensorPort;

}while(!validRange(sensorPort, 1, 6));

cout << "Sensor Port number:" << sensorPort << endl;

return sensorPort;
}

void UI::doBeep()
{
cout << "Beep" << endl;
mySystem.dynamixelCommunication.sendOrder(100, AXS1_Buzzer, (byte) DO, (short) 500);
Sleep (2);
mySystem.dynamixelCommunication.sendOrder(200, MyCommunications::Beep, (byte) 5);
}

void UI::doGetPosition()
{
int ax12Id=getId();

int position = mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::PresentPosition);
cout << "the position is: [" << position << "] " << endl << endl << endl;
}

void UI::doSetPosition()
{
int ax12Id=getId();
int position=getPosition();

mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::GoalPosition,(short) position);

}

void UI::doQuerySensor()
{
int sensorPort=getSensorPort();

int value=mySystem.dynamixelCommunication.readSensorValue (200, ReadCM510SensorRaw, sensorPort);
cout << "the sensor reads: [" << value << "] " << endl << endl << endl;
}

void UI::doSetLEDOnOff()
{
byte lByte=0, hByte=0;
int ledValue;

int ax12Id=getId();

ledValue=mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::LED);
Hex::toHexHLConversion(ledValue, hByte, lByte);

bool onOff=false;
if (lByte!=0)
onOff=true;

cout << "The LED is: [" << (onOff?"on":"off") << "], putting it: [" << (onOff?"Off":"on") << "] " << endl << endl << endl;
mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::LED, byte(onOff?0:1));
}

void UI::doSetTorqueOnOff()
{
byte lByte=0, hByte=0;
int ax12Id=getId();

int torque=mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::Torque);
Hex::toHexHLConversion(torque, hByte, lByte);
bool onOff=(lByte!=0?true:false);

cout << "The Torque is: [" << (onOff?"on":"off") << "], putting it: [" << (onOff?"Off":"on") << "] " << endl << endl << endl;

mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::Torque,(byte) (onOff?0:1));
}

bool UI::executeSelectedOption(int option)
{
bool isOk=true;
cout << endl;
cout << endl;

cout << "Selected option: [" << option << "] " << endl;

switch(option)
{
case OptionSetLEDOnOff:
doSetLEDOnOff();
break;
case OptionQueryAX12:
doGetPosition();
break;
case OptionMoveAX12:
doSetPosition();
break;
case OptionTorqueAX12:
doSetTorqueOnOff();
break;
case OptionQuerySensor:
doQuerySensor();
break;
case OptionShowMenu:
showMenu();
break;
case OptionBeep:
doBeep();
break;
}

return isOk;
}

int _tmain(int argc, _TCHAR* argv[])
{
cout << "AXControl_v2_VS_CPP test v0" << endl;

bool quit=false;
MyBasicSystem::BasicSystem mySystem;
UI ui(mySystem);
do
{
ui.showMenu();
int selected=ui.selectOption();
if (selected==ui.OptionQuit)
quit=true;
ui.executeSelectedOption(selected);
}while (!quit);

mySystem.dynamixelCommunication.close();

return 0;
}

[/sourcecode]