Programming the Titan

Motor Setup

1
2
3
4
5
6
7
8
//import the TitanQuad Library
import com.studica.frc.TitanQuad;

//Create the TitanQuad Object
private TitanQuad motor;

//Constuct a new instance
motor = new TitanQuad(TITAN_CAN_ID, TITAN_MOTOR_NUMBER);

Note

TITAN_CAN_ID is the CAN id for the Titan, by defualt it is 42. TITAN_MOTOR_NUMBER is the motor port to be used. Valid range is 0 - 3, this corresponds to the M0 - M3 on the Titan.

1
2
3
4
5
6
//Include the TitanQuad Library
#include <studica/TitanQuad.h>

//Constuct a new instance
private:
    studica::TitanQuad motor{TITAN_CAN_ID, TITAN_MOTOR_NUMBER};

Note

TITAN_CAN_ID is the CAN id for the Titan, by defualt it is 42. TITAN_MOTOR_NUMBER is the motor port to be used. Valid range is 0 - 3, this corresponds to the M0 - M3 on the Titan.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
//Include the TitanQuad Library
#include "TitanDriver_ros_wrapper.h"

int main(int argc, char **argv)
{
   system("/usr/local/frc/bin/frcKillRobot.sh"); //Terminal call to kill the robot manager used for WPILib before running the executable.
   ros::init(argc, argv, "titan_node");

   ros::NodeHandle nh; //internal reference to the ROS node that the program will use to interact with the ROS system
   VMXPi vmx(true, (uint8_t)50); //realtime bool and the update rate to use for the VMXPi AHRS/IMU interface, default is 50hz within a valid range of 4-200Hz

   TitanDriverROSWrapper titan(&nh, &vmx);

   ros::spin() //ros::spin() will enter a loop, pumping callbacks to obtain the latest sensor data

   return 0;
}

Note

TITAN_CAN_ID is the CAN id for the Titan, by defualt it is 42. TITAN_MOTOR_NUMBER is the motor port to be used. Valid range is 0 - 3, this corresponds to the M0 - M3 on the Titan.

Setting Motor Speed

1
2
3
4
5
6
7
8
9
/**
 * Sets the speed of a motor
 * <p>
 * @param speed range -1 to 1 (0 stop)
 */
public void setMotorSpeed(double speed)
{
    motor.set(speed);
}
1
2
3
4
5
6
7
8
9
/**
 * Sets the speed of a motor
 * <p>
 * @param speed range -1 to 1 (0 stop)
 */
void ClassName::SetMotorSpeed(double speed)
{
    motor.Set(speed);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/**
 * Sets the speed of a motor by sending a request to the motor-speed server
 * speed range -1.0 to 1.0 (0 stop)
 */

 ros::ServiceClient set_m_speed = nh->serviceClient<vmxpi_ros::MotorSpeed>("titan/set_motor_speed");

 vmxpi_ros::MotorSpeed msg;

 msg.request.speed = rightSpeed;
 msg.request.motor = 0;
 set_m_speed.call(msg);

Note

This is a demonstration of calling the motor speed service using the set_motor_speed server.

Full Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package frc.robot.subsystems;

//Subsystem Base import
import edu.wpi.first.wpilibj2.command.SubsystemBase;

//Titan import
import com.studica.frc.TitanQuad;

public class Example extends SubsystemBase
{
    /**
     * Motors
     */
    private TitanQuad motor;

    public Example()
    {
        //Motors
        motor = new TitanQuad(TITAN_CAN_ID, TITAN_MOTOR_NUMBER);
    }

    /**
     * Sets the speed of a motor
     * <p>
     * @param speed range -1 to 1 (0 stop)
     */
    public void setMotorSpeed(double speed)
    {
        motor.set(speed);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#pragma once

//Include SubsystemBase
#include <frc2/command/SubsystemBase.h>

//Include Titan Library
#include "studica/TitanQuad.h"

class Example : public frc2::SubsystemBase
{
    public:
        Example();
        void SetMotorSpeed(double speed);

    private:
        studica::TitanQuad motor(TITAN_CAN_ID, TITAN_MOTOR_NUMBER);
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//Include Header
#include "subsystems/Example.h"

//Constructor
Example::Example(){}

/**
 * Sets the speed of a motor
 * <p>
 * @param speed range -1 to 1 (0 stop)
 */
void Example::SetMotorSpeed(double speed)
{
    motor.Set(speed);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//Include the TitanQuad Library
#include "TitanDriver_ros_wrapper.h"

double motor1_speed;

// Returns the speed of motor 1
void motor1_speed_callback(const std_msgs::Float32::ConstPtr& msg)
{
   motor1_speed = msg->data;
}

int main(int argc, char **argv)
{
   system("/usr/local/frc/bin/frcKillRobot.sh"); //Terminal call to kill the robot manager used for WPILib before running the executable.
   ros::init(argc, argv, "titan_node");

   /**
    * Constructor
    * Titan's ros threads (publishers and services) will run asynchronously in the background
    */

   ros::NodeHandle nh; //internal reference to the ROS node that the program will use to interact with the ROS system
   VMXPi vmx(true, (uint8_t)50); //realtime bool and the update rate to use for the VMXPi AHRS/IMU interface, default is 50hz within a valid range of 4-200Hz

   ros::ServiceClient set_m_speed;
   ros::Subscriber motor1_speed_sub;

   TitanDriverROSWrapper titan(&nh, &vmx);

  /**
   * Sets the speed of a motor by sending a request to the motor-speed server
   * speed range -1.0 to 1.0 (0 stop)
   */

   set_m_speed = nh.serviceClient<vmxpi_ros::MotorSpeed>("titan/set_motor_speed");

   vmxpi_ros::MotorSpeed msg;

   msg.request.speed = 1.0; //Setting the motor 0 speed to 1.0
   msg.request.motor = 0;
   set_m_speed.call(msg);

   // Subscribing to Motor 1 speed topic to access the speed data
   motor1_speed_sub = nh.subscribe("titan/motor1/speed", 1, motor1_speed_callback);

   ros::spin(); //ros::spin() will enter a loop, pumping callbacks to obtain the latest sensor data

   return 0;
}

Important

Subscribe to Titan topics to access the data being published and write callbacks to pass messages between various processes.

Note

Calling the frcKillRobot.sh script is necessary since the VMXPi HAL uses the pigpio library, which unfortunately can only be used in one process. Thus, everything that interfaces with the VMXPi must be run on the same executable. For more information on programming with ROS, refer to: ROS Tutorials.