Motors in multiple motor groups

Was curious, I know the GUI of adding motor groups doesn’t allow for motors to be part of multiple motor groups, but if you write it out in the competition template (for like your own smart drive train) would it work?

We’re trying to see if we could use motor groups to create strafing with mecanum wheels or x drives.

I know VEXcode doesn’t support it, but thought I’d ask.

Yes, a motor can be included in more than one motor group. Not sure I would program an X drive that way though.

4 Likes

Any suggestions? Trying to use the same smart drive we used last year for ease of use, only way I can think of doing is to make a third and fourth motor groups with separate motors.

This is what I was thinking of trying, not sure if it will work:

motor_group LeftSide(leftFront, leftBack);

motor_group RightSide(rightFront,rightBack);

motor_group Strafe2(rightFront, leftBack);

motor_group Strafe1(leftFront, rightBack);

motor_group ArmsTog(armLeft, armRight);

inertial Inertial16=inertial(PORT16);

smartdrive robotDrive(LeftSide, RightSide, Inertial16, 12.56, 16, 16, distanceUnits::in);

smartdrive sideDrive(Strafe1, Strafe2, Inertial16, 12.56, 16, 16, distanceUnits::in);

It would probably work, as long as you only used commands for one or the other at a time.
An alternative may be to create a new sub class and add the functionality you want, more complicated but may have better long term capability. something along these lines perhaps.

smartdrive for x drive class
class smartdrive_x : public smartdrive {
    private:
      vex::motor  &m_lf;
      vex::motor  &m_lb;
      vex::motor  &m_rf;
      vex::motor  &m_rb;
      vex::motor_group m_l;
      vex::motor_group m_r;

      motor_group &set_lm( motor &m1, motor &m2 ) {
        return (m_l = motor_group(m1, m2));
      }
      motor_group &set_rm( motor &m1, motor &m2 ) {
        return (m_r = motor_group(m1, m2));
      }
      
    public:
      // adjust defaults as necessary
      smartdrive_x( motor &m_lf, motor &m_lb, motor &m_rf, motor &m_rb, vex::guido &g, double wheelTravel=200, double trackWidth=150, double wheelBase=150, distanceUnits unit=distanceUnits::mm, double externalGearRatio = 1.0 )
      : smartdrive( set_lm(m_lf, m_lb), set_rm(m_rf, m_rb), g, wheelTravel, trackWidth, wheelBase, unit, externalGearRatio), 
        m_lf(m_lf),
        m_lb(m_lb),
        m_rf(m_rf),
        m_rb(m_rb) {
      }

      ~smartdrive_x(){}

      void xdrive( int fwd_back, int turn, int right_left ) {
        // Set drive
        int drive_l_front = fwd_back + turn + right_left;
        int drive_l_back  = fwd_back + turn - right_left;

        int drive_r_front = fwd_back - turn - right_left;
        int drive_r_back  = fwd_back - turn + right_left;

        // normalize drive so max is 100 if any drive is over 100
        int max = abs(drive_l_front);
        if (abs(drive_l_back)  > max)
            max = abs(drive_l_back);
        if (abs(drive_r_back)  > max)
            max = abs(drive_r_back);
        if (abs(drive_r_front) > max)
            max = abs(drive_r_front);
        if (max>100) {
            drive_l_front = 100 * drive_l_front / max;
            drive_l_back  = 100 * drive_l_back  / max;
            drive_r_back  = 100 * drive_r_back  / max;
            drive_r_front = 100 * drive_r_front / max;
        }
        
        m_lf.spin( forward, drive_l_front, percent );
        m_lb.spin( forward, drive_l_back , percent );
        m_rf.spin( forward, drive_r_front, percent );
        m_rb.spin( forward, drive_r_back , percent );
      }

      void strafe( int right_left ) {
        xdrive(0, 0, right_left);
      }
};

initialization of the motor groups is a little messy as you have to create them before the base class constructor is called. Motors are saved in some private variables to be used as desired.

you would use it like this. (this is EXP code, change the inertial sensor for V5)

// motors for mecanum drive
motor       mlf(PORT1);
motor       mlb(PORT2);
motor       mrf(PORT4, true);
motor       mrb(PORT5, true);

// internal imu on EXP
inertial    imu1;

controller  Controller(primary);

smartdrive_x sd( mlf, mlb, mrf, mrb, imu1 );

int main() {
    sd.turnToHeading( 90, degrees );
    Brain.Screen.printAt(10, 10, "done");

    while(1) {
      int fwd_back   = Controller.Axis3.position();
      int turn       = Controller.Axis4.position();
      int right_left = Controller.Axis1.position();

      sd.xdrive( fwd_back, turn, right_left );

      // Allow other tasks to run
      this_thread::sleep_for(20);
    }
}

that doesn’t give you any “strafeFor” distance or anything, but you could add those functions to the class as needed. The smartdrive turnFor etc. will work as usual.

5 Likes

Thats kinda over my head currently, need to break it down slowly for myself later. But thank you.

1 Like

alright so I tried my way but I guess cause I’m using the inertial sensor it cant read left or right, idk how to command it to strafe, its either direction fwd or reverse, left or right… Gonna play with it this weekend, might just have to stick with using just regular motor groups and making the functions manually