1#include "robodktypes.h" 
    9    _nDOFs = qMin(ndofs, RDK_SIZE_JOINTS_MAX);
 
   10    for (
int i=0; i<
_nDOFs; i++){
 
 
   21    int ndofs_ok = qMin(ndofs, RDK_SIZE_JOINTS_MAX);
 
   22    double jnts[RDK_SIZE_JOINTS_MAX];
 
   23    for (
int i=0; i<ndofs_ok; i++){
 
 
   29    if (Matrix2D_Size(mat2d, 2) >= column){
 
   31        qDebug()<<
"Warning: tMatrix2D column outside range when creating joints";
 
   34        ndofs = Matrix2D_Size(mat2d, 1);
 
   36    _nDOFs = qMin(ndofs, RDK_SIZE_JOINTS_MAX);
 
   38    double *ptr = Matrix2D_Get_col(mat2d, column);
 
 
   50    for (
int i=0; i<RDK_SIZE_JOINTS_MAX; i++){
 
 
   55#ifdef ROBODK_API_FLOATS 
   65double tJoints::Compare(
const tJoints &other)
 const {
 
   66    double sum_diff = 0.0;
 
   80        _nDOFs = qMin(ndofs, RDK_SIZE_JOINTS_MAX);
 
   82    for (
int i=0; i<
_nDOFs; i++){
 
 
   89        _nDOFs = qMin(ndofs, RDK_SIZE_JOINTS_MAX);
 
   91    for (
int i=0; i<
_nDOFs; i++){
 
 
   96    for (
int i=0; i<
_nDOFs; i++){
 
 
  106    values.append(QString::number(
_Values[0],
'f',precision));
 
  107    for (
int i=1; i<
_nDOFs; i++){
 
  108        values.append(separator);
 
  109        values.append(QString::number(
_Values[i],
'f',precision));
 
 
  114    QStringList jnts_list = QString(str).replace(
";",
",").replace(
"\t",
",").split(
",", Qt::SkipEmptyParts);
 
  115    _nDOFs = qMin(jnts_list.length(), RDK_SIZE_JOINTS_MAX);
 
  116    for (
int i=0; i<
_nDOFs; i++){
 
  117        QString stri(jnts_list.at(i));
 
  118        _Values[i] = stri.trimmed().toDouble();
 
 
  127    if (new_length >= 0 && new_length < 
_nDOFs){
 
 
  142Mat transl(
double x, 
double y, 
double z){
 
  167Mat::Mat(
const QMatrix4x4 &matrix) : QMatrix4x4(matrix) {
 
 
  176Mat::Mat(
double nx, 
double ox, 
double ax, 
double tx, 
double ny, 
double oy, 
double ay, 
double ty, 
double nz, 
double oz, 
double az, 
double tz) :
 
  177    QMatrix4x4(nx, ox, ax, tx, ny, oy, ay, ty, nz, oz, az, tz, 0,0,0,1)
 
 
  182    QMatrix4x4(v[0], v[4], v[8], v[12], v[1], v[5], v[9], v[13], v[2], v[6], v[10], v[14], v[3], v[7], v[11], v[15])
 
 
  187    QMatrix4x4(v[0], v[4], v[8], v[12], v[1], v[5], v[9], v[13], v[2], v[6], v[10], v[14], v[3], v[7], v[11], v[15])
 
 
  193    QMatrix4x4(1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, y, 0.0, 0.0, 1.0, z, 0.0,0.0,0.0,1.0)
 
 
  291    QVector4D rw(this->row(i));
 
 
  306    return this->inverted();
 
 
  311    const bool debug_info = 
false;
 
  313    const double tol = 1e-7;
 
  317    if (fabs((
double) DOT(vx,vy)) > tol){
 
  319            qDebug() << 
"Vector X and Y are not perpendicular!";
 
  322    } 
else if (fabs((
double) DOT(vx,vz)) > tol){
 
  324            qDebug() << 
"Vector X and Z are not perpendicular!";
 
  327    } 
else if (fabs((
double) DOT(vy,vz)) > tol){
 
  329            qDebug() << 
"Vector Y and Z are not perpendicular!";
 
  332    } 
else if (fabs((
double) (NORM(vx)-1.0)) > tol){
 
  334            qDebug() << 
"Vector X is not unitary! " << NORM(vx);
 
  337    } 
else if (fabs((
double) (NORM(vy)-1.0)) > tol){
 
  339            qDebug() << 
"Vector Y is not unitary! " << NORM(vy);
 
  342    } 
else if (fabs((
double) (NORM(vz)-1.0)) > tol){
 
  344            qDebug() << 
"Vector Z is not unitary! " << NORM(vz);
 
 
  373    return !is_homogeneous;
 
 
  385    if (
Get(2,0) > (1.0 - 1e-6)){
 
  388        w = atan2(-
Get(1,2), 
Get(1,1));
 
  389    } 
else if (
Get(2,0) < -1.0 + 1e-6){
 
  392        w = atan2(
Get(1,2),
Get(1,1));
 
  394        p = atan2(-
Get(2, 0), sqrt(
Get(0, 0) * 
Get(0, 0) + 
Get(1, 0) * 
Get(1, 0)));
 
  395        w = atan2(
Get(1, 0), 
Get(0, 0));
 
  396        r = atan2(
Get(2, 1), 
Get(2, 2));
 
  401    xyzwpr[3] = r*180.0/M_PI;
 
  402    xyzwpr[4] = p*180.0/M_PI;
 
  403    xyzwpr[5] = w*180.0/M_PI;
 
 
  405QString 
Mat::ToString(
const QString &separator, 
int precision, 
bool xyzwpr_only)
 const {
 
  407        return "Mat(Invalid)";
 
  411        str.append(
"Warning!! Pose is not homogeneous! Use Mat::MakeHomogeneous() to make this matrix homogeneous\n");
 
  413    str.append(
"Mat(XYZRPW_2_Mat(");
 
  417    str.append(QString::number(xyzwpr[0],
'f',precision));
 
  418    for (
int i=1; i<6; i++){
 
  419        str.append(separator);
 
  420        str.append(QString::number(xyzwpr[i],
'f',precision));
 
  428    for (
int i=0; i<4; i++){
 
  430        for (
int j=0; j<4; j++){
 
  431            str.append(QString::number(row(i)[j], 
'f', precision));
 
  433                str.append(separator);
 
 
  441    QString pose_str2(pose_str.trimmed());
 
  442    if (pose_str2.startsWith(
"Mat(",Qt::CaseInsensitive)){
 
  443        pose_str2.remove(0, 4).trimmed();
 
  445    if (pose_str2.startsWith(
"XYZRPW_2_Mat(",Qt::CaseInsensitive)){
 
  446        pose_str2.remove(0, 13).trimmed();
 
  448    if (pose_str2.endsWith(
"))")){
 
  452    QStringList values_list = pose_str2.replace(
";",
",").replace(
"\t",
",").split(
",", Qt::SkipEmptyParts);
 
  453    tXYZWPR xyzwpr = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
  454    if (values_list.length() < 6){
 
  458    for (
int i=0; i<6; i++){
 
  459        QString stri(values_list.at(i));
 
  460        xyzwpr[i] = stri.trimmed().toDouble();
 
 
  467    double a = r * M_PI / 180.0;
 
  468    double b = p * M_PI / 180.0;
 
  469    double c = w * M_PI / 180.0;
 
  476    return Mat(cb * cc, cc * sa * sb - ca * sc, sa * sc + ca * cc * sb, x, cb * sc, ca * cc + sa * sb * sc, ca * sb * sc - cc * sa, y, -sb, cb * sa, ca * cb, z);
 
 
  479    return XYZRPW_2_Mat(xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]);
 
  483    Mat newmat = 
Mat::XYZRPW_2_Mat(xyzwpr[0], xyzwpr[1], xyzwpr[2], xyzwpr[3], xyzwpr[4], xyzwpr[5]);
 
  484    for (
int i=0; i<4; i++){
 
  485        for (
int j=0; j<4; j++){
 
  486            this->
Set(i,j, newmat.
Get(i,j));
 
 
  492    double* _ddata16_non_const = (
double*) 
_ddata16;
 
  493    for(
int i=0; i<16; ++i){
 
  494        _ddata16_non_const[i] = constData()[i];
 
 
  502#ifdef ROBODK_API_FLOATS 
  516    for(
int i=0; i<16; ++i){
 
  517        data[i] = constData()[i];
 
 
  521    for(
int i=0; i<16; ++i){
 
  522        data[i] = constData()[i];
 
 
  539    return Mat(1, 0, 0, 0, 0, cx, -sx, 0, 0, sx, cx, 0);
 
 
  545    return Mat(cy, 0, sy, 0, 0, 1, 0, 0, -sy, 0, cy, 0);
 
 
  551    return Mat(cz, -sz, 0, 0, sz, cz, 0, 0, 0, 0, 1, 0);
 
 
  569void emxInit_real_T(
tMatrix2D **pEmxArray, 
int numDimensions){
 
  573    emxArray = *pEmxArray;
 
  574    emxArray->
data = (
double *)NULL;
 
  576    emxArray->
size = (
int *)malloc((
unsigned int)(
sizeof(int) * numDimensions));
 
  578    emxArray->canFreeData = 
true;
 
  579    for (i = 0; i < numDimensions; i++) {
 
  580        emxArray->
size[i] = 0;
 
  586    emxInit_real_T((
tMatrix2D**)(&matrix), 2);
 
  591void emxFree_real_T(
tMatrix2D **pEmxArray){
 
  593        if (((*pEmxArray)->data != (
double *)NULL) && (*pEmxArray)->canFreeData) {
 
  594            free((
void *)(*pEmxArray)->data);
 
  596        free((
void *)(*pEmxArray)->size);
 
  597        free((
void *)*pEmxArray);
 
  608void emxEnsureCapacity(
tMatrix2D *emxArray, 
int oldNumel, 
unsigned int elementSize){
 
  617        newNumel *= emxArray->
size[i];
 
  624        while (i < newNumel) {
 
  625            if (i > 1073741823) {
 
  631        newData = (
double*) calloc((
unsigned int)i, elementSize);
 
  632        if (emxArray->
data != NULL) {
 
  633            memcpy(newData, emxArray->
data, elementSize * oldNumel);
 
  634            if (emxArray->canFreeData) {
 
  635                free(emxArray->
data);
 
  638        emxArray->
data = newData;
 
  640        emxArray->canFreeData = 
true;
 
  644void Matrix2D_Set_Size(
tMatrix2D *mat, 
int rows, 
int cols) {
 
  647    old_numel = mat->
size[0] * mat->
size[1];
 
  651    emxEnsureCapacity(mat, old_numel, 
sizeof(
double));
 
  657int Matrix2D_Size(
const tMatrix2D *var, 
int dim) { 
 
  659        return var->
size[dim - 1];
 
  665int Matrix2D_Get_ncols(
const tMatrix2D *var) {
 
  666    return Matrix2D_Size(var, 2);
 
  668int Matrix2D_Get_nrows(
const tMatrix2D *var) {
 
  669    return Matrix2D_Size(var, 1);
 
  671double Matrix2D_Get_ij(
const tMatrix2D *var, 
int i, 
int j) { 
 
  672    return var->
data[var->
size[0] * j + i];
 
  674void Matrix2D_Set_ij(
const tMatrix2D *var, 
int i, 
int j, 
double value) { 
 
  675    var->
data[var->
size[0] * j + i] = value;
 
  678double *Matrix2D_Get_col(
const tMatrix2D *var, 
int col) { 
 
  679    return (var->
data + var->
size[0] * col);
 
  683        Matrix2D_Set_Size(to, 0,0);
 
  686    int sz1 = Matrix2D_Size(from,1);
 
  687    int sz2 = Matrix2D_Size(from,2);
 
  688    Matrix2D_Set_Size(to, sz1, sz2);
 
  690    for (
int i=0; i<numel; i++){
 
  698void Matrix2D_Add(
tMatrix2D *var, 
const double *array, 
int numel){
 
  700    int size1 = var->
size[0];
 
  701    int size2 = var->
size[1];
 
  702    oldnumel = size1*size2;
 
  703    var->
size[1] = size2 + 1;
 
  704    emxEnsureCapacity(var, oldnumel, (
int)
sizeof(
double));
 
  705    numel = qMin(numel, size1);
 
  706    for (
int i=0; i<numel; i++){
 
  707        var->
data[size1*size2 + i] = array[i];
 
  713    int size1 = var->
size[0];
 
  714    int size2 = var->
size[1];
 
  715    int size1_ap = varadd->
size[0];
 
  716    int size2_ap = varadd->
size[1];
 
  717    int numel = size1_ap*size2_ap;
 
  718    if (size1 != size1_ap){
 
  721    oldnumel = size1*size2;
 
  722    var->
size[1] = size2 + size2_ap;
 
  723    emxEnsureCapacity(var, oldnumel, (
int)
sizeof(
double));
 
  724    for (
int i=0; i<numel; i++){
 
  725        var->
data[size1*size2 + i] = varadd->
data[i];
 
  729void Debug_Array(
const double *array, 
int arraysize) {
 
  732    for (i = 0; i < arraysize; i++) {
 
  733        strout.append(QString::number(array[i], 
'f', 3));
 
  734        if (i < arraysize - 1) {
 
  735            strout.append(
" , ");
 
  738    qDebug().noquote() << strout;
 
  741void Debug_Matrix2D(
const tMatrix2D *emx) {
 
  746    size1 = Matrix2D_Get_nrows(emx);
 
  747    size2 = Matrix2D_Get_ncols(emx);
 
  748    qDebug().noquote() << 
"Matrix size = " << size1 << 
" x " << size2;
 
  749    if (size1*size2 == 0){ 
return; }
 
  750    for (j = 0; j<size2; j++) {
 
  751        column = Matrix2D_Get_col(emx, j);
 
  752        Debug_Array(column, size1);
 
  756void Matrix2D_Save(QDataStream *st, 
tMatrix2D *emx){
 
  761        qint32 sizei = emx->
size[i];
 
  762        size_values = size_values * sizei;
 
  765    for (i=0; i<size_values; i++){
 
  769void Matrix2D_Save(QTextStream *st, 
tMatrix2D *emx, 
bool csv){
 
  774    size1 = Matrix2D_Get_nrows(emx);
 
  775    size2 = Matrix2D_Get_ncols(emx);
 
  777    if (size1*size2 == 0){ 
return; }
 
  779        for (j = 0; j<size2; j++) {
 
  780            column = Matrix2D_Get_col(emx, j);
 
  781            for (
int i = 0; i < size1; i++) {
 
  782                *st << QString::number(column[i], 
'f', 8) << 
", ";
 
  787        for (j = 0; j<size2; j++) {
 
  788            column = Matrix2D_Get_col(emx, j);
 
  790            for (
int i = 0; i < size1; i++) {
 
  791                *st << QString::number(column[i], 
'f', 8) << 
" ";
 
  798void Matrix2D_Load(QDataStream *st, 
tMatrix2D **emx){
 
  800        qDebug() << 
"No data to read";
 
  803    if (*emx != 
nullptr){
 
  804        Matrix2D_Delete(emx);
 
  810    qDebug() << 
"Loading matrix of dimensions: " << ndim;
 
  811    emxInit_real_T(emx, ndim);
 
  813    for (i=0; i<ndim; i++){
 
  815        size_values = size_values * sizei;
 
  816        (*emx)->size[i] = sizei;
 
  819    emxEnsureCapacity(*emx, 0, 
sizeof(
double));
 
  821    for (i=0; i<size_values; i++){
 
  823        (*emx)->data[i] = value;
 
The Mat class represents a 4x4 pose matrix. The main purpose of this object is to represent a pose in...
QString ToString(const QString &separator=", ", int precision=3, bool xyzrpw_only=false) const
Retrieve a string representation of the pose.
Mat()
Create the identity matrix.
void VX(tXYZ xyz) const
Get the X vector (N vector)
void setVX(double x, double y, double z)
Set the X vector values (N vector)
void FromXYZRPW(tXYZWPR xyzwpr)
Calculates the pose from the position and euler angles ([x,y,z,r,p,w] vector) The result is the same ...
void VY(tXYZ xyz) const
Get the Y vector (O vector)
static Mat transl(double x, double y, double z)
Return a translation matrix.
void ToXYZRPW(tXYZWPR xyzwpr) const
Calculates the equivalent position and euler angles ([x,y,z,r,p,w] vector) of the given pose Note: tr...
void setVZ(double x, double y, double z)
Set the Z vector values (A vector)
double Get(int r, int c) const
Get a matrix value.
bool Valid() const
Check if the matrix is valid.
void setVY(double x, double y, double z)
Set the Y vector values (O vector)
static Mat roty(double ry)
Return a Y-axis rotation matrix.
const double * Values() const
Get a pointer to the 16-digit array (doubles or floats if ROBODK_API_FLOATS is defined).
void setValues(double pose[16])
Set the pose values.
void Pos(tXYZ xyz) const
Get the position (T position), in mm.
bool MakeHomogeneous()
Forces 4x4 matrix to be homogeneous (vx,vy,vz must be unitary vectors and respect: vx x vy = vz)....
static Mat rotz(double rz)
Return a Z-axis rotation matrix.
const double * ValuesD() const
Get a pointer to the 16-digit double array.
double _ddata16[16]
Copy of the data as a double array.
bool FromString(const QString &str)
Set the matrix given a XYZRPW string array (6-values)
double _valid
Flags if a matrix is not valid.
Mat inv() const
Invert the pose (homogeneous matrix assumed)
void setPos(double x, double y, double z)
Set the position (T position) in mm.
void VZ(tXYZ xyz) const
Get the Z vector (A vector)
bool isHomogeneous() const
Returns true if the matrix is homogeneous, otherwise it returns false.
const float * ValuesF() const
Get a pointer to the 16-digit array as an array of floats.
void Set(int r, int c, double value)
Set a matrix value.
static Mat rotx(double rx)
Return the X-axis rotation matrix.
static Mat XYZRPW_2_Mat(double x, double y, double z, double r, double p, double w)
Calculates the pose from the position and euler angles ([x,y,z,r,p,w] vector) The result is the same ...
The tJoints class represents a joint position of a robot (robot axes).
int GetValues(double *joints)
GetValues.
tJoints(int ndofs=0)
tJoints
QString ToString(const QString &separator=", ", int precision=3) const
Retrieve a string representation of the joint values.
int Length() const
Number of joint axes of the robot (or degrees of freedom)
const double * Values() const
Joint values.
bool Valid()
Check if the joints are valid. For example, when we request the Inverse kinematics and there is no so...
int _nDOFs
number of degrees of freedom
const double * ValuesD() const
Joint values.
double _Values[RDK_SIZE_JOINTS_MAX]
joint values (doubles, used to store the joint values)
bool FromString(const QString &str)
Set the joint values given a comma-separated string. Tabs and spaces are also allowed.
void setLength(int new_length)
Set the length of the array (only shrinking the array is allowed)
float _ValuesF[RDK_SIZE_JOINTS_MAX]
joint values (floats, used to return a copy as a float pointer)
const float * ValuesF() const
Joint values.
void SetValues(const double *joints, int ndofs=-1)
Set the joint values in deg or mm. You can also important provide the number of degrees of freedom (6...
The tMatrix2D struct represents a variable size 2d Matrix. Use the Matrix2D_... functions to oeprate ...
double * data
Pointer to the data.
int * size
Pointer to the size array.
int allocatedSize
Allocated size.
int numDimensions
Number of dimensions (usually 2)