Robotics


Robotics

It studies the design, construction, operation and applications of robots.
Estudia el diseño, construcción, operación y aplicación de los robots.

End Effector

The device that is attached at the end of a robotic arm is called end effector. It is designed to interact with the objects in the environment and the environment itself. The figure below shows an end effector in three dimensions and in two dimensions. In the 3D robot of the figure, the end effector requires four variables to describe its position and orientation. In the 2D robot of the figure, the end effector requires only three variables to describe its position and orientation.
El dispositivo que está sujetado al final de un arma de robot se llama efector final. Este está diseñado para interactuar con los objetos en el ambiente y el propio ambiente. La figura de abajo muestra un efector final en tres dimensiones y en dos dimensiones. En el robot de 3D de la figura, el efector final requiere cuatro variables para describir su posición y su orientación. En el robot de 2D de la figura, el efector final requiere solamente tres variables para describir su posición y su orientación.

EndEffector

Problem 1
In the robot below, the orientation of the end effector is not important. Find the value of the angles B and C to set the position of the end effector at (a) x = 2.2 and y = 4.7, (b) x = -1.2 and y = 4.7.
En el robot de abajo, la orientación del efector final no es importante. Encuentre el valor de los ángulos B y C para fijar la posición del efector final en (a) x = 2.2, y = 4.7, (b) x = -1.2, y = 4.7.

SimpleRotation

Problem 2
Find the value of the angles α1, β1, α2, β2 to set the position of the end effector in x = 2.2 and y = 4.7.
Encuentre el valor de los ángulos α1, β1, α2, β2 para fijar la posición del efector final en x = 2.2, y = 4.7.

Geometry

Problem 3
Find the value of the angles α1, β1, α2, β2 to set the position of the end effector in x = -1.2 and y = 4.7.
Encuentre el valor de los ángulos α1, β1, α2, β2 para fijar la posición del efector final en x = -1.2, y = 4.7.

Geometry2

Problem 4
Create a Wintempla dialog application called Robot to simulate the 2D Robot of the previous problem.
Cree una aplicación de diálogo de Wintempla llamada Robot para simular el Robot de 2D del problema previo.

RobotRun1

RobotRun2

RobotRun3

Step A
Add a Custom Control. From Microsoft Visual Studio menu Tools > Add Wintempla Item > Custom Control . Set the name to SimView and click the Add button.
Agregue un Custom Control. Desde el menú de Microsoft Visual Studio Tools > Add Wintempla Item > Custom Control . Fije el nombre a SimView y de clic en el botón de Add.

CustomControl

Step B
Edit the GUI interface. From Microsoft Visual Studio menu Tools > Wintempla . Add six Textboxes, six Labels, two Sliders and a Custom Control (To see the Custom Control, click the green asterisk to display all the controls in the toolbox). After inserting the Custom Control, set the Class Name to SimView as shown.
Edite la interface GUI. Desde el menú de Microsoft Visual Studio Tools > Wintempla Item . Fije el nombre a SimView y de clic en el botón de Add. Agregue seis Textboxes, seis Labels, dos Sliders y un Custom Control (para ver el Custom Control, haga clic en el asterisco verde para mostrar todos los controles en la caja de herramientas, toolbox). Después de insertar el Custom Control, fije la Class Name a SimView como se muestra.

RobotGUI

CustomControlClass

Step C
Edit the files SimView.h and SimView.cpp.
Edite los archivos SimView.h and SimView.cpp.

SimView.h
//____________________________________________________________ SimView.h
#pragma once
#include "resource.h"
#define MAX_VALUE 6
//To create an object of this class, you must insert a Custom Control in the GUI

class SimView: public Win::Window
{
public:
     SimView();
     ~SimView();
     Direct::Graphics graphics;
     Direct::SolidBrush brushGreen;
     Direct::SolidBrush brushBlue;
     D2D1_SIZE_F size;
     double x = 0.0f;
     double y = 0.0f;
     double x1= 0.0f;
     double y1 = 0.0f;
     double x2 = 0.0f;
     double y2 = 0.0f;
     float TransformX(double inx);
     float TransformY(double iny);
     //____________________________________________________ Font
     virtual void SetFont(Win::Gdi::Font& font);
     __declspec( property( put=SetFont) ) Win::Gdi::Font& Font;
     //____________________________________________________ Events
     bool IsEvent(Win::Event& e, int notification);
private:
     const wchar_t * GetClassName(void){return L"SimView";}
     static bool isRegistered;
protected:
     HFONT _hFont;
     //______ Wintempla GUI manager section begin: DO NOT EDIT AFTER THIS LINE
     void Window_Open(Win::Event& e);
     void Window_Paint(Win::Event& e);
     void Window_Size(Win::Event& e);
};


SimView.cpp
//____________________________________________________________ SimView.cpp
#include "stdafx.h"
#include "SimView.h"

bool SimView::isRegistered= false;

SimView::SimView()
{     
     if (!this->isRegistered)
     {

          this->RegisterClassEx(
               LoadCursor(NULL, IDC_ARROW),
               (HBRUSH)::GetStockObject(NULL_BRUSH));
          this->isRegistered = true;
     }
     size.width = 0;
     size.height = 0;
}

SimView::~SimView()
{
}

float SimView::TransformX(double inx)
{
     return size.width*(float)inx/(2.0f*MAX_VALUE) + size.width/2.0f;
}

float SimView::TransformY(double iny)
{
     return size.height*(float)iny/(-2.0f*MAX_VALUE) + size.height/2.0f;
}

void SimView::Window_Open(Win::Event& e)
{
     brushGreen.Create(graphics, 0.0f, 1.0f, 0.0f, 1.0f);
     brushBlue.Create(graphics, 0.0f, 0.0f, 1.0f, 1.0f);
}

void SimView::Window_Paint(Win::Event& e)
{
     D2D1_ELLIPSE ellipse;
     ellipse.point.x = TransformX(x);
     ellipse.point.y = TransformY(y);
     ellipse.radiusX = 10.0f;
     ellipse.radiusY = 10.0f;
     if (graphics.BeginDraw(hWnd, width, height, RGB(0, 0, 0)) == false) return;
     graphics.SetTransform(D2D1::Matrix3x2F::Identity());
     graphics.DrawLine(TransformX(0.0), TransformY(0.0), TransformX(x1), TransformY(y1), brushBlue, 3.0f);
     graphics.DrawLine(TransformX(x1), TransformY(y1), TransformX(x2), TransformY(y2), brushBlue, 3.0f);
     graphics.FillEllipse(ellipse, brushGreen);
     graphics.EndDraw(true);
}

void SimView::Window_Size(Win::Event& e)
{
     graphics.Resize(hWnd, width, height);
     size = graphics.GetSize();
}

void SimView::SetFont(Win::Gdi::Font& font)
{
     this->_hFont = font.GetHFONT();
     ::InvalidateRect(hWnd, NULL, FALSE);
}

bool SimView::IsEvent(Win::Event& e, int notification)
{
     if (e.uMsg!=WM_COMMAND) return false;
     const int id = LOWORD(e.wParam);
     const int notificationd = HIWORD(e.wParam);
     if (id != this->id) return false;
     if (notificationd!=notification) return false;
     return true;
}


Step D
Edit the files Robot.h and Robot.cpp.
Edite los archivos Robot.h and Robot.cpp.

Robot.h
#pragma once //______________________________________ Robot.h
#include "Resource.h"
#include "SimView.h"
#define RESOLUTION 200

class Robot: public Win::Dialog
{
public:
     Robot()
     {
     }
     ~Robot()
     {
     }
     void RefreshView();
     . . .
};


Robot.cpp
. . .
void Robot::Window_Open(Win::Event& e)
{
     //________________________________________________________ sldX
     sldX.SetRange(0, RESOLUTION);
     sldX.Position = RESOLUTION/2;
     tbxX.DoubleValue = 0.0;
     //________________________________________________________ sldY
     sldY.SetRange(0, RESOLUTION);
     sldY.Position = RESOLUTION/2;
     tbxY.DoubleValue = 0.0;
}

void Robot::sldX_Hscroll(Win::Event& e)
{
     int position = 0;
     if (sldX.GetPosition(position) == false) return;
     tbxX.DoubleValue = 2.0*MAX_VALUE*(position/(double)RESOLUTION) - MAX_VALUE;
     RefreshView();
}

void Robot::sldY_Hscroll(Win::Event& e)
{
     int position = 0;
     if (sldY.GetPosition(position) == false) return;
     tbxY.DoubleValue = 2.0*MAX_VALUE*(position/(double)RESOLUTION) - MAX_VALUE;
     RefreshView();
}

void Robot::RefreshView()
{
     //________________________________________________ 1. Local variables
     const double x = tbxX.DoubleValue;
     const double y = tbxY.DoubleValue;
     const double a = 2.0;
     const double b = 4.0;
     //________________________________________________ 2. C and B
     const double c = sqrt(x*x + y*y);
     const double C = acos( (a*a + b*b - c*c)/(2.0*a*b));
     const double B = acos( (a*a + c*c - b*b)/(2.0*a*c));
     //________________________________________________ 3. alpha and beta
     double lambda = atan2(y, x);
     if (lambda < 0.0) lambda += (2.0*M_PI);
     const double alpha1 = lambda + B;
     const double alpha2 = lambda - B;
     double beta1 = atan2(y - a * sin(alpha1), x - a * cos(alpha1) );
     double beta2 = atan2(y - a * sin(alpha2), x - a * cos(alpha2) );
     if (beta1 < 0.0) beta1 += (2.0*M_PI);
     if (beta2 < 0.0) beta2 += (2.0*M_PI);
     //________________________________________________ 4. Display in GUI
     tbxBeta1.DoubleValue = beta1*180.0/M_PI;
     tbxBeta2.DoubleValue = beta2*180.0/M_PI;
     tbxAlpha1.DoubleValue = alpha1*180.0/M_PI;
     tbxAlpha2.DoubleValue = alpha2*180.0/M_PI;
     //________________________________________________ 5. Move bars
     customControlSim.x = x;
     customControlSim.y = y;
     //
     customControlSim.x1 = a*cos(alpha1);
     customControlSim.y1 = a*sin(alpha1);
     //
     customControlSim.x2 = customControlSim.x1 + b*cos(beta1);
     customControlSim.y2 = customControlSim.y1 + b*sin(beta1);
     //
     customControlSim.Repaint(NULL, false);
}


Optimization

It is possible to use optimization algorithms to find the values of θ1 and θ2 by defining an error function.
Es posible usar algoritmos de optimización para encontrar los valores de θ1 y θ2 definiendo una función de error.

ErrorFunction

Problem 5
Create a Wintempla dialog application called TwoBars to plot the error function shown below. After creating the project, use Wintempla to edit the GUI, click on "Show All Control in Toolbox" in the toolbar and insert a "Color Map" control to display the graph.
Cree una aplicación de diálogo de Wintempla llamada TwoBars para graficar la función de error mostrada. Después de crear el proyecto, use Wintempla para editar la GUI, haga clic en "Show All Control in Toolbox" en la barra de herramientas e inserte un control de "Color Map" para mostrar la gráfica.

TwoBarsGUI

TwoBarsRun1

TwoBarsRun2

MultipleSol

Step A
Edit the TwoBars.h file, do not forget to derivate the main class from Sys::IColorMapDataProvider.
Edite el archivo TwoBars.h, no se olvide de derivar la clase principal desde Sys::IColorMapDataProvider.

TwoBars.h
#pragma once //______________________________________ TwoBars.h
#include "Resource.h"
class TwoBars: public Win::Dialog, public Sys::IColorMapDataProvider
{
public:
     TwoBars()
     {
     }
     ~TwoBars()
     {
     }
     double x = 0.0;
     double y = 0.0;
protected:
     //_____________________________________________Sys::IColorMapDataProvider
     void GetDataRowZ(const int row, const int in_countX, const double* in_x, const double in_y, double* out_z);
     . . .
};


Step B
Edit the TwoBars.cpp file.
Edite el archivo TwoBars.cpp.

TwoBars.cpp
. . .

void TwoBars::Window_Open(Win::Event& e)
{
     //________________________________________________________ mapError
     mapError.MinX = 0.0;
     mapError.MaxX = 360.0;
     mapError.MinY = 0.0;
     mapError.MaxY = 360.0;
     mapError.MinZ = 0.0;
     mapError.MaxZ = 0.2;
     mapError.SetPixelsResolutionX(512);
     mapError.SetPixelsResolutionY(512);
     mapError.SetCaptionX(L"a", true);
     mapError.SetCaptionY(L"b", true);
     mapError.SetCaptionZ(L"Error", false);
     mapError.SetDataProvider(this);
     //________________________________________________________ sldX
     sldX.SetRange(0, 200);
     sldX.Position = 50;
     //________________________________________________________ sldY
     sldY.SetRange(0, 200);
     sldY.Position = 50;
     //
     tbxX.DoubleValue = 0.0;
     tbxY.DoubleValue = 0.0;
     mapError.Refresh();
}

void TwoBars::GetDataRowZ(const int row, const int in_countX, const double* in_x, const double in_y, double* out_z)
{
     double alpha = 0.0;
     double beta = 0.0;
     double dx, dy;
     for (int i = 0; i < in_countX; i++)
     {
          alpha = in_x[i]*M_PI/180.0;
          beta = in_y*M_PI/180.0;
          dx = x - 2.0*cos(alpha) - 4.0*cos(beta);
          dy = y - 2.0*sin(alpha) - 4.0*sin(beta);
          out_z[i] = dx*dx + dy*dy;
     }
}

void TwoBars::sldX_Hscroll(Win::Event& e)
{
     int position = 0;
     if (sldX.GetPosition(position) == false) return;
     x = 12.0*position/200.0 - 6.0;
     tbxX.DoubleValue = x;
     mapError.Refresh();
}

void TwoBars::sldY_Hscroll(Win::Event& e)
{
     int position = 0;
     if (sldY.GetPosition(position) == false) return;
     y = 12.0*position/200.0 - 6.0;
     tbxY.DoubleValue = y;
     mapError.Refresh();
}


Problem 6
Create a Wintempla dialog application called BarSol to compute the optimization error for uniformly distributed values for θ1 and θ2. After creating the project, insert a multiline textbox to display the results. Also insert two textboxes, two labels and one button as shown below. One textbox is for the resolution and the other textbox is for the maximum error.
Cree una aplicación de diálogo de Wintempla llamada BarSol para calcular el error de optimización para valores uniformemente distribuidos para θ1 y θ2. Después de crear el proyecto, inserte una caja multilínea para mostrar los resultados. También inserte dos cajas de texto, dos etiquetas y un botón cómo se muestra. Una caja de texto es para la resolución y la otra para el error máximo.

BarSolRun1

BarSolRun2

BarSolRun3

BarSol.cpp
. . .
void BarSol::Window_Open(Win::Event& e)
{
     tbxMaxError.DoubleValue = 0.01;
     tbxResolution.IntValue = 100;
}

void BarSol::btCompute_Click(Win::Event& e)
{
     const double maxError = tbxMaxError.DoubleValue;
     wstring text = L"alpha\t\tbeta\t\terror\r\n";
     wchar_t tmp[512];
     const int resolution = tbxResolution.IntValue;
     const double delta = 360.0/resolution;
     double alpha, beta, error;
     double dx, dy;
     for (alpha = 0.0; alpha < 360.0; alpha += delta)
     {
          for (beta = 0.0; beta < 360.0; beta += delta)
          {
               dx = 5.0 - 2.0*cos(alpha*M_PI/180.0) - 4.0*cos(beta*M_PI/180.0);
               dy = 3.0 - 2.0*sin(alpha*M_PI/180.0) - 4.0*sin(beta*M_PI/180.0);
               error = dx*dx + dy*dy;
               if (error > maxError) continue;
               _snwprintf_s(tmp, 512, _TRUNCATE, L"%.4f\t\t%.4f\t\t%.4f\r\n", alpha, beta, error);
               text += tmp;
          }
     }
     tbxOutput.Text = text;
}


Artificial Neural Networks

In some cases, it is possible to use an artificial neural network to find the configuration of the robot using the desired position of the end effector. However, if the robot has two or more configurations to obtain one desired position of the end effector, an artificial neural network will NOT be able to learn multiple configurations. In fact, only one robot configuration for each position (and orientation) of the end effector can be included in the training set.
En algunos casos, es posible usar una red neuronal artificial para encontrar la configuración de un robot usando la posición deseada del efector final. Sin embargo, si el robot tiene dos o más configuraciones para conseguir la posición deseada del efector final, una red neuronal artificial NO podrá aprender las dos configuraciones. De hecho, solamente una configuración del robot para cada posición (y orientación) del efector final puede ser incluida en el conjunto de datos de entrenamiento.

Problem 7
Create a Wintempla dialog application called BuildTrainSet to create a dataset to train an artificial neural network to compute the values of α and β for a given position of the end effector in the figure. After creating the project, edit the GUI as shown below.
Cree una aplicación de diálogo de Wintempla llamada BuildTrainSet para crear un conjunto de datos para entrenar una red neuronal artificial para calcular los valores de α y β para una posición dada del efector final de la figura. Después de crear el proyecto, edite la GUI cómo se muestra debajo.

AnnInverse

BuilTrainSetRun

Step A
Edit the BuildTrainSet.cpp file as shown.
Edite el archivo BuilTrainSet.cpp cómo se muestra.

BuilTrainSet.cpp
. . .
void BuildTrainSet::btBuild_Click(Win::Event& e)
{
     //____________________________________________________ 1. Prompt user for filename
     Win::FileDlg dlg;
     dlg.Clear();
     dlg.SetFilter(L"Comma separated values (*.csv)\0*.csv\0\0", 0, L"csv");
     if (dlg.BeginDialog(hWnd, L"Save", true) != TRUE) return;
     //____________________________________________________ 2. Create file
     Sys::File file;
     if (file.CreateForWritting(dlg.GetFileNameFullPath()) == false)
     {
          Sys::DisplayLastError(hWnd, L"Saving CSV file");
          return;
     }
     //____________________________________________________ 3. Write file
     const int resolution = tbxResolution.IntValue;
     const double delta = 180.0/resolution;
     double alpha, beta, radAlpha, radBeta;
     double x, y;
     char text[512];
     _snprintf_s(text, 512, _TRUNCATE, "x, y, alpha, beta\r\n");
     file.WriteText(text);
     for (alpha = 0.0; alpha < 180.0; alpha += delta)
     {
          radAlpha = alpha*M_PI/180.0;
          for (beta = alpha + delta; beta < 180.0; beta += delta)
          {
               radBeta = beta*M_PI/180.0;
               x = 2.0*cos(radAlpha) + 4.0*cos(radBeta);
               y = 2.0*sin(radAlpha) + 4.0*sin(radBeta);
               _snprintf_s(text, 512, _TRUNCATE, "%.7f, %.7f, %.7f, %.7f\r\n", x, y, alpha, beta);
               file.WriteText(text);
          }
     }
}


Step B
From Microsoft Visual Studio menu Build > Configuration Manager change the configuration to "Release". Then, compile and run the program.
Desde el menú de Microsoft Visual Studio Build > Configuration Manager cambie la configuración a "Release". Entonces, compile y ejecute el programa.

ConfigurationManager

Step C
Set the resolution to 180 (180/180=1 degrees), then create a filename called dataset.csv as shown.
Fije la resolución a 180 (180/180=1 grados), entonces cree un archivo llamado dataset.csv cómo se muestra.

DatasetFile

Problem 8
Use Neural Lab (4.5 or later) to create a project called Inverse, select the option "Main file only". After creating the project, copy the dataset.csv file to the Inverse folder as shown. Edit the Main.lab file to create the training set input and the training set target for α and for β.
Use Neural Lab (4.5 o posterior) para crear un proyecto llamado Inverse, seleccione la opción de "Main file only". Después de crear el proyecto, copie el archivo dataset.csv a la carpeta del proyecto Inverse como se muestra. Edite el archivo Main.lab para crear la entrada del conjunto de entrenamiento y la meta del conjunto de datos de entrenamiento para α y para β.

InverseFolder

Inverse\Main.lab
//_______________________________________ 1. Load dataset
Matrix dataset;
dataset.Load();
//_______________________________________ 2. Train set input
Vector index;
index.Create(2);
index[0] = 0;
index[1] = 1;
Matrix trainSetInput = dataset.GetCols(index);
trainSetInput.Save();
//_______________________________________ 3. alpha
Matrix alpha = dataset.GetCol(2);
alpha.Save();
//_______________________________________ 4. beta
Matrix beta = dataset.GetCol(3);
beta.Save();

Step A
Add a file called TrainAlpha.lab as shown below to train an artificial neural network to estimate the value of α. After editing the file, execute the code to train the artificial neural network for α.
Agregue un archivo llamado TrainAlpha.lab cómo se muestra debajo para entrenar una red neuronal artificial para estimar el valor de α. Después de editar el archivo, ejecute el código para entrenar la red neuronal artificial para α.

Inverse\TrainAlpha.lab
//_______________________________________ 1. Network setup
DeepNet netAlpha;
netAlpha.Create(2, 2);
netAlpha.SetLayer(0, 1, 20);
netAlpha.SetLayer(1, 1, 1);
//_______________________________________ 2. Input scaling
netAlpha.SetInScaler(0, -6.0, 6.0); // x
netAlpha.SetInScaler(1, 0.0, 6.0); // y
//_______________________________________ 3. Output scaling
netAlpha.SetOutScaler(0, 0.0, 179.0);
//_______________________________________ 4. Training set
Matrix trainSetInput;
trainSetInput.Load();
Matrix alpha;
alpha.Load();
netAlpha.SetTrainSet(trainSetInput, alpha, false);
//_______________________________________ 5. Train using simulated annealing
netAlpha.TrainSimAnneal(
     20, //Number of Temperatures
     20, //Number Iterations
     15, //Initial Temperature
     0.001, //Final Temperature
     true, //Is Cooling Schedule Linear?
     2, //Number of Cycles
     1.0e-5, //Goal (desired mse)
     true //Use Singular Value Decomposition
);
//_______________________________________ 6. Train using conjugate gradient
netAlpha.TrainConjGrad(2500, 1.0e-8);
//_______________________________________ 7. Save the trained network
netAlpha.Save();

Step B
Add a file called TrainBeta.lab as shown below to train an artificial neural network to estimate the value of β. After editing the file, execute the code.
Agregue un archivo llamado TrainBeta.lab cómo se muestra debajo para entrenar una red neuronal artificial para estimar el valor de β. Después de editar el archivo, ejecute el código.

Inverse\TrainBeta.lab
//_______________________________________ 1. Network setup
DeepNet netBeta;
netBeta.Create(2, 2);
netBeta.SetLayer(0, 1, 20);
netBeta.SetLayer(1, 1, 1);
//_______________________________________ 2. Input scaling
netBeta.SetInScaler(0, -6.0, 6.0); // x
netBeta.SetInScaler(1, 0.0, 6.0); // y
//_______________________________________ 3. Output scaling
netBeta.SetOutScaler(0, 0.0, 179.0);
//_______________________________________ 4. Training set
Matrix trainSetInput;
trainSetInput.Load();
Matrix beta;
beta.Load();
netBeta.SetTrainSet(trainSetInput, beta, false);
//_______________________________________ 5. Train using simulated annealing
netBeta.TrainSimAnneal(
     20, //Number of Temperatures
     20, //Number Iterations
     15, //Initial Temperature
     0.001, //Final Temperature
     true, //Is Cooling Schedule Linear?
     2, //Number of Cycles
     1.0e-5, //Goal (desired mse)
     true //Use Singular Value Decomposition
);
//_______________________________________ 6. Train using conjugate gradient
netBeta.TrainConjGrad(2500, 1.0e-8);
//_______________________________________ 7. Save the trained network
netBeta.Save();

Step C
Add a file called Test.lab to evaluate the performance of the artificial neural network.
Agregue un archivo llamado Test.lab para evaluar el desempeño de la red neuronal artificial.

Inverse\Test.lab
//_______________________________________ 1. Load networks
DeepNet netAlpha;
netAlpha.Load();
DeepNet netBeta;
netBeta.Load();
//_______________________________________ 2. Input
Matrix trainSetInput;
trainSetInput.Load();
int count = trainSetInput.GetRowCount();
Vector index;
index.CreateRandomSet(100, count-1);
Matrix inputXY = trainSetInput.GetRows(index);
//_______________________________________ 3. Run networks
Matrix alpha;
netAlpha.Run(inputXY, alpha);
Matrix beta;
netBeta.Run(inputXY, beta);
//_______________________________________ 4. Compute x and y
Matrix radAlpha = alpha*3.1416/180.0;
Matrix radBeta = beta*3.1416/180.0;
Matrix x = 2.0*cos(radAlpha) + 4.0*cos(radBeta);
Matrix y = 2.0*sin(radAlpha) + 4.0*sin(radBeta);
//_______________________________________ 5. Plot target
XyChart xyGraph;
xyGraph.SetColorMode(2);
xyGraph.SetLimits(-6.0, 6.0, 0.0, 6.0);
Vector vx = inputXY.GetColVec(0);
Vector vy = inputXY.GetColVec(1);
xyGraph.AddGraph(vx, vy, "Target", 1, 2, 0, 100, 255);
//_______________________________________ 6. Plot ANN results;
vx = x.GetColVec(0);
vy = y.GetColVec(0);
xyGraph.AddGraph(vx, vy, "ANN", 1, 3, 0, 255, 0);
xyGraph.SaveAndShow();
xyGraph.SavePDF(0.0);

AnnXyGraph

Frame of reference

In robotics, physics and other areas, it is very important to have point in space and time for reference. This point is called Frame of Reference and it is depicted as shown below.
En robótica, física y otras áreas, es muy importante tener un punto en espacio y tiempo para referencia. Este punto es llamado Marco de Referencia y se dibuja como se muestra debajo.

Frame

Joints

There are two types of joints: rotational joints and prismatic joints (extending). A joint connects two different frames. The joint allows to change the distance or rotation angle between two frames.
Hay dos tipos de uniones: uniones de rotación y uniones prismáticas (extendedoras). Una unión conecta dos frames diferentes. La unión permite cambiar la distancia o el ángulo de rotación entre dos frames.

joints

Joint Variable

Each join has a parameter associated with the joint. A prismatic joint has a variable to represent the distance between the two frames. A rotational joint has a variable to represent the angle between the two frames.
Cada unión tiene un parámetro asociado con la unión. Una unión prismática tiene una variable para representar la distancia entre las dos frames. Una unión de rotación tiene una variable para representar el ángulo entre las dos frames.

JointVariable

Homogeneous Transformation Matrix

It allows transforming the coordinates of a point relative to one frame to the coordinates relative to another frame. This matrix is very useful in robotics to know the position of any part of the robot relative to the base frame. An homogeneous transformation matrix has four rows and four columns. The last row of the matrix is composed of three "zeros" and one "one" as shown in the figure. The matrix includes inside a rotation matrix and a displacement vector. An homogeneous transformation matrix has a superscript to indicate the current frame, and a subscript to indicate the next frame. In the example, both frames are separated a distance of two in the X direction.
Esta permite transformar las coordenadas de un punto relativas a una frame a las coordenadas relativas a otra frame. Esta matriz es muy útil en robótica para conocer la posición de cualquier parte del robot en forma relativa a la frame base. Una matriz de transformación homogénea tiene cuatro renglones y cuatro columnas. El último renglón de la matriz está compuesto de tres "ceros" y un "uno" como se muestra en la figura. La matriz incluye dentro una matriz de rotación y un vector de desplazamiento. Una matriz de transformación homogénea tiene un superíndice para indicar la frame actual, y un subíndice para indicar la frame siguiente. En el ejemplo, ambas frames están separadas una distancia de dos en la dirección de X.

HomTransMat

Point Transformation

In the figure below, there is the point P. The point P does not change position, but the point P can be expressed using as reference frame 1 or frame 2. P1 denotes the point P relative to frame 1, while P2 denotes the point P relative to frame 2. Observe that in this type of notation, the point is expressed by a vector column with four elements. Observe also that the value in the last row of this vector is always one. The figure below shows the value of P2. The figure also illustrates how compute the value of P1, that is, the value P relative to Frame 1. Thus, once the homogeneous transformation matrix between two frames has been computed, it is possible to transform a point from one frame to the other frame.
En la figura de abajo, está el punto P. El punto P no cambia de posición, pero el punto P puede ser expresado usando como referencia la frame 1 o la frame 2. P1 denota el punto P en forma relativa con la frame 1, mientras P2 denota el punto P en forma relativa con la frame 2. Observe que en este tipo de notación, el punto se expresa por un vector columna con cuatro renglones. Observe también que el valor en el último renglón de este vector es siempre uno. La figura de abajo muestra el valor de P2. La figura también ilustra cómo calcular el valor de P1, esto es, el valor de P en forma relativa a la frame 1. Así, una vez que la matriz de transformación homogénea entre dos frames sea calculado, es posible transformar un punto de una frame a la otra frame.

PointTranformation

Problem 9
Compute the homogeneous transformation matrix for the system below.
Calcule la matriz de transformación homogénea para el sistema debajo.

XDisplacement

Problem 10
Compute the homogeneous transformation matrix for the system below.
Calcule la matriz de transformación homogénea para el sistema debajo.

RotationMatrix2

Problem 11
Compute the homogeneous transformation matrix for the system below.
Calcule la matriz de transformación homogénea para el sistema debajo.

RotationMatrix3

Tip
The figure below shows the formulas for rotation around each axis for a left-handed coordinate system and a right-handed coordinate system.
La figura de abajo muestra las fórmulas para rotación alrededor de cada eje para un sistema de coordenadas de mano derecha y para un sistema de coordenadas de mano izquierda.

RotationFormulas

Problem 12
Compute the homogeneous transformation matrix for the system below for a right-handed coordinate system.
Calcule la matriz de transformación homogénea para el sistema debajo para un sistema de coordenadas de mano derecha.

RotationMatrix4

Denavit-Hartenberg

The method of Denavit-Hartenberg allows computing the homogeneous transformation matrix using an alternative method. This method includes some rules, they are called frame rules and are:
  1. The Z-axis must be the axis of revolution in a rotation joint or the direction of motion in a prismatic joint
  2. The X-axis must be perpendicular to the Z-axis of the frame before it.
  3. The X-axis must intersect the Z-axis of the frame before it.
  4. The Y-axis must be drawn so the whole frame follows the right-hand rule.

El método de Denavit-Hartenberg permite calcular la matriz de transformación homogénea usando un método alternativo. Este método incluye algunas reglas, estas son llamadas las reglas de las frames y son:
  1. El eje Z debe ser el eje de giro en una unión de rotación o en la dirección del movimiento en una unión prismática
  2. El eje X debe ser perpendicular al eje Z de la frame que está antes de este.
  3. El eje X debe intersectar al eje Z de la frame que está antes de este.
  4. El eje Y debe ser dibujado de tal forma que la frame completa siga la regla de la mano derecha.

Denavit-Hartenberg parameters

The method of Denavit-Hartenberg has four input parameters: θ, α, r and d Once these parameters have been computed, the formula below is used to compute the homogeneous transformation matrix. Wintempla provides the function Math::Oper::Denavit to compute this matrix.
El método de Denavit-Hartenberg tiene cuatro parámetros de entrada: θ, α, r y d. Una vez que estos parámetros han sido calculados, la fórmula de abajo se usa para calcular la matriz de transformación homogénea. Wintempla proporciona la función Math::Oper::Denavit para calcular esta matriz.

DenavitHartenberg

Computation of θ

θ is the amount of rotation around the Zn-1 axis to get axis Xn-1 to match the direction of Xn axis as shown in the figure below.
θ es la cantidad de rotación alrededor del eje Zn-1 para que el eje Xn-1 tenga la misma dirección del eje Xn como se muestra en la figura.

DH_theta

Computation of α

α is the amount of rotation around the Xn axis to get the axis Zn-1 to match the direction of Zn axis as shown in the figure below.
α es la cantidad de rotación alrededor del eje Xn para que el eje Zn-1 tenga la misma dirección que el eje Zn como se muestra en la figura.

DH_alpha

Computation of r

r is the displacement along the Xn axis between the center of frame n-1 and the center of frame n as shown in the figure below.
r es la desplazamiento a lo largo del eje Xn entre el centro de la frame n-1 y el centro de la frame n como se muestra en la figura.

DH_r

Computation of d

d is the distance between the centers of the two frames in the direction of the Zn-1 axis as shown in the figure below.
d es la distancia entre los centros de las dos frames en la dirección del eje Zn-1 como se muestra en la figura.

DH_d

Problem 13
Compute the Denavit-Hartenberg parameters for the system shown.
Calcule los parámetros de Denavit-Hartenberg para el sistema mostrado.

RotVert

Problem 14
Compute the Denavit-Hartenberg parameters for the system shown.
Calcule los parámetros de Denavit-Hartenberg para el sistema mostrado.

RotHorz

Problem 15
Compute the Denavit-Hartenberg parameters for the system shown.
Calcule los parámetros de Denavit-Hartenberg para el sistema mostrado.

RotCorner

Problem 16
Compute the Denavit-Hartenberg parameters for the system shown.
Calcule los parámetros de Denavit-Hartenberg para el sistema mostrado.

RotCornerDown

Problem 17
Compute the Denavit-Hartenberg parameters for the system shown.
Calcule los parámetros de Denavit-Hartenberg para el sistema mostrado.

PrismDown

Problem 18
Create a DirectX application called Cartesian using Wintempla to test the cartesian manipulator. Press the
  1. Space bar to rotate the manipulator
  2. 1, 2 or 3 key to increase d1, d2 or d3
  3. Q, W or E key to decrease d1, d2 or d3

Cree una aplicación de DirectX llamada Cartesian usando Wintempla para probar el manipulador cartesiano. Presiona la tecla
  1. de barra espaciadora para girar el manipulador
  2. 1, 2 o 3 para incrementar d1, d2 or d3
  3. Q, W o E para disminuir d1, d2 or d3

CartesianManipulator

CartesianRun1

CartesianRun2

CartesianRun3

Step 1
Edit the files Manipulator.h and Manipulator.cpp.
Edite los archivos Manipulator.h and Manipulator.cpp.

Manipulator.h
#pragma once
class Manipulator : public DX11::ColorVertexBuffer
{
public:
     Manipulator();
     ~Manipulator();
     DirectX::XMMATRIX world;
     void ChangeD1(ID3D11DeviceContext* deviceContext, double delta);
     void ChangeD2(ID3D11DeviceContext* deviceContext, double delta);
     void ChangeD3(ID3D11DeviceContext* deviceContext, double delta);
     void Turn(Sys::Stopwatch& stopWatch);
private:
     MATRIX H01;
     MATRIX H12;
     MATRIX H23;
     MATRIX H02;
     MATRIX H03;
     double d1 = 0.0;
     double d2 = 0.0;
     double d3 = 0.0;
     void ComputeH();
     FLOAT angleY = (FLOAT)0.0f;
};


Manipulato.cpp
. . .
Manipulator::Manipulator()
{
     world = DirectX::XMMatrixIdentity();
     if (Setup(6, 6, D3D11_USAGE_DYNAMIC, D3D_PRIMITIVE_TOPOLOGY_LINELIST) == false) return;
     for (size_t i = 0; i < 6; i++)
     {
          vertex[i].position = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f);
          index[i] = i;
     }
     //_________________________________________________ Link 1 (Red)
     vertex[0].color = DirectX::XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f);
     vertex[1].color = DirectX::XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f);
     //_________________________________________________ Link 2 (Green)
     vertex[2].color = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f);
     vertex[3].color = DirectX::XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f);
     //_________________________________________________ Link 3 (Blue)
     vertex[4].color = DirectX::XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f);
     vertex[5].color = DirectX::XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f);
     ComputeH();
}

Manipulator::~Manipulator()
{
}

void Manipulator::ChangeD1(ID3D11DeviceContext* deviceContext, double delta)
{
     d1 += delta;
     ComputeH();
     this->DynamicUpdate(deviceContext, true, false);
}

void Manipulator::ChangeD2(ID3D11DeviceContext* deviceContext, double delta)
{
     d2 += delta;
     ComputeH();
     this->DynamicUpdate(deviceContext, true, false);
}

void Manipulator::ChangeD3(ID3D11DeviceContext* deviceContext, double delta)
{
     d3 += delta;
     ComputeH();
     this->DynamicUpdate(deviceContext, true, false);
}

void Manipulator::ComputeH()
{
     Math::Oper::DenavitD(90.0, 90.0, 0.0, 4.0+d1, H01);
     Math::Oper::DenavitD(90.0, -90.0, 0.0, 8.0+d2, H12);
     Math::Oper::DenavitD(0.0, 0.0, 0.0, 5.0+d3, H23);
     Math::Oper::Product(H01, H12, H02); // H02 = H01*H12
     Math::Oper::Product(H02, H23, H03); // H03 = H02*H23
     //
     if (this->GetVertexCount() == 0) return;
     //_________________________________________________ Link 1
     vertex[0].position = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f);
     vertex[1].position = DX11::Geometry::HomegeneousTransformation(H01, 0.0f, 0.0f, 0.0f);
     //_________________________________________________ Link 2
     vertex[2].position = vertex[1].position;
     vertex[3].position = DX11::Geometry::HomegeneousTransformation(H02, 0.0f, 0.0f, 0.0f);
     //_________________________________________________ Link 3
     vertex[4].position = vertex[3].position;
     vertex[5].position = DX11::Geometry::HomegeneousTransformation(H03, 0.0f, 0.0f, 0.0f);
}

void Manipulator::Turn(Sys::Stopwatch& stopWatch)
{
     const FLOAT delta = (FLOAT)stopWatch.GetSeconds();
     //________________________________________________________ 1. Rotate, translate and scale
     angleY += (0.5f*delta);
     world = DirectX::XMMatrixRotationY(angleY);
     if (angleY > DirectX::XM_2PI) angleY -= DirectX::XM_2PI;
}


Step 2
Edit the files Cartesian.h and Cartesian.cpp.
Edite los archivos Cartesian.h and Cartesian.cpp.

Cartesian.h
#pragma once //______________________________________ Cartesian.h
#include "Resource.h"
#include "Manipulator.h"

class Cartesian: public DX11::Window
{
public:
     Cartesian()
     {
     }
     ~Cartesian()
     {
     }
     //____________________________________________________ 1. Application
     Manipulator manipulator;
     . . .
};


Cartesian.cpp
. . .
void Cartesian::Window_Open(Win::Event& e)
{
     . . .
     //________________________________________________________________ 4. Setup the camera
     camera.position.x = 0.0f;
     camera.position.y = 2.0f;
     camera.position.z = -10.0f;
     //
     camera.lookAt.x = 0.0f;
     camera.lookAt.y = -0.2f;
     camera.lookAt.z = 1.0f;
     //
     camera.SetViewInfo(modeDesc.Width, modeDesc.Height, false); // Left-Handed coordinate system
     //________________________________________________________________ 5. Setup the application objects
     manipulator.Create(hWnd, device);
}

void Cartesian::RenderScene()
{
     //________________________________________________ 1. Clear screen and camera update
     Clear(0.0f, 0.0f, 0.2f, 1.0f);
     camera.Update();
     //________________________________________________ 2. Application objects
     manipulator.DynamicUpdate(deviceContext, true, false);
     manipulator.Render(deviceContext);
     if (keyboard[VK_SPACE]) manipulator.Turn(stopWatch);
     colorShader.Render(deviceContext, manipulator.GetIndexCount(), manipulator.world, camera);
}

void Cartesian::Window_KeyDown(Win::Event& e)
{
     if (e.wParam>255) return;
     keyboard[e.wParam] =true;
     if (e.wParam == VK_ESCAPE)
     {
          if (isFullScreen)
          {
               ::DestroyWindow(hWnd);
          }
          else
          {
               if (::MessageBox(hWnd, L"Do you want to close?", L"Cartesian", MB_YESNO | MB_ICONQUESTION) == IDYES) ::DestroyWindow(hWnd);
          }
     }
     else if (e.wParam == '1')
     {
          manipulator.ChangeD1(deviceContext, 0.1);
     }
     else if (e.wParam == '2')
     {
          manipulator.ChangeD2(deviceContext, 0.1);
     }
     else if (e.wParam == '3')
     {
          manipulator.ChangeD3(deviceContext, 0.1);
     }
     else if (e.wParam == 'Q')
     {
          manipulator.ChangeD1(deviceContext, -0.1);
     }
     else if (e.wParam == 'W')
     {
          manipulator.ChangeD2(deviceContext, -0.1);
     }
     else if (e.wParam == 'E')
     {
          manipulator.ChangeD3(deviceContext, -0.1);
     }
}
. . .


Problem 19
Create a DirectX application called Spherical using Wintempla to test the spherical manipulator. After creating the project, add a new class called Manipulator.
Cree una aplicación de DirectX llamada Spherical usando Wintempla para probar el manipulador esférico. Después de crear el proyecto, agrega una nueva clase llamada Manipulator.

SphericalManipulator

© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home