Library initialization within a header

Hello,

I am writing a library but am confused on how I should initialize another library within the header file.

For example, lets say I have an object that is initialized as Surgeon s(int a, String b), within the cpp file I can initialize it that way, but what should I write in the header file?

Thanks,

aaddcc

but what should I write in the header file?

Which header file? The one for the Surgeon class?

Yes, I'm actually having a different issue now. I realize I could just type pretty much what I had up there.

Now I am trying to use the PID object within a robot class. I've initialized it fine, but whenever I do leftpid.Compute() or call anything from the PID class I get this error?

D:\Dropbox\slingshot\Arduino\libraries\robot\robot.cpp: In member function 'void robot::setup()': D:\Dropbox\slingshot\Arduino\libraries\robot\robot.cpp:27: error: '((robot*)this)->robot::leftPID' does not have class type

Your code and errors in full?

The errors above are the only ones. Here is the code:

#include "robot.h"
#include "Arduino.h"
#include "Servo.h"
#include <PID_v1.h>

  robot::robot() {
  	Servo servo[3];
  	char l[] = "lmr";
	double enc[3] = {0, 0, 0};
	setupPID();
  }
  void robot::setupPID() {
	double servoSpeed[] = {1,1,1};
	double rotationWanted[] = {0, 0, 0};
	double kp[3] = {.15, .2, .10};
	double kd[3] = {.2, .2, .1};
	double ki[3] = {0, 0, 0};
	double p[] = {0, 0, 0};
	PID leftPID(&enc[0], &servoSpeed[0], &rotationWanted[0], kp[0],kd[0],ki[0], DIRECT);
	PID middlePID(&enc[1], &servoSpeed[1], &rotationWanted[1], kp[1],kd[1],ki[1], DIRECT);
	PID rightPID(&enc[2], &servoSpeed[2], &rotationWanted[2], kp[2],kd[2],ki[2], DIRECT);
  }
  void robot::setup() {
  	for(int i=0;i<3;i++) {
      servo[i].write(90);
    }
	
	//part that errors
	leftPID.Compute();
  }
  void robot::servSpeed(float speed[3]) {
  	for(int i=0;i<3;i++) {
  		servo[i].write(speed[i]);
  		
  	}
  }
  void robot::processEncoders() {
	Serial.println(enc[0]);
	Serial.println(enc[1]);
	Serial.println(enc[2]);
  }
void robot::updateEncoders(int en1, int en2, int en3) {
	enc[0] = en1;
	enc[1] = en2;
	enc[2] = en3;
}
#ifndef robot_h
#define robot_h

#include "Arduino.h"
#include "Servo.h"
#include <PID_v1.h>

class robot {
  public:
    robot();
    Servo servo[3];
    void setup();
    int pin[3];
    void servSpeed(float speed[3]);
    char l[3];
	void processEncoders();
	void updateEncoders(int en1, int en2, int en3);
	double enc[3];
	PID leftPID(double* d1, double* d2, double* d3, int i1, int i2, int i3);
	PID rightPID(double* d1, double* d2, double* d3, int i1, int i2, int i3);
	PID middlePID(double* d1, double* d2, double* d3, int i1, int i2, int i3);
	void setupPID();
  private:
	double rotationWanted[3];
	double servoSpeed[3];
};
#endif

Where is your sketch?

What is the purpose of creating three local variables, of type PID, in the constructor that go out of scope when the constructor ends?

Of course the call to leftPID errors. leftPID doesn't exist in that scope.

Well the sketch requires me linking to other files and I figured it's easier to just post this cause its where the error actually occurs. How is it out of scope if I declared it as a public variable in the header file? I can access all other variables in the same way as long as my header says its public

How is it out of scope if I declared it as a public variable in the header file?

You declared a function that returns a variable of type PID:

    PID leftPID(double* d1, double* d2, double* d3, int i1, int i2, int i3);

You did not create an instance of the class PID.

You did that here:

  void robot::setupPID() {
    double servoSpeed[] = {1,1,1};
    double rotationWanted[] = {0, 0, 0};
    double kp[3] = {.15, .2, .10};
    double kd[3] = {.2, .2, .1};
    double ki[3] = {0, 0, 0};
    double p[] = {0, 0, 0};
    PID leftPID(&enc[0], &servoSpeed[0], &rotationWanted[0], kp[0],kd[0],ki[0], DIRECT);
    PID middlePID(&enc[1], &servoSpeed[1], &rotationWanted[1], kp[1],kd[1],ki[1], DIRECT);
    PID rightPID(&enc[2], &servoSpeed[2], &rotationWanted[2], kp[2],kd[2],ki[2], DIRECT);
  } // All 3 instances of the PID class go out of scope here.

Ahh that makes perfect sense. In that case how can I define a public variable for PID? Would it make more sense to just use a pointer as a public variable if I wanted to? How can I declare leftPID as a PID instance that can be accessesed by all of robots methods?

Thanks for your help!

How can I declare leftPID as a PID instance that can be accessesed by all of robots methods?

You have to declare that leftPID is a variable of type PID, in the header file.

    public:
        PID leftPID;
        PID middlePID;
        PID rightPID;

Then, in the source file, you need to value leftPID at the same time you call your constructor:

robot::robot(), leftPID(some arguments), middlePID(some arguments), rightPID(some arguments)
{
}

Paul, thanks for all of your help. This is making more sense now. However, I have not seen something be initialized this way. I did some searching and came upon initialization list, is that different than this?

in those examples, they were using base classes though as indicated by something like robot::robot : base_class1(info), base_class2(info). Is that similar to what is happening here? Is there a different term for this so I know where I can look up information about this? Would I only use the single colon if my header was like:

class robot : public base_class1 {}

? Obviously that's not what I'm doing, but that's what the examples of initialization lists I found were doing.

I first learned object oriented programming with Java so I'm not so used to this.

Thanks again for your help!

I did some searching and came upon initialization list, is that different than this?

No.

in those examples, they were using base classes though as indicated by something like robot::robot : base_class1(info), base_class2(info). Is that similar to what is happening here?

Similar, but not the same.

Would I only use the single colon if my header was like

Yes. The single colon is how you invoke the base class' initializer before your constructor does its thing. Following the base class constructor call, you could use the ", otherClass()" stuff.

I first learned object oriented programming with Java so I'm not so used to this.

There are fundamental difference with Java. One of which is to try to hide a lot of stuff that C++ makes clear. For that reason, I do not like Java (or C# which is Microsoft's ripoff of Java).

What if I need to initialize variables before initializing the PID? As you can see in the script I use a pointers to certain variables when I call PID. Before those variables were initialized in setupPID() but now the PID object is initialized before the robot constructor, right?

Before those variables were initialized in setupPID() but now the PID object is initialized before the robot constructor, right?

This is true, but it is irrelevant. What you are passing to the PID constructor is the address of the variable, not the value of the variable. The PID methods then know where to read from and/or write to based on the addresses.

That's true for the pointers, but what about the nonpublic variables like kp and kd? I essentially need to initialize an array before the constructor, which I'm not sure how to do unless its a static type. When I just wrote this before the constructor:

double robot::kd[3] = {.2, .2, .1};

It errored with D:\Dropbox\slingshot\Arduino\libraries\robot\robot.cpp:6: error: 'double robot::servoSpeed []' is not a static member of 'class robot'

It doesn’t make a lot of sense to put a value in an array, and then pass the array value to a function, and then have the array go out of scope.

So, skip the useless array. Simply put the values in the various PID constructor calls.

If you really want to use arrays, and a constructor like what you last poste, leftPID, etc. must be pointers and the code in the constructor would be:

	leftPID = new PID(&enc[0], &servoSpeed[0], &rotationWanted[0], kp[0],kd[0],ki[0], DIRECT);

where:

   PID *leftPID;

is in the header file.