Accessing class instance variables and methods from another class instance

Hi,

Trying to access the public variables and methods of one class instance from another class instance, and currently have the following errors:

..HPLRover_Motors.cpp.cpp:5: error: expected initializer before '&' token
..HPLRover_Motors.cpp.cpp: In member function 'void HPLRover_Motors::output()':
..HPLRover_Motors.cpp.cpp:15: error: 'hplrover_radio' was not declared in this scope

As you can see in the main sketch I create an instance of HPLRover_Radio as hplrover_radio. I execute to get commands from a serial stream.

I want to access both the public variables and methods in the instance of HPLRover_Radio from the instance of HPLRover_Motors.

I currently am not obviously properly referencing back to the instance created in the main sketch. I guess anothejr alternative would be to pass the pointer to the radio instance to the motors instance?

Most grateful for your help, still getting to grips with C++ as you can see! Of course any other criticisms of my code are most welcome.

Here is the code from the main sketch

#include <HPLRover_Common.h>

#include <Event.h>
#include <Timer.h>


#include <HPLRover_Radio.h>
#include <HPLRover_Motors.h>


HPLRover_Radio hplrover_radio;
HPLRover_Motors hplrover_motors;

Timer scheduler;

 void setup() {
  Serial.begin(9600);        

  init_commands();
 
  scheduler.every(1000, one_second_loop, 0);
  
}



// loop() is called rapidly while the sketch is running
void loop() {
 scheduler.update();
 
 fast_loop();
 
}  


void fast_loop() {
  Serial.println("fast loop");
  hplrover_radio.read_radio_data_stream();
  hplrover_motors.output();
}  
  

void one_second_loop(void* context) 
{
    Serial.println("One second loop");
}


void init_commands() {
  
  HPLRover_Radio::radio_cmd_in.velocity_rx = false;
  HPLRover_Radio::radio_cmd_in.velocity_val = 0;
  
  HPLRover_Radio::radio_cmd_in.direction_rx = false;
  HPLRover_Radio::radio_cmd_in.direction_val = 0;
  
  HPLRover_Radio::radio_cmd_in.heading_rx = false;
  HPLRover_Radio::radio_cmd_in.heading_val = 0;
  
  HPLRover_Radio::radio_cmd_in.rotate_rx = false;

  
  HPLRover_Radio::radio_cmd_in.stop_rx = false;
  HPLRover_Radio::radio_cmd_in.step_rx = false;
  
  HPLRover_Radio::radio_cmd_in.lights_mainbeam_rx = false;
  HPLRover_Radio::radio_cmd_in.lights_mainbeam_val = 0;

  HPLRover_Radio::radio_cmd_in.cam_pan_rx = false;

  HPLRover_Radio::radio_cmd_in.cam_tilt_rx = false;

  HPLRover_Radio::radio_cmd_in.cam_sweep_rx = false;
  
}

Here is the code from the HPLRover_Radio header

#ifndef HPLRover_Radio_h
#define HPLRover_Radio_h

#include "Arduino.h"

class HPLRover_Radio 
{
  public:
  
  struct data_stream_command_in_type {
        boolean velocity_rx;
		int     velocity_val;
		
		boolean direction_rx;
		char    direction_val;
		
		boolean heading_rx;
		int     heading_val;
		
		boolean rotate_rx;
		char    rotate_val;
		
		boolean stop_rx;
		boolean step_rx;
				
		boolean lights_mainbeam_rx;
		int     lights_mainbeam_val;
		
		boolean cam_pan_rx;
		char    cam_pan_val;
				
		boolean cam_tilt_rx;
		char    cam_tilt_val;
		
		boolean cam_sweep_rx;		
    };
	
	
	static struct data_stream_command_in_type radio_cmd_in;
	
	//Constructor
    HPLRover_Radio();        
	
	//Initialise the radio
	void init();
	
	void read_radio_data_stream();
	
	static void send_radio_data_stream(void* context);
	void clear_buffer();
	
	
	
  private:
	char serial_char;                                     // value for each byte read in from serial comms
	int serial_count;                                 // current length of command
	char buffer[100];                             // buffer for serial commands
	
	void stream_register(char command[], int command_length);
	
};

#endif

The HPLRover_Radio .cpp file

#include "Arduino.h"
#include "HPLRover_Radio.h"
#include "HPLRover_Common.h"


struct HPLRover_Radio::data_stream_command_in_type HPLRover_Radio::radio_cmd_in;

HPLRover_Radio::HPLRover_Radio()
{
	serial_count = 0;   
}


// Init
void HPLRover_Radio::init()
{
 
}


void HPLRover_Radio::read_radio_data_stream()
{

  Serial.println("Read radio data stream");
  
  if (Serial.available()) 
  {
    serial_char = Serial.read();                               // read individual byte from serial connection
  
    switch (serial_char) {
      case ':' :  
        buffer[serial_count] = null_terminator;
        stream_register(buffer, serial_count);
        clear_buffer();
        break;
      case ']' :
        cmd_process = true;
        break;
      default:
        buffer[serial_count] = serial_char;                   // add byte to buffer string
        serial_count++;
        if (serial_count > 100)                      // overflow, dump and restart
        {
          clear_buffer();
          Serial.flush();
        }            
    }
  }

}


void HPLRover_Radio::send_radio_data_stream(void* context)
{
  Serial.println("Send radio data stream");
}


void HPLRover_Radio::stream_register(char command[], int command_length) {   // deals with standardized input from serial connection

  if (command[0] == cmd_stop) 
  {
    HPLRover_Radio::radio_cmd_in.stop_rx = true;
  }
 
 
  if (command[0] == cmd_step) 
  {
    HPLRover_Radio::radio_cmd_in.step_rx = true;
  }
 

  if (command[0] == cmd_cam_sweep) 
  {
    HPLRover_Radio::radio_cmd_in.cam_sweep_rx = true;
  }

  
  if (command[0] == cmd_velocity) 
  {
    HPLRover_Radio::radio_cmd_in.velocity_rx = true;
    HPLRover_Radio::radio_cmd_in.velocity_val = (int)strtod(&command[1], NULL);
  }
 
  
  if (command[0] == cmd_direction) 
  {
    HPLRover_Radio::radio_cmd_in.direction_rx = true;
    HPLRover_Radio::radio_cmd_in.direction_val = command[1];
  }


  if (command[0] == cmd_cam_pan) 
  {
    HPLRover_Radio::radio_cmd_in.cam_pan_rx = true;
    HPLRover_Radio::radio_cmd_in.cam_pan_val = command[1];
  }


  if (command[0] == cmd_cam_tilt) 
  {
    HPLRover_Radio::radio_cmd_in.cam_tilt_rx = true;
    HPLRover_Radio::radio_cmd_in.cam_tilt_val = command[1];
  }
 
  
  if (command[0] == cmd_heading)
  {
    HPLRover_Radio::radio_cmd_in.heading_rx = true;
    HPLRover_Radio::radio_cmd_in.heading_val = (int)strtod(&command[1], NULL);
  }


  if (command[0] == cmd_rotate) 
  {
    HPLRover_Radio::radio_cmd_in.rotate_rx = true;
    HPLRover_Radio::radio_cmd_in.rotate_val = command[1];
  }


  if (command[0] == cmd_cam_pan) 
  {
    HPLRover_Radio::radio_cmd_in.cam_pan_rx = true;
    HPLRover_Radio::radio_cmd_in.cam_pan_val = (int)strtod(&command[1], NULL);
  }


  if (command[0] == cmd_cam_tilt) 
  {
    HPLRover_Radio::radio_cmd_in.cam_tilt_rx = true;
    HPLRover_Radio::radio_cmd_in.cam_tilt_val = (int)strtod(&command[1], NULL);
  }

  if (command[0] == cmd_lights_mainbeam) 
  {
    HPLRover_Radio::radio_cmd_in.lights_mainbeam_rx = true;
    HPLRover_Radio::radio_cmd_in.lights_mainbeam_val = command[1];
  }

}


void HPLRover_Radio::clear_buffer() { // empties command buffer from serial connection

  serial_count = 0; // reset buffer placement
  buffer[serial_count] = null_terminator; 
}

The HPLRover_Motors header file

#ifndef HPLRover_Motors_h
#define HPLRover_Motors_h

#include "Arduino.h"

class HPLRover_Motors
{
  public:
    HPLRover_Motors();        //Constructor
	void output();
};

#endif

And finally the HPLRover_Motors .cpp file

#include "Arduino.h"
#include "HPLRover_Motors.h"
#include <HPLRover_Radio.h>

extern const HPLRover_Radio::hplrover_radio& hplrover_radio;

HPLRover_Motors::HPLRover_Motors()
{
}

void HPLRover_Motors::output()
{

  Serial.println("Motor output");
  hplrover_radio->clear_buffer();

}

Try changing your extern to:

extern HPLRover_Radio hplrover_radio;

and change your call to:

hplrover_radio.clear_buffer();

Alternatively you could pass a pointer to the Radio object to the Motor object and save the pointer as Motor object data.

I think you should examine WHY the Motor object needs control over the Radio object. It makes little sense. Perhaps you should move that behavior up a level and create a Rover object that has Motor and Radio objects and controls the interactions.

  hplrover_motors.output();

How is the output() method supposed to know which instance of the HPLRover_Radio class it is to operate with?

extern const HPLRover_Radio::hplrover_radio& hplrover_radio;

The HPLRover_Radio class does not have a field called hplrover_radio.

Rather than trying to couple the two instances this way, the output() method should accept a pointer to an instance of, or an object of, the radio class it is top operate with.

@John - Thanks very much, that worked. Indeed, the call to the radio output was only an "access" test - the motor just needs to know if any motor commands were received by inbound radio comms - I will probably re-organise to create a command stream class the motor can access, to separate the radio from the motor.

@Paul - I agree, it would be preferable to pass a pointer of the instance. I have tried and failed miserably, by chaning the main sketch with a new declaration of radio:

HPLRover_Radio *radio;

radio = &hplrover_radio;

I get the error:

expected constructor, destructor, or type conversion before '=' token

And further down upon call to hplrover_motors.output I'm not sure how to reference radio (using * or &, I need to go back to some basics with a C++ book which will be done this weekend!).

I would most appreciate an example, many thanks.

I have tried and failed miserably, by chaning the main sketch with a new declaration of radio:

Speaking of failing miserably, snippets don't cut it here.

Grumpybeard:

HPLRover_Radio *radio;

radio = &hplrover_radio;

If that's global code, you can't just make a variable assignment like that. Read up on the distinction between including initialisation data in a variable definition, and making an assignment to a variable after it has been defined.

What you're trying to achieve may be:

HPLRover_Radio *radio = &hplrover_radio;

Although I can't imagine why you would want to define a global pointer to a global variable.

PaulS:

I have tried and failed miserably, by chaning the main sketch with a new declaration of radio:

Speaking of failing miserably, snippets don't cut it here.

Apologies, I didn't want to repeat the whole sketch with just two changed lines. In any case I have resolved, with a change to call of motors.output in function fast_loop in the main sketch:

void fast_loop() {
  Serial.println("fast loop");
  hplrover_radio.read_radio_data_stream();
 hplrover_motors.output(hplrover_radio);
}

A change to the HPLRover_Motors .h file:

#include <HPLRover_Radio.h>

class HPLRover_Motors
{
  public:
    HPLRover_Motors();        //Constructor
	void output(HPLRover_Radio &radio);
};

And changes to the HPLRover_Motors .cpp file to test access to public variable of passed motors instance:

void HPLRover_Motors::output(HPLRover_Radio &radio)
{
  Serial.println("Motor output");
  Serial.println(radio.radio_cmd_in.stop_rx);  
}

Thanks.

@PeterH - Yes I was making quite a mess of it through my trials and errors in trying to obtain a pointer to pass! More reading up required. Thanks for the contribution anyway, I believe I have resolved now as earlier posted by directly passing hplrover_radio and using the reference operator & in the called method..