Differential Drive with Talon SRX

Hello,
We recently switched from a mecanum drive to an arcade drive in C++. I built my code using robot builder than have been modifying it to behave the way I would like. When it built it used RobotDrive instead of DifferentialDrive which gives an error saying to use DifferentialDrive instead because RobotDrive is deprecated.

So I have made the change to DifferentialDrive, and have made a SpeedControllerGroup for the left and right side to hand over to differential Drive. When I Hand it the TalonSRX speed controllers it throws an error saying there is no matching function call that allows for a talonSRX

Here is my RobotMap Code which is giving the error.

#include "RobotMap.h"
#include "LiveWindow/LiveWindow.h"
#include "ctre/Phoenix.h"
#include "WPILib.h"
// END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=INCLUDES

// BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=ALLOCATION
std::shared_ptr<WPI_TalonSRX> RobotMap::driveBaseSubfrontLeft;
std::shared_ptr<WPI_TalonSRX> RobotMap::driveBaseSubfrontRight;
std::shared_ptr<WPI_TalonSRX> RobotMap::driveBaseSubrearLeft;
std::shared_ptr<WPI_TalonSRX> RobotMap::driveBaseSubrearRight;

std::shared_ptr<SpeedControllerGroup> RobotMap::driveBaseSubleftSide;
std::shared_ptr<SpeedControllerGroup> RobotMap::driveBaseSubrightSide;

std::shared_ptr<DifferentialDrive> RobotMap::driveBaseSuba_drive;
// END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=ALLOCATION

void RobotMap::init() {
    // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTRUCTORS
    //frc::LiveWindow *lw = frc::LiveWindow::GetInstance();

	driveBaseSubfrontLeft.reset(new WPI_TalonSRX(10));
    
    
    driveBaseSubfrontRight.reset(new WPI_TalonSRX(11));
    
    
    driveBaseSubrearLeft.reset(new WPI_TalonSRX(12));
    
    
    driveBaseSubrearRight.reset(new WPI_TalonSRX(13));
    
    driveBaseSubleftSide.reset(new SpeedControllerGroup(driveBaseSubfrontLeft, driveBaseSubrearLeft));

    driveBaseSubrightSide.reset(new SpeedControllerGroup(driveBaseSubfrontRight, driveBaseSubrearRight));

    driveBaseSuba_drive.reset(new DifferentialDrive(driveBaseSubleftSide, driveBaseSubrightSide));
    
    driveBaseSuba_drive->SetSafetyEnabled(true);
        driveBaseSuba_drive->SetExpiration(0.1);
        driveBaseSuba_drive->SetMaxOutput(1.0);

Alternatively I have tried to pass differential Drive the front left and front right talons and make the Rear talons slaves to their respective masters. This also gives an error in Differential Drive. :confused: :confused: :confused:
Thanks.

I was able to get it to build by passing my motor controllers with an asterisk

driveBaseSuba_drive.reset(new DifferentialDrive(*driveBaseSubfrontLeft, *driveBaseSubfrontRight));

I chose to use the Follower Control mode for the rear motors based on the example provided by CTRE

https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/blob/master/C%2B%2B/DifferentialDrive/src/Robot.cpp

A SpeedControllerGroup is not a (i.e. does not inherit from) a SpeedController, which is what the DifferentialDrive constructor wants. GCC++ will also not automatically cast from a smart pointer to a normal object pointer.

We also just pass the one MotorController per side and set the other two per side to follow the leader.

See
http://first.wpi.edu/FRC/roborio/release/docs/cpp/classfrc_1_1SpeedControllerGroup.html

http://first.wpi.edu/FRC/roborio/release/docs/cpp/classfrc_1_1DifferentialDrive.html

My question would be… since a SpeedControllerGroup can’t be used in place of a SpeedController… what is the intended use case?

I don’t know what code you’ve been reading, but SpeedControllerGroup definitely inherits from SpeedController. https://github.com/wpilibsuite/allwpilib/blob/master/wpilibc/src/main/native/include/SpeedControllerGroup.h#L18

Yeah, the “.H” file clearly shows it, but the doc I linked doesn’t mention it, and I recall having much the same issue as the OP back in January when we abandoned it. It does seem pointless otherwise.

The inheritance graphs are missing in general. The OP’s issue is caused by RobotBuilder using reference semantics with smart pointers while SpeedControllerGroup uses value semantics. Adding a leading asterisk to a smart pointer dereferences it and returns a reference that SpeedControllerGroup can use.

RobotBuilder’s auto-generated C++ code isn’t idiomatic and doesn’t follow modern WPILib conventions. We’ve wanted to modify RobotBuilder’s templates to use value semantics since at least 2017, but only one or two of us developers actually know how to modify RobotBuilder. Its YAML template approach is really confusing.