lunes, 25 de marzo de 2013

So... let's the Bioloid, C++ and QT games start!

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),

[caption id="attachment_1635" align="aligncenter" width="300"]Synaptic G++ Synaptic G++[/caption]

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)

[caption id="attachment_1637" align="aligncenter" width="600"]QTCreator Bioloid QTWorkshop QTCreator Bioloid QTWorkshop[/caption]

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

[sourcecode language="cpp"]

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

[/sourcecode]

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

[sourcecode language="cpp"]

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
[/sourcecode]

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

[sourcecode language="cpp"]
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);
}
}
[/sourcecode]

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

[sourcecode language="cpp"]
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
[/sourcecode]

Getting the AX12 position and showing it:

[sourcecode language="cpp"]
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);
[/sourcecode]

Setting the AX12 position:

[sourcecode language="cpp"]
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);
}
[/sourcecode]

Putting the selected AX12 LED on and off

[sourcecode language="cpp"]
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
}
[/sourcecode]

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

[sourcecode language="cpp"]
{
int MainWindow::getAX12_1_Id()
{
QString qStr=ui->SB_AX12_1_ID->text();
int id=Util::convertToInt(qStr.toStdString());

return id;
}
[/sourcecode]

You can download sources and Linux binaries here

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

[caption id="attachment_1384" align="aligncenter" width="600"]c++ signatura c++ signatura[/caption]

[Update]

[caption id="attachment_1722" align="aligncenter" width="164"]QT5 Bioloid Workbench QT5 Bioloid Workbench[/caption]

No hay comentarios:

Publicar un comentario