Archive

Workshop: Programming a Bioloid robot workbench using C# and C++

This entry is part 1 of 6 in the series Bioloid Workshop

[Next post: Dynamixel communications with C#]

It would be a workshop using C# .Net and C++ with Qt 5. The code presented here is used in this two different robots and boards, a HP 214 Ipaq with Windows Mobile and a Raspberry Pi, using the Robotis CM-510 as the servo and sensors controller:

These will be the first steps, using C# and .Net , here the code and the exe for the Workbench UI:

Bioloid Workbench

Using this enhaced Toss Mode that adds some new functions.  Some of them:

Read more

Workshop: USB, serial and remote communications with C#

This entry is part 2 of 6 in the series Bioloid Workshop

[Previous post: Workshop: Dynamixel communications with C#]

Bioloid SerialPort2Dynamixel C#

Bioloid SerialPort2Dynamixel C#

SerialPort2Dynamixel

Encapsulating  the SerialPort .Net class offers an easy way to use the serial port and receive Dynamixel Zig messages with the Dynamixel protocol.

.

.

Collaborator classes:

Bioloid SerialPort2Dynamixel C# Collaborators

Bioloid SerialPort2Dynamixel C# Collaborators

– The SerialPort .Net class.

RCDataReader class, which unpack the Dynamixel Zigbee sequence offering the clean data received.

Operations:

The public interface that others classes will use offers principally these operations:

public void setRemoteControlMode(bool on), which sets on or off the reception of data


public void setRemoteControlMode(bool on)
{
if (on)
setReceiveDataMethod(rdDataReader.rawRemoteDataReceived);
else
setReceiveDataMethod(null);
}

public void setReceiveDataMethod(remoteControlDataReceived rcDataReceived), that sets the method that will be called when serial port data is received.

And some basics serial port data operations:

Raspberry Pi - USB2Dynamixel - CM510

Raspberry Pi – USB2Dynamixel – CM510

public bool open(String com, int speed), to open the serial port which name is in the com parameter. Wireless communications and USB ports, as used by Zig or USB2Dynaniel, are also serial ports  (COM1, COM2, … or /ttyUSB0, ttyUSB1).

public void close(), it will do nothing if the port is already closed.

public byte[] query(byte[] buffer, int pos, int wait), send (write) a query and gets (read) the result.

public void rawWrite(byte[] buffer, int pos), well… it will write whatever contains the buffer in the first pos positions

public byte[] rawRead() , read and returns the data received.

Notes:

To avoid concurrency problems all the operations that use the Dynamixel bus are protected with a Mutex object that avoids that two or more concurrent objects use SerialPort2Dynamixel simultaneously entering the same operation or using the same resources, like variables, objects or the Dynamixel bus.

Xevel USB2AX

Xevel USB2AX

USB2AX over USB2DYNAMIXEL

USB2AX over USB2DYNAMIXEL

RCDataReader

Bioloid RCDataReader C#

Bioloid RCDataReader C#

Remote communications

RemoteCommunications

Its responsability is to receive the Dynamixel Zig packets and extract the data.

Collaborator class:

– The ZigSequence enum, with the Dynamixels protocols data sections

RC-100 packet

RC-100 packet

Operations:

Robotis RC-100 remote controller values

Robotis RC-100 remote controller values

public void rawRemoteDataReceived(byte[] rcData), receives the Zigbee data.

public int getValue(), returns the last value received

C++, Bioloid and Raspberry Pi (v0.2)

This entry is part 3 of 6 in the series Bioloid Workshop

[V.02 updates: AX C++ architecture, core classes diagram and HexaWheels scanning video]

Why C++, Bioloid and Raspberry Pi?

TCPL4thEnglishC++, specially with the great improvements of the last C++11 standard, joins together a great efficiency in performance and a low memory footprint with advanced high level language features, making C++ a great tool for embedding, robotics, programming.

If you want to know how to use C++ very efficiently these two guides will help you:

The JSF air vehicle C++ coding standards ( F-35 fighter aircraft)

– ISO C++ committee’s report on performance

.

.

Bioloid Premium

Bioloid Premium

Bioloid Premium is a wonderful kit for creating legged and wheeled robots, including (here full parts list):

– 18 powerful and versatile AX-12 servos

– an ATMega 2561 (CM-510) or, recently, an ARM STM32F103RE 32bits (CM-530), based controller. Also you can control the AX-12 with the USB2Dynamixel straight from your USB with a FTDI driver.

– And a lot of parts to create the structure of the robot

.

RaspberryPi

RaspberryPi

Raspberry Pi is the cheaper and more brilliant conceived SBC (more specifications here):

– Broadcom BCM2835 SoC full HD multimedia applications processor

– 700 MHz Low Power ARM1176JZ-F Applications Processor

– Dual Core VideoCore IV® Multimedia Co-Processor

– 256/512 MB SDRAM

One simple example:

Learning C++


Starting:

C++ is a very powerful but complex programming language, so I think that the better approach is to start step by step, from the most easy features (yes, C++ could be used in an easy way) to the most advanced features it offers. What is C++? I will quote (I try to not explain anything that already is explained), Stroustrup, “his father”, from his book The C++ programming language 3th Edition:

“C++ is a general-purpose programming language with a bias towards systems programming that
– is a better C,
– supports data abstraction,
– supports object-oriented programming, and
– supports generic programming.”

And wikipedia:

C++ (pronounced “see plus plus”) is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features.[3] Developed by Bjarne Stroustrup starting in 1979 at Bell Labs, it adds object oriented features, such as classes, and other enhancements to the C programming language.

Web resources:

If you want more C++ links, these found at JUCE will help you.

Programming -- Principles and Practice Using C++Programming -- Principles and Practice Using C++

Programming — Principles and Practice Using C++

Free books and documents:

– Maintain stability and compatibility with C++98 and possibly with C;
– Improve C++ to facilitate systems and library design, rather than to introduce new features useful only to specific applications;
– Increase type safety by providing safer alternatives to earlier unsafe techniques;
– Increase performance and the ability to work directly with hardware

Books:

Advancing:

In robotics, and embedded programming in general, we will need some advanced knowledge and practices to reach our goals.

Free books and documents:

  • Concurrent programming, threading Our robots we will need to do several actions simultaneously, like perceiving the world with several sensors, moving and deciding what to do to reach is objectives.
  • Communications, the serial port communications functions are used for wireless and wired connections, and we will need to communicate between controllers and with sensors and servos.

Books:

C++ robotics programming

Well, this is really the goal, robotics programming.

As this is a workshop it will follow the creation of the the walker and vehicle Hexapod showed above in the video. This is currently the core architecture and the HexaWheels module (namespace classes):

AX C++ architecture v2

AX C++ architecture v2

And these are the core classes:

todo_signatura

The workshop will include:

– Basics

Like communications with serial port and wireless, using Dynamixels, sensors, … Language features for robotics, like asynchronous communications and threads and… delays!.

– Intermediate

Combination of basics features using sensors (like scanning) and servos (walking motions). For example, scanning with a DMS sensor:

As a simple example:

– Advanced

Advanced perception and behaviours

I think this could very funny, using an advanced sensor like Asus Xtion, to detect certain objects to interact, and create configurable and amusing behaviours.

CM-510 mirocontroller programming

– Tools:

PC, Raspberry Pi and Pandaboard, installation and configuration, tool and projects

– GNU C++, Boost
– Eclipse
– QT 5

The contents will come soon, very soon…

So… let’s the Bioloid, C++ and QT games start!

This entry is part 4 of 6 in the series Bioloid Workshop

To cretate this workshop I’m using Ubuntu 12.04, GNU g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 (see Synaptic installer capture),

Synaptic G++

Synaptic G++

QT 5.0.1 and QT creator 2.6.2,

QT creator is a very easy, and good, free IDE with a great design tool for creating user interfaces:

Be careful with this bug: Qt Creator 2.0: UI layout is not updated before launching the application http://qt-project.org/forums/viewthread/292 Is very annoying and time consuming, the solution is in the last comment (setting the UI_DIR in the .pro file)

QTCreator Bioloid QTWorkshop

QTCreator Bioloid QTWorkshop

I also will use it with Windows 7.

I also use Boost to get some C++11 features for threading. For example:

pWorkThread = new thread(&Activity::doWork, this, parameter);

std::lock_guard < std::mutex > guard(myMutex);

Don’t bother if you don’t understand it right now, it’s in the guts of the AXControl_v2 library we will use it in a very easy way, as you will see below. Here you will find a lot of resources to learn basic and advanced C++

Example context fot std::lock_guard < std::mutex > guard(myMutex);


short DynamixelCommunication::readSensorValue(int id, AX12Address address,
int port) {
std::lock_guard < std::mutex > guard(myMutex);
short value = -1;
try {
int size = getReadSensorWordCommand(buffer, (byte) (id), address,
(byte) (port));
memset(&result, 0, MaxBufferSize);
serialPort.query(buffer, result, size, WaitTimeReadSensor);
value = getQueryResult(result, size);
if (value <= 0)
Debug::show("DynamixelCommunication.readSensorValue", value);

} catch (exception e) {
Debug::show("DynamixelCommunication.readSensorValue", e.what());
}
return value;
}

And context for pWorkThread = new thread(&Activity::doWork, this, parameter);:


class Activity {
private:

protected:
std::thread *pWorkThread;

...

}

void Activity::start(int parameter) {
working = true;
pWorkThread = new thread(&Activity::doWork, this, parameter);
Util::sleepMS(10);
}
Let's see how to open the connection

Let’s see how to open the connection to the CM-510:

void MainWindow::on_B_Open_clicked()
{
//QString output="Open it";
//QMessageBox::information(this, "Output", output, QMessageBox::Ok);

//dynComm.open("/dev/ttyUSB0",57600); //open with these parameters
if (pDynComm->open()) //open getting the parameter from the configuration fiel
{
//Connection opened
setConnectionButtons(true); //User interface update
updateAX12Parameters(ui->SB_AX12_1_ID->text().toInt()); //User interface update
}
else
{
//Show problem opening the connection
string cantOpenPortName="I can't open port: ";
cantOpenPortName+=pConf->getStringValue(DynamixelCommunication::ParameterSerialPortName);

QMessageBox::information(this, "Error", QString::fromStdString(cantOpenPortName), QMessageBox::Ok);
}
}

and get a beep from the Robotis CM-510 (using this alternative firmware):

pDynComm->sendOrder(200, MyCommunications::BeepCM510, 0); //200 is the Dynamixel device ID used for the CM-510, 0 because beep doesn't need any additional value

Getting the AX12 position and showing it:

void MainWindow::on_B_AX12_1_GET_POS_clicked()
{
    QString qStr;

    int id = getAX12_1_Id();

    int position = pDynComm->readValue(id, MyCommunications::PresentPosition);

    ui->SB_AX12_1_POS->setValue(position);

Setting the AX12 position:

void MainWindow::on_B_AX12_1_SET_POS_clicked()
{
    int id = getAX12_1_Id();

    int position= ui->SB_AX12_1_POS->text().toInt();
    pDynComm->sendOrder(id, MyCommunications::GoalPosition,position);
}

Putting the selected AX12 LED on and off

void MainWindow::on_CH_AX12_1_LED_clicked(bool checked)
{
    int id = getAX12_1_Id();

    pDynComm->sendOrder(id, MyCommunications::LED, (checked?1:0));// if checked 1, else 0
}

And an auxiliary UI method to get the id from the selected AX-12

{
int MainWindow::getAX12_1_Id()
{
    QString qStr=ui->SB_AX12_1_ID->text();
    int id=Util::convertToInt(qStr.toStdString());

    return id;
}

You can download sources and Linux binaries here

A diagram with all the AXControl_v2 lib classes and their methods:

c++ signatura

c++ signatura

[Update]

QT5 Bioloid Workbench

QT5 Bioloid Workbench

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

This entry is part 5 of 6 in the series Bioloid Workshop

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

.
.
.
.
.

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

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)


/*------------------------------------------------------------------------------*\
 * 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;
}

Bioloid Workbench Windows C++ examples

This entry is part 6 of 6 in the series Bioloid Workshop

This post presents the Windows version of two examples/utilities built, this time, with MS Visual C++ and QT Creator, a great open source IDE and framework.

The first utility has a comand line user interface, being an easy example with only two DLL dependencies to the Visual C++ runtimes.

Screenshot-Terminal

The second example utility has a graphic user interface created with QT Creator.

QTWorkbench

Here you can find the bin executables and the projects with the source code.

This is the main function of the first example, the command line:

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;
}

[Update] Yesterday I discovered a subtle but ugly bug. Can you spot it? Send an email to if you can’t find it but you want to know the danger bug.

It use two classes, the “BasicSystem” (in the library “VS_CPP_AXControl_lib.lib”) and a simple “UI” class that receives the input from the user and use the operations offered by the “BasicSystem” class.

For example:

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;
}
...
void UI::doSetPosition()
{
  int ax12Id=getId();
  int position=getPosition();

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

And all the cource code:

/*------------------------------------------------------------------------------*\
 * 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 (http://www.siempreaprendiendo.es) *
 * @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; } 

The code for the Qt version is more complex, but as an example, the same operation that the example for the command line:

 int MainWindow::getAX12_1_Id() {     // Get the value from the edit control for the first AX-12     QString qStr=ui->SB_AX12_1_ID->text();
    int id=Util::convertToInt(qStr.toStdString());

    return id;
}
...
void MainWindow::on_B_AX12_1_SET_POS_clicked()
{
    int id = getAX12_1_Id();

    // Get the target position from the UI edit control as string and a convert it to int
    short position= ui->SB_AX12_1_POS->text().toInt();

    // Send the order to the AX-12 with the "id" to go to "position"
    pDynComm->sendOrder(id, MyCommunications::GoalPosition,position);
}
%d bloggers like this: