VexIQ C++ Code Giving Errors

Hi,
I’ve just started working on learning the C++ code for IQ and keep having the issue of ‘use of undeclared identifier ‘onevent_LDownPressed_0’ (616, 16)’ below is the main bits of code.

void onevent_LDownPressed_0() {
  Brain.Screen.clearScreen();
  Brain.Screen.setCursor(1,1);
  Brain.Screen.print("DEBUG MENU");
  Brain.Screen.newLine();
  Brain.Screen.print("Battery: "+Brain.Battery.capacity(percent));
}

I also have this

int main() {
  // initialize the random number system
  srand(Brain.Timer.system());

  // register event handlers
  GetGridPos(onevent_GetGridPos_0);
  TLED.pressed(onevent_TLED_pressed_0);
  message1(onevent_message1_0);
  ShutdownAuto(onevent_ShutdownAuto_0);
  LDownPressed(onevent_LDownPressed_0);

  wait(15, msec);
  whenStarted1();
}

And this

#pragma region VEXcode Generated Robot Configuration
// Make sure all required headers are included.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>


#include "vex.h"

using namespace vex;

// Brain should be defined by default
brain Brain;


// START IQ MACROS
#define waitUntil(condition)                                                   \
  do {                                                                         \
    wait(5, msec);                                                             \
  } while (!(condition))

#define repeat(iterations)                                                     \
  for (int iterator = 0; iterator < iterations; iterator++)
// END IQ MACROS


// Robot configuration code.
controller Controller = controller();
motor LeftDriveSmart = motor(PORT7, 1, false);
motor RightDriveSmart = motor(PORT6, 1, true);
drivetrain Drivetrain = drivetrain(LeftDriveSmart, RightDriveSmart, 200, 173, 76, mm, 1);
motor Lyft = motor(PORT1, true);
motor Spinner = motor(PORT10, true);
touchled TLED = touchled(PORT11);
gyro Gyroschopic = gyro(PORT12);
colorsensor GridPosSys = colorsensor(PORT9);



// define variable for remote controller enable/disable
bool RemoteControlCodeEnabled = true;
// define variables used for controlling motors based on controller inputs
bool eButtonsControlMotorsStopped = true;
bool fButtonsControlMotorsStopped = true;
bool DrivetrainLNeedsToBeStopped_Controller = true;
bool DrivetrainRNeedsToBeStopped_Controller = true;

// define a task that will handle monitoring inputs from Controller
int rc_auto_loop_function_Controller() {
  // process the controller input every 20 milliseconds
  // update the motors based on the input values
  while(true) {
    if(RemoteControlCodeEnabled) {
      
      // calculate the drivetrain motor velocities from the controller joystick axies
      // left = AxisA + AxisC
      // right = AxisA - AxisC
      int drivetrainLeftSideSpeed = Controller.AxisA.position() + Controller.AxisC.position();
      int drivetrainRightSideSpeed = Controller.AxisA.position() - Controller.AxisC.position();
      
      // check if the value is inside of the deadband range
      if (drivetrainLeftSideSpeed < 5 && drivetrainLeftSideSpeed > -5) {
        // check if the left motor has already been stopped
        if (DrivetrainLNeedsToBeStopped_Controller) {
          // stop the left drive motor
          LeftDriveSmart.stop();
          // tell the code that the left motor has been stopped
          DrivetrainLNeedsToBeStopped_Controller = false;
        }
      } else {
        // reset the toggle so that the deadband code knows to stop the left motor nexttime the input is in the deadband range
        DrivetrainLNeedsToBeStopped_Controller = true;
      }
      // check if the value is inside of the deadband range
      if (drivetrainRightSideSpeed < 5 && drivetrainRightSideSpeed > -5) {
        // check if the right motor has already been stopped
        if (DrivetrainRNeedsToBeStopped_Controller) {
          // stop the right drive motor
          RightDriveSmart.stop();
          // tell the code that the right motor has been stopped
          DrivetrainRNeedsToBeStopped_Controller = false;
        }
      } else {
        // reset the toggle so that the deadband code knows to stop the right motor next time the input is in the deadband range
        DrivetrainRNeedsToBeStopped_Controller = true;
      }
      
      // only tell the left drive motor to spin if the values are not in the deadband range
      if (DrivetrainLNeedsToBeStopped_Controller) {
        LeftDriveSmart.setVelocity(drivetrainLeftSideSpeed, percent);
        LeftDriveSmart.spin(forward);
      }
      // only tell the right drive motor to spin if the values are not in the deadband range
      if (DrivetrainRNeedsToBeStopped_Controller) {
        RightDriveSmart.setVelocity(drivetrainRightSideSpeed, percent);
        RightDriveSmart.spin(forward);
      }
      // check the ButtonEUp/ButtonEDown status to control Lyft
      if (Controller.ButtonEUp.pressing()) {
        Lyft.spin(forward);
        eButtonsControlMotorsStopped = false;
      } else if (Controller.ButtonEDown.pressing()) {
        Lyft.spin(reverse);
        eButtonsControlMotorsStopped = false;
      } else if (!eButtonsControlMotorsStopped) {
        Lyft.stop();
        // set the toggle so that we don't constantly tell the motor to stop when the buttons are released
        eButtonsControlMotorsStopped = true;
      }
      // check the ButtonFUp/ButtonFDown status to control Spinner
      if (Controller.ButtonFUp.pressing()) {
        Spinner.spin(forward);
        fButtonsControlMotorsStopped = false;
      } else if (Controller.ButtonFDown.pressing()) {
        Spinner.spin(reverse);
        fButtonsControlMotorsStopped = false;
      } else if (!fButtonsControlMotorsStopped) {
        Spinner.stop();
        // set the toggle so that we don't constantly tell the motor to stop when the buttons are released
        fButtonsControlMotorsStopped = true;
      }
    }
    // wait before repeating the process
    wait(20, msec);
  }
  return 0;
}

task rc_auto_loop_task_Controller(rc_auto_loop_function_Controller);

#pragma endregion VEXcode Generated Robot Configuration

Try adding parenthesis after the zero, like this:

// register event handlers
  GetGridPos(onevent_GetGridPos_0());
  TLED.pressed(onevent_TLED_pressed_0());
  message1(onevent_message1_0());
  ShutdownAuto(onevent_ShutdownAuto_0());
  LDownPressed(onevent_LDownPressed_0());

can you show us line 616? I think it means an error on line 616, and we can use that.

If this line of code below is line 616, then I know the issue

Brain.Screen.print("Battery: "+Brain.Battery.capacity(percent));

C++ is basically C with add ons. in C and C++ (but more commonly used in C) there is a function called printf(). I am very sure that VEX uses the same idea as printf for Brain.Screen.print().

If what I said above is correct, then your issue is that you can’t add the +Brain.Battery.capacity(percent), but instead you need to have this:

Brain.Screen.print("Battery: %d", static_cast<int>(Brain.Battery.capacity(percent)));

Side note that you might want to read: You may have noticed instead of just Brain.Battery.capacity(percent)));, I used a static cast. I don’t think you need to use a static cast. Instead, you can write this:
Brain.Screen.print("Battery: %d", Brain.Battery.capacity(percent));

1 Like

Line 616 is this

LDownPressed(onevent_LDownPressed_0);

@hazem
That results in these errors.

no matching function for call to object or type 'vex::event' (611, 3)
cannot initialize a parameter of the 'void (*)()' with an rvalue of type 'void' (612, 16)
error: (613, 3)
no matching function to call to object of event 'vex::event' (616, 3)

It would, that was incorrect advise.

Without seeing all the code it’s hard to tell what the issue is.
has LDownPressed been declared as an event somewhere ?

It looks like you started with block code and perhaps converted to C++. Block code does not create very good or well structured C++ code, it’s also overly verbose due to how the code generation works.

1 Like

Fixed It.
I’m pretty sure it was just the syntax.
Here’s the fix.

Controller.ButtonLDown.pressed(onevent_ControllerButtonLDown_pressed_0);

and

void onevent_ControllerButtonLDown_pressed_0() {
  Brain.Screen.clearScreen();
  Brain.Screen.setCursor(1,1);
  Brain.Screen.print("DEBUG MENU");
  Brain.Screen.newLine();
  Brain.Screen.print("Battery: "+Brain.Battery.capacity(percent));
}

I apologize for the mistake. I thought you were supposed to put parenthesis after calling a function, which you are, but I’d like to know why not in this case

It’s because that’s for defining the functions(I’m pretty sure) and including the ()'s after the name is what you use when you add a condition to the variable.

Er no. not exactly.

using

Controller.ButtonLDown.pressed

or when using one of the other functions that allow setting the event handler after an event has been created (used by the broadcast blocks)

You need to pass the address of the function that will be called, just using the function name without parens allows this. If you were to add the parens

 Controller.ButtonLDown.pressed( foo() );

What you are saying is call the function foo and use the return value from that function as the parameter to Controller.ButtonLDown.pressed.

3 Likes

Different C++ basic language problem. This throws an error, and seems a primitive that the compiler would handle.
ssfb=(AxisAposition**2)/100. (using 2.0 also fails) Circumvention easy with “AxisAposition*AxisAposition” and then handle the sign, but I thought the primitives were all implemented…

**

is not a power operator in C or C++, use the pow function.

1 Like

confirmed, pow(double,double) works.

Different implementation question. No doc on how to “unhandle” an event. Therefore, even through main() finishes, the brain app is still engaged and must be manually started. How can you disconnect your event (e.g., TouchLED.pressed() )

You can’t.

On V5 there’s a way to reset events via competition class when the robot becomes disabled, but in general, once registered events are set until the program exits. Obviously no competition control on IQ so not available there.

even through main() finishes

Main is really just another thread, other threads and event handlers will continue to run even if main returns, that helps students who forget to put a blocking loop at the end of main.

2 Likes

Thanks for pointing that out!!

On events, this successfully compiles; TouchLED.pressed(0); . I had hoped TouchLED.pressed(null); would have worked, but didn’t.
Couldn’t you use the zero as acceptable and unhandle function? That should end the listening thread(s), and so a Event cleanups could successfully stop the brain… Not an illogical implementation, as you may WANT TO use this to stop for a while, and then restart later (with a different function).

It would require a major overhaul of the event system in vexos, not happening any time soon.

1 Like

So, on the wish list; great!!! Can you at least complete the app design, so we can code to it, and it just won’t really unhandle??
In the codeIQ doc, could you add that unhandle not (yet) implemented?

Nope, that’s not what I said.

What I said was

not happening any time soon.

which was a polite way of saying, “we are not changing the design”

1 Like

I did read between the lines, but one last attempt to get it started!
At least put in codeIQ there is no way to “unhandle”; I wasted days trying to find out where it was…
Enjoy the Superbowl. I was a little disappointed at the compiler design, but it’s a game; you work with what your given…