0

I have been trying to resolve an undefined reference error for hours caused by my 2D array, but I don't know what I am missing. I have a 2D array.

#include <iostream>
#include "ServoJoint.h"
#include "JointedLeg.h"
#include "TwoJointLeg.h"
#include "ThreeJointLeg.h"

int main() {

    //2D array containing the 7 calibrated positions for each of the 10 servo motors
    size_t servoCalibrations[10][7]={{143, 190, 245, 305, 365, 410, 467},
                                     {143, 205, 260, 320, 377, 423, 475},
                                     {115, 168, 230, 280, 340, 392, 440},
                                     {130, 182, 235, 290, 340, 397, 455},
                                     {135, 190, 235, 290, 345, 400, 455},
                                     {140, 190, 250, 305, 355, 415, 465},
                                     {130, 185, 240, 300, 355, 415, 465},
                                     {140, 200, 245, 300, 355, 410, 460},
                                     {140, 200, 245, 300, 355, 410, 460},
                                     {140, 200, 245, 300, 355, 410, 460}};

    double walkCycle[4][2]= {{45, 45},
                            {60, 150},
                            {60, 135},
                            {30, 60}};

    //Array of pointers to 10 size_t arrays of size 7
    //This is because C++ doesn't allow accessing an entire row/column of a 2D array
    //or I don't know how to
    size_t * calibrationArrays[10];
    for(size_t i=0; i<10; i++){
        size_t * tmp= new size_t[7];
        for(size_t j=0; j<7; j++){
            tmp[j]= servoCalibrations[i][j];
        }
        calibrationArrays[i]= tmp;
    }

    //Array of pointers to 10 ServoJoint objects
    ServoJoint * servoJoints[10];

    //Dynamically allocate 10 ServoJoint objects
    for(size_t i=0; i<10; i++){
        servoJoints[i]= new ServoJoint(i, 7, calibrationArrays[i]);
    }

    for(size_t i=0; i<10; i++){
        std::cout << "Servo motor " << i+1 << " has the following PWM values: ";
        for(size_t j=0; j<7; j++){
            std::cout << servoJoints[i]->getPWM(-90+(double)(j*30)) << " ";
        }
        std::cout<< std::endl;
    };

    //Array of pointers to 2 ThreeJointLeg objects
    ThreeJointLeg * threeJointLegs[2];

    //Dynamically allocate 2 ThreeJointLeg objects
    for(size_t i=0; i<6; i+=3){
        threeJointLegs[i]= new ThreeJointLeg(servoJoints[i], servoJoints[i+1], servoJoints[i+2], 1-(i%2)*2, walkCycle);
    }

    //Array of pointers to 2 TwoJointLeg objects
    TwoJointLeg * twoJointLegs[2];

    //Dynamically allocate 2 TwoJointLeg objects
    for(size_t i=6; i<10; i+=2){
        twoJointLegs[i]= new TwoJointLeg(servoJoints[i],servoJoints[i+1], 1, walkCycle);
    }

    return 0;
}

JointedLeg.h:

#ifndef ROBOTLEG_JointedLeg_H
#define ROBOTLEG_JointedLeg_H

#include "ServoJoint.h"

class JointedLeg{

private:
//Pointers to the 2 ServoJoint objects for the upper and lower joint
ServoJoint * upperJoint;
ServoJoint * lowerJoint;

int isRight;

//2D array, where each of the four rows represents each phase in the walk cycle and each column of each row
//represents the upper and lower joint angles respectively

//walkCycle[0][]= home
//walkCycle[1][]= step forward
//walkCycle[2][]= step down
//walkCycle[3][]= step back
double walkCycle[4][2];

public:
JointedLeg(ServoJoint * joint1, ServoJoint * joint2, int side, double givenWalk[][2]);

JointedLeg.cpp:

#include "JointedLeg.h"

JointedLeg::JointedLeg(ServoJoint * joint1, ServoJoint * joint2, int side, double givenWalk[][2]):upperJoint(joint1), lowerJoint(joint2), isRight(side){
    for(size_t i=0; i<4; i++){
        for(size_t j=0; j<2; j++){
            walkCycle[i][j]= givenWalk[i][j];
        }
    }
}

TwoJointLeg.h:

#ifndef QUADRUPEDROBOT_TWOJOINTLEG_H
#define QUADRUPEDROBOT_TWOJOINTLEG_H

#include "JointedLeg.h"

class TwoJointLeg : public JointedLeg{

public:
    TwoJointLeg(ServoJoint * joint1, ServoJoint * joint2, int side, double givenWalk[][2]);

};

#endif //QUADRUPEDROBOT_TWOJOINTLEG_H

TwoJointLeg.cpp:

#include "TwoJointLeg.h"

TwoJointLeg::TwoJointLeg(ServoJoint * joint1, ServoJoint * joint2, int side, double givenWalk[][2])
        :JointedLeg(joint1, joint2, side, givenWalk){}

and I wish to pass this as a parameter to the following constructor:

JointedLeg(ServoJoint * joint1, ServoJoint * joint2, int side, double givenWalk[][2]);

I read on Passing a 2D array to a C++ function that when I declare a 2D array with 2 brackets, i.e. [][], I can do the same in the function header and simply pass the array variable name, which is what I believe I have done.

However, my compiler keeps telling me that I am passing a "double (*) [2]." I am aware that a 2D array is technically a pointer to sub-arrays and that the first array can be decayed to a pointer, but why is there a mismatch in the parameter type when I have the same syntax in the function call and the definition?

I've tried both of these in the function header:

double givenWalk[4][2]
double givenWalk[][2]
Community
  • 1
  • 1
Skipher
  • 205
  • 2
  • 13
  • Cannot reproduce; works for me. Please show an example where you define the class as well as the code where you call the function. – Stephan Lechner Mar 31 '17 at 06:04
  • You're using `&walkCycle` in the call; you should be using just `walkCycle`. When you use `&walkCycle`, you are passing a pointer to an array, which is written `double (*)[2]`. – Jonathan Leffler Mar 31 '17 at 06:08
  • @JonathanLeffler am I implicitly using &walkCycle? I do not see an ampersand in my code. – Skipher Mar 31 '17 at 06:15
  • You hadn't shown most of your code when I wrote the comment. It remains true that if you wrote `&walkCycle`, you would be passing a `double (*)[2]` (unless the matrix definition has changed while I wasn't watching). But I've not correlated it with any line of code since you've not identified the line of code triggering the complaint. Your `JointedLeg.h` header is incomplete — there isn't a close brace for the class. Please create a minimal MCVE ([MCVE]) that triggers the problem — trying to create it will probably allow you to resolve the problem anyway. – Jonathan Leffler Mar 31 '17 at 14:56

2 Answers2

0

See the following minimal example, which shows that it works:

void JointedLeg(double givenWalk[][2]) { }

int main(int argc, char* argv[]) {

    double walkCycle[4][2]= {{45, 45},
        {60, 150},
        {60, 135},
        {30, 60}};

    JointedLeg(walkCycle);

    return 0;
}
Stephan Lechner
  • 33,675
  • 4
  • 27
  • 49
0

Look at your array indexes that you used in cycles:

//Array of pointers to 2 ThreeJointLeg objects
ThreeJointLeg * threeJointLegs[2];

//Dynamically allocate 2 ThreeJointLeg objects
for(size_t i=0; i<6; i+=3){
    threeJointLegs[i/3]= new ThreeJointLeg(servoJoints[i], servoJoints[i+1], servoJoints[i+2], 1-(i%2)*2, walkCycle);
}

//Array of pointers to 2 TwoJointLeg objects
TwoJointLeg * twoJointLegs[2];

//Dynamically allocate 2 TwoJointLeg objects
for(size_t i=6; i<10; i+=2){
    twoJointLegs[(i-6)/2]= new TwoJointLeg(servoJoints[i],servoJoints[i+1], 1, walkCycle);
}
user3811082
  • 198
  • 1
  • 7