Waypoint Command + Obstacle Avoidance + Controller

Dependencies:   mbed-rtos mbed QEI BNO055 MPU6050_DMP_Nucleo-I2Cdev virgo3_imuHandler MAX17048 Servo MODSERIAL

Fork of Orion_PCB_test_Faulhaber_gear_ratio41_waypoint_cmd by Team Virgo v3

Revision:
26:cd503e08a218
Child:
27:c813451bfb4d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri May 04 12:54:10 2018 +0000
@@ -0,0 +1,1158 @@
+#include "mbed.h"
+#include "imuHandler.h"
+#include "main.h"
+
+#include "VL53L0X.h"
+#include "Servo.h"
+
+#define W 0.1 //time to initiate the lidar
+
+//TODO
+//1,Rewrite the controller core for the robot - currently using Virgo controller
+//2,Add time-out for UWB
+
+
+
+DigitalOut led(NC);
+
+
+//**Ranging Module**
+/* THREAD */
+void static_ranging_thread(void const *n);
+void ranging_thread(void const *n); 
+/* VARIABLE */
+I2C ItC_ranging(ranging_i2c_SDA, ranging_i2c_SCL);
+Timer time_r;
+
+
+DigitalOut xshut1(XS1);
+DigitalOut xshut2(XS2);
+DigitalOut xshut3(XS3);
+
+DigitalOut xshut4(XS4);
+DigitalOut xshut5(XS5);
+
+VL53L0X sensor(&ItC_ranging, &time_r);
+VL53L0X sensor2(&ItC_ranging, &time_r);
+VL53L0X sensor3(&ItC_ranging, &time_r);
+
+VL53L0X sensor4(&ItC_ranging, &time_r);
+VL53L0X sensor5(&ItC_ranging, &time_r);
+    
+uint16_t data;
+struct RangeData{
+    uint16_t fwd,right,right_d,left_d,left;
+    double theta_idx;
+    };
+RangeData RangeSensor;
+
+//** IMU **
+/* THREAD */
+void imu_thread(void const *n);
+
+float imuTime;
+IMU_BNO055 imu; //Bosch BNO055 IMU wrapper class. For Invensense IMU use IMU_MPU6050 imu;    //MPU9150 / MPU6050 wrapper class
+DigitalOut imu_reset(imu_RST);
+
+/* FUNCTION */
+void imuReset();
+bool imuInit_function();
+
+//** ODOMETRY **
+/* THREAD */
+void odometry_thread(void const *n);
+
+odometer odometry;  //odometer function
+Localization localization;  //localization function
+
+motorDriver drive;  //motor drive train
+pidControl PID_L, PID_R; //pidcontroller for left and right motors
+
+Timer motorControl_t;
+float rpm_cmd[2]; //drive motor rpm command
+float rpm_compensated[2]; //rpm command compensated by acc limit
+float targetAcceleration = 150.0; //RPM/s acceleration
+float pwm_cmd[2]; //drive motor pwm command
+bool motor_enable = 0;
+
+//** Trajectory tracking **
+/* THREAD */
+void purePursuit_thread(void const *n);
+void waypointCmd_thread(void const *n);
+
+purePursuit purePursuit;
+bool purePursuit_enable = 1;
+float purePursuit_velocity, purePursuit_omega, purePursuit_gamma;
+//waypoints tored in format: x_coordinate,y_coordinate,speed_%,heading_toFace
+uint8_t totalWaypoints = 6;
+//kite pattern 200cm long, 100cm wide
+//int16_t waypoints_set[][4] = { {0,0,90,0},
+//    {100,100,90,0},
+//    {0,200,90,0},
+//    {-100,100,90,0},
+//    {0,0,90,0},
+//    {0,0,90,0},
+//    {0,0,90,0}
+//};
+
+int16_t waypoints_set[][4] = { {0,0,0,0},
+    {0,0,0,0},
+};
+
+float waypointZone = 150.0; //diameter around desired waypoint, if robot reaches within that zone then waypoint is reached.
+uint8_t waypointReached_flag = 0; //indicates if the desired waypoint has been reached
+uint8_t waypointSetFinish_flag = 0; //indicates if the desired waypoint set is over and the robot needs to stop.
+float target_waypoint[2] = {0.0, 0.0}; //coordinates in millimeters for pure-pursuit's use. initialize with 0,0 this is necessary to prevent comparison to a garbage value
+float target_velocity =0.0; //target velocity in mm/s
+float distanceToWaypoint; //distance from robot to waypoint
+uint8_t waypoint_index=0;
+uint8_t go_cmd=0; //make robot run a waypoint set
+
+
+
+/*Motor Control*/
+/* THREAD */
+void motorControl_thread(void const *n);
+attitudeControl attitudeControl;
+
+float rpm_smc = 500;
+float ref_dtheta = 0;
+float ref_theta = 0;
+
+float ref_dgamma = 0;
+float ref_gamma = 0;
+
+float ref_beta = DEG_TO_RAD(0.0);
+float ref_dbeta = 0;
+
+float u1, u2;
+
+
+//void waypoint_parser(void const *n);
+
+//** Communications **
+//nRF24NetworkHandler comm;  //nRF24 radio and network layer handler function
+//uint8_t dataSend_flag; //flag to indicate data is ready to be transmitted
+//uint8_t comm_status[3]; //[2] comm status, [0] decoded tx status, [1] rx status,
+//
+//cmdParser wirelessCmd;
+
+/* THREAD */
+//void comm_thread(void const *n);
+/*   **   */
+//-------------
+//-----------------------------------------------------------------------------
+
+////** UWB **
+/* THREAD */
+void uwb_thread(void const *n);
+void uwbtriangulation_thread(void const *n);
+/* VARIABLE */
+MODSERIAL uwb(uwb_TX, uwb_RX);
+//RawSerial uwb(uwb_TX, uwb_RX);
+char uwb_data[67]; 
+char uwb_data1[67];
+volatile bool newline_detected = false;
+//char rangestring_array[3][10];
+//int range_array[4];
+//char range[9];
+//****Trilateration configuration
+Trilateration trilateration;
+bool uwb_data_flag = 0;
+void rxUwbCallback(MODSERIAL_IRQ_INFO *q);
+//void rxUwbCallback();
+//vec3d bestsolution;
+//int distanceArray[4];
+//vec3d anchorArray[3];
+/*FUNCTION*/
+void uwbtriangulation_fn(char* uwb_data);
+////** End UWB **
+
+//***Raspberry Pi Communication***
+/* THREAD */
+void raspberryrx_thread(void const *n);
+void raspberrytx_thread(void const *n);
+/* VARIALE */
+//RawSerial Rasp(PA_9,PA_10);
+MODSERIAL Rasp(rasp_TX, rasp_RX);
+volatile bool rasp_newline_detected = false;
+bool rasp_data_flag = 0;
+char letter[15];
+char rasp_data[30];
+char waypoint_data[30];
+bool waypoint_ready =0;
+/* FUNCTION */
+void waypoint_parser_fn(char* waypoint_data);
+void rxRaspCallback(MODSERIAL_IRQ_INFO *q);
+//void rxRaspCallback();
+//******Debug******
+DigitalOut debugLED(debug_LED);
+Serial debugprint(uart_TX,uart_RX); //debug serial port
+/* THREAD */
+void heartbeat_thread(void const *n); //heartbeat loop as an individual thread
+void print_thread(void const *n); //debug printing thread
+
+
+
+int main() {
+    debugprint.baud(PC_BAUDRATE);
+    Rasp.baud(115200);
+
+    debugLED =1;
+
+    //wait_ms(5000);
+
+    debugprint.printf("** Starting Virgo v3 Routines *************\n\n");
+
+//    //** start Hearbeat loop as a thread **
+    Thread Heartbeat_function(heartbeat_thread, NULL, osPriorityNormal);
+    debugprint.printf("* Hearbeat loop started *\n");
+
+    //** start IMU funtion as Thread **
+    Thread IMU_function(imu_thread, NULL, osPriorityHigh);
+    debugprint.printf("* IMU routine started *\n");
+    
+//    //** start Ranging funtion as Thread **
+//    Thread Ranging_function(ranging_thread, NULL, osPriorityNormal);
+//    debugprint.printf("* Ranging routine started *\n");
+    
+//    //** start UwbUpdate function as Thread **
+    Thread UwbUpdate_function(uwb_thread, NULL, osPriorityNormal);
+    debugprint.printf("* Uwb Update routine started *\n");
+    
+//            //** start Uwb Triangulation function as Thread **
+//    Thread UwbTriangulation_function(uwbtriangulation_thread, NULL, osPriorityNormal);
+//    debugprint.printf("* Uwb Triangulation routine started *\n");
+
+//            //** start Raspberrypi receive function as Thread **
+    Thread Raspberryrx_function(raspberryrx_thread, NULL, osPriorityNormal,1024);
+    debugprint.printf("* Raspberrypi routine started *\n");
+    
+    //            //** start Raspberrypi transmit function as Thread **
+    Thread Raspberrytx_function(raspberrytx_thread, NULL, osPriorityNormal,1024);
+    debugprint.printf("* Raspberrypi routine started *\n");
+      
+//        //** start OdometryUpdate function as Thread **
+    Thread Odometry_function(odometry_thread, NULL, osPriorityNormal, 1024);
+    debugprint.printf("* Odometry routine started *\n");
+//    
+//        //** start MotorControl function as Thread **
+    Thread MotorControl_function(motorControl_thread, NULL, osPriorityHigh); // should be osPriorityHigh
+    debugprint.printf("* Motor control routine started *\n");
+
+//       //** start PurePursuit controller as Thread **
+    Thread PurePursuitUpdate_function(purePursuit_thread, NULL, osPriorityNormal);
+    debugprint.printf("* PurePursuit controller routine started *\n");
+
+//*    //** start Waypoint commander function as Thread **
+    Thread WaypointCmdUpdate_function(waypointCmd_thread, NULL, osPriorityNormal);
+    debugprint.printf("* Waypoint commander routine started *\n");
+
+//*    //** start Waypoint parser function as Thread **
+//    Thread WaypointParser_function(waypoint_parser, NULL, osPriorityNormal);
+//    debugprint.printf("* Waypoint commander routine started *\n");    
+    
+//*        //** start comm loop as a thread **
+//    Thread Comm_function(comm_thread, NULL, osPriorityNormal, 1024);
+//    debugprint.printf("* Communications loop started *\n");
+    
+//*        ** start debug print loop as a thread **
+//    Thread PrintLoop_function(print_thread, NULL, osPriorityNormal, 1024);
+//    debugprint.printf("* Print loop started *\n\n\n");
+
+//    Thread GetLoop_function(get_thread,NULL,osPriorityNormal, 1024);
+//    debugprint.printf("* Get loop started *\n\n\n");
+    debugprint.printf("Start\n");
+//  pinMode(5, OUTPUT);
+//  pinMode(4, OUTPUT);
+xshut1 = 0;
+xshut2 = 0;
+xshut3 = 0;
+
+xshut4 = 0;
+xshut5 = 0;
+
+debugprint.printf("\n======== Orion v1: Multiple Range Monitor ========\n");
+debugprint.printf("\nXSHUT OFF\n");
+
+
+Thread::wait(W);
+
+
+
+xshut1 = 1;
+debugprint.printf("Sensor 1: \nXSHUT ON\n");
+Thread::wait(W);
+
+sensor.init();
+debugprint.printf("S1 Initialized...\n");
+Thread::wait(W);
+
+sensor.setAddress((uint8_t)22);
+debugprint.printf("S1 Address set...\n");
+
+
+xshut2 = 1;
+debugprint.printf("\nSensor 2: \nXSHUT ON\n");
+Thread::wait(W);
+
+sensor2.init();
+debugprint.printf("S2 Initialized...\n");
+Thread::wait(W);
+
+sensor2.setAddress((uint8_t)23);
+debugprint.printf("S2 Address set...\n");
+
+xshut3 = 1;
+debugprint.printf("\nSensor 3: \nXSHUT ON\n");
+Thread::wait(W);
+
+sensor3.init();
+debugprint.printf("S3 Initialized...\n");
+Thread::wait(W);
+
+sensor3.setAddress((uint8_t)25);
+debugprint.printf("S3 Address set...\n");
+
+//////////////////////////////////////////////////
+xshut4 = 1;
+debugprint.printf("\nSensor 4: \nXSHUT ON\n");
+Thread::wait(W);
+
+sensor4.init();
+debugprint.printf("S4 Initialized...\n");
+Thread::wait(W);
+
+sensor4.setAddress((uint8_t)27);
+debugprint.printf("S4 Address set...\n");
+
+//////////////////////////////////////////////////
+xshut5 = 1;
+debugprint.printf("\nSensor 5: \nXSHUT ON\n");
+Thread::wait(W);
+
+sensor5.init();
+debugprint.printf("S5 Initialized...\n");
+Thread::wait(W);
+
+sensor5.setAddress((uint8_t)31);
+debugprint.printf("S5 Address set...\n");
+
+//////////////////////////////////////////////////
+
+sensor.startContinuous();
+sensor2.startContinuous();
+sensor3.startContinuous();
+
+sensor4.startContinuous();
+sensor5.startContinuous();
+debugprint.printf("S5 Address set... %u \n",sensor.readRangeContinuousMillimeters());
+debugprint.printf("S5 Address set... %u \n",sensor2.readRangeContinuousMillimeters());
+debugprint.printf("S5 Address set... %u \n",sensor3.readRangeContinuousMillimeters());
+        
+debugprint.printf("S5 Address set... %u \n",sensor4.readRangeContinuousMillimeters());
+debugprint.printf("S5 Address set... %u \n",sensor5.readRangeContinuousMillimeters()); 
+//    //** start Ranging funtion as Thread **
+Thread Static_Ranging_function(static_ranging_thread, NULL, osPriorityNormal);
+debugprint.printf("* Ranging routine started *\n");
+    debugprint.printf(" ***** \e[5mWAIT UNTIL IMU IS STABILIZED\e[0;m *****\n");
+
+    while(1) {
+
+    }
+ 
+
+
+}
+
+//****END MAIN*****************************
+//****THREAD AND FUNCTION******************
+
+/**
+ * heartbeat loop as an individual thread
+ */
+void heartbeat_thread(void const *n)
+{
+    while(true) {
+        if(imu.imu_stabilized[0] ==1) {
+            debugLED = !debugLED;
+            Thread::wait(Hearbeat_RateMS-50);
+            debugLED = !debugLED;
+            Thread::wait(50);
+        } else
+            debugLED = 1;
+    }
+}
+
+/**
+ * imu loop as an individual thread
+ */
+
+void imu_thread(void const *n)
+{
+    bool init_status = imuInit_function();
+    Thread::wait(100);
+
+    while(init_status) {
+//        debugprint.printf("%.2f Running 1 imu \n", imuTime);
+        imu.imuUpdate();
+
+        //Usage:
+        //imu.Pose[0, 1, 2]; //euler x, y, z
+        //imu.AngVel[0, 1, 2]; //AngVel x, y, z
+        //imu.LinAcc[0, 1, 2]; //LinAcc x, y, z
+        //imu.Quat[0, 1, 2, 3]; //Quaternion w, x, y, z
+
+        imuTime = imu.time_s;
+
+        Thread::wait(imu_UpdatePeriodMS);
+    }
+}
+
+bool imuInit_function()
+{
+    //Set Reset pin low and then high to reset the imu
+    imuReset(); //Physical reset
+    return (imu.imuInit());
+}
+
+void imuReset() //Physical reset
+{   
+    imu_reset = 0;
+    wait_ms(50);
+    imu_reset = 1;
+    return;
+}
+    
+    
+
+
+
+/**
+ * Ranging sensor loop as an individual thread
+ */
+ /**
+ * Ranging sensor loop as an individual thread
+ */
+void static_ranging_thread(void const *n)
+{
+    while(true)
+    {
+//      if(imu.imu_stabilized[1] ==1){   
+        RangeSensor.right   =  sensor.readRangeContinuousMillimeters();
+        RangeSensor.right_d = sensor2.readRangeContinuousMillimeters();
+        RangeSensor.fwd     = sensor3.readRangeContinuousMillimeters();
+        
+        RangeSensor.left_d  = sensor4.readRangeContinuousMillimeters();
+        RangeSensor.left    = sensor5.readRangeContinuousMillimeters(); 
+//        if (sensor.timeoutOccurred() || sensor2.timeoutOccurred() || sensor3.timeoutOccurred())  
+//            debugprint.printf(" TIMEOUT\r\n"); 
+//        }
+      Thread::wait(10);
+      }           
+}
+ 
+
+
+void odometry_thread(void const *n)
+{
+    odometry.init();
+    Thread::wait(50);
+
+    while(true) {
+//        debugprint.printf("%.2f Running 2 odometry \n", imuTime);
+        odometry.update();
+
+        //Usage:
+        //odometer.revolutions[0, 1]; //revolutions left, right
+        //odometer.rpm[0, 1]; //rpm left, right
+
+        localization.updatePosition(DEG_TO_RAD(imu.Pose[2]), odometry.revolutions);
+
+        //Usage:
+        //localization.position[0, 1] //x, y
+
+        Thread::wait(odometry_UpdatePeriodMS);
+    }
+}
+
+/**/
+/**
+ * motor control loop as an individual thread
+ */
+void motorControl_thread(void const *n)
+{
+    motorControl_t.start();
+
+    float pitch_th, pitch_om, yaw_th, yaw_om;
+    float wheelTh_l, wheelTh_r, wheelOm_l, wheelOm_r;
+    float W_l, W_r;
+
+    while(true) {
+//        debugprint.printf("%.2f Running 3 motorControl \n", imuTime);
+        //if((imu.imu_stabilized[1] ==1) && (go_cmd == 1)) {
+        if(imu.imu_stabilized[1] ==1) {
+
+            pitch_th = DEG_TO_RAD(imu.Pose[0]);
+            if(pitch_th < -1*M_PI)   pitch_th += 2*M_PI;
+            if(pitch_th > M_PI)   pitch_th -= 2*M_PI;
+            if(pitch_th < -1*M_PI)   pitch_th += 2*M_PI;
+            
+            
+            pitch_om = DEG_TO_RAD(imu.AngVel[0]);
+
+            yaw_th = DEG_TO_RAD(imu.Pose[2]);
+            
+            yaw_om = DEG_TO_RAD(imu.AngVel[2]);
+
+            wheelTh_l = odometry.revolutions[0]*(-2*M_PI);
+            wheelTh_r = odometry.revolutions[1]*(-2*M_PI);
+
+            wheelOm_l = (odometry.rpm[0]/60)*(-2*M_PI);
+            wheelOm_r = (odometry.rpm[1]/60)*(-2*M_PI);
+
+//            Rasp.printf("%.2f \n", purePursuit_velocity);
+            ref_dtheta = (purePursuit_velocity * (60.0 / (M_PI * wheel_dia)))*(-2*M_PI/60.0);
+            ref_gamma = purePursuit_gamma;
+            ref_dgamma = purePursuit_omega;
+
+            attitudeControl.GenWheelVelocities(&W_l, &W_r, 0, motorControl_t.read(),
+                                               pitch_th, pitch_om, yaw_th , yaw_om,
+                                               wheelTh_l, wheelTh_r, wheelOm_l, wheelOm_r,
+                                               0, ref_dbeta, ref_beta,
+                                               0, ref_dtheta, ref_theta,
+                                               0, ref_dgamma, ref_gamma,
+                                               &u1, &u2);
+            
+
+
+//            Rasp.printf("Reach %d \n", waypointReached_flag);
+//            Rasp.printf("Finsih %d \n", waypointSetFinish_flag);
+//            if(waypointSetFinish_flag == 0 && waypointReached_flag == 0 ) {
+//              Rasp.printf("Motor enable: %d \n", motor_enable);
+              if (motor_enable == 1){
+                rpm_cmd[0]=W_l*60/(2*M_PI)*(-1.0);// Virgo
+                rpm_cmd[1]=W_r*60/(2*M_PI)*(-1.0);
+//               Rasp.printf("%.2f \n", rpm_cmd[0]);
+//                rpm_cmd[0]=W_l*60/(2*M_PI)*(1.0); //Orion
+//                rpm_cmd[1]=W_r*60/(2*M_PI)*(1.0);
+                
+//                rpm_cmd[0]=0;
+//                rpm_cmd[1]=0;
+
+                if( (generalFunctions::abs_f(rpm_cmd[0]) < 50.0) && (generalFunctions::abs_f(rpm_cmd[0]) > 10.0) )
+                    rpm_cmd[0] = 47.5*generalFunctions::sign_f(rpm_cmd[0]);
+                else if(generalFunctions::abs_f(rpm_cmd[0]) <= 10.0)
+                    rpm_cmd[0] = 0;
+
+                if( (generalFunctions::abs_f(rpm_cmd[1]) < 50.0) && (generalFunctions::abs_f(rpm_cmd[1]) > 10.0) )
+                    rpm_cmd[1] = 47.5*generalFunctions::sign_f(rpm_cmd[1]);
+                else if(generalFunctions::abs_f(rpm_cmd[1]) <= 10.0)
+                    rpm_cmd[1] = 0;
+
+                rpm_compensated[0]=PID_L.processAcc(rpm_cmd[0], targetAcceleration, motorControl_t.read());
+                rpm_compensated[1]=PID_R.processAcc(rpm_cmd[1], targetAcceleration, motorControl_t.read());
+
+
+            } else {
+                rpm_cmd[0]=0;
+                rpm_cmd[1]=0;
+                
+                rpm_compensated[0]=PID_L.processAcc(rpm_cmd[0], 225.0, motorControl_t.read());
+                rpm_compensated[1]=PID_R.processAcc(rpm_cmd[1], 225.0, motorControl_t.read());
+            }
+
+            pwm_cmd[0]=PID_L.calcOutput(rpm_compensated[0], odometry.rpm[0], motorControl_t.read());
+            pwm_cmd[1]=PID_R.calcOutput(rpm_compensated[1], odometry.rpm[1], motorControl_t.read());
+
+            drive.setPWM_L(pwm_cmd[0]);
+            drive.setPWM_R(pwm_cmd[1]);
+ 
+        }
+
+        motorControl_t.reset();
+
+        Thread::wait(motorControl_UpdatePeriodMS);
+    }
+}
+
+//*************Raspberry Pi and STM32 Communication
+//****Transmit
+void raspberrytx_thread(void const *n)
+{
+    while(1){
+//This part for Communication    
+                Rasp.printf("%.4f: ",imuTime); //timestamp
+                Rasp.printf("%.2f,%.2f,%.2f; ",imu.Pose[0], imu.Pose[1], imu.Pose[2]); //euler x,y,z
+////                Rasp.printf("%.2f,%.2f,%.2f; ",imu.AngVel[0], imu.AngVel[1], imu.AngVel[2]); //ang vel x,y,z
+////                Rasp.printf("%.2f,%.2f,%.2f; ",imu.LinAcc[0], imu.LinAcc[1], imu.LinAcc[2]); //Linear acc
+                Rasp.printf("%.2f,%.2f; ",localization.position[0], localization.position[1]); //Localization X,Y
+                Rasp.printf("%u,%u,%u,%u,%u; ", RangeSensor.right,RangeSensor.right_d,RangeSensor.fwd, RangeSensor.left_d, RangeSensor.left);
+                Rasp.printf("%.2f,%.2f; ",trilateration.robot_pos.x, trilateration.robot_pos.y); //uwb position
+                Rasp.printf("%d,%d,%d; ",trilateration.range_array[0], trilateration.range_array[1], trilateration.range_array[2]); //uwb range data
+//                Rasp.printf("%.2f,%.2f; ",odometry.revolutions[0] * 2*M_PI, odometry.revolutions[1] * 2*M_PI); //Wheel Position L,R
+                Rasp.printf("%.2f,%.2f; ",odometry.rpm[0] * 2*M_PI / 60, odometry.rpm[1] * 2*M_PI / 60); //Wheel Speed L,R
+                Rasp.printf("%.2f,%.2f; ", target_waypoint[0], target_waypoint[1]); //Waypoint heading to
+                
+                Rasp.printf("%d", waypointReached_flag);
+//                //Rasp.printf("%.2f,%.2f; ",comm.DataIn.data[13], comm.DataIn.data[14]); //Drivetrain Command L,R
+//                Rasp.printf("%.2f,%.2f;",rpm_compensated[0] * 2*M_PI / 60, rpm_compensated[1] * 2*M_PI / 60); //Compensated Command L,R
+                Rasp.printf("\n");   
+
+//This part for Debug:
+//Rasp.printf("time: %.4f: ",imuTime); //timestamp
+//Rasp.printf("imu: %.2f,%.2f,%.2f; ",imu.Pose[0], imu.Pose[1], imu.Pose[2]); //euler x,y,z
+//Rasp.printf("position: %.2f,%.2f; ",localization.position[0], localization.position[1]); //Localization X,Y
+//Rasp.printf("uwb: %.2f,%.2f; ",trilateration.robot_pos.x, trilateration.robot_pos.y); //uwb position
+//Rasp.printf("lidar: %u,%u,%u,%u,%u; ", RangeSensor.right,RangeSensor.right_d,RangeSensor.fwd, RangeSensor.left_d, RangeSensor.left);
+//Rasp.printf("waypoint data: %d %d %d; ", waypoints_set[1][0],waypoints_set[1][1], waypoints_set[1][2]);
+//Rasp.printf("waypointReached: %d; ", waypointReached_flag);
+//Rasp.printf(";\n");     
+    Thread::wait(RaspTransmit_UpdatePeriodMS);
+    }   
+}
+
+//****Receive
+//void rxRaspCallback(){
+//    NVIC_DisableIRQ(USART1_IRQn);
+//    led = !led;;
+//    while(Rasp.getc() != '$'){
+//    }
+//    for(int i = 0 ; i < sizeof(rasp_data); i ++){
+//    rasp_data[i] = Rasp.getc();
+//    if(rasp_data[i] == '\n'){
+//        rasp_data_flag = 1;
+//        break;
+//    }
+//    }
+//    NVIC_EnableIRQ(USART1_IRQn);
+//}
+
+void rxRaspCallback(MODSERIAL_IRQ_INFO *q) {
+    MODSERIAL *serial = q->serial;
+    if ( serial->rxGetLastChar() == '\n') {
+        rasp_newline_detected = true;
+    }
+}
+
+void raspberryrx_thread(void const *n)
+{
+    Rasp.baud(115200);
+//    Rasp.attach(&rxRaspCallback, RawSerial::RxIrq);
+    Rasp.attach(&rxRaspCallback, MODSERIAL::RxIrq);
+    for(int i = 0 ; i < sizeof(rasp_data); i ++){
+    rasp_data[i] = NULL;
+    }
+    
+    
+    while(1){
+//    led = 0;
+    while (! rasp_newline_detected ) ;//debugprint.printf("detecting the line \n");    //should be: If newline_detected --> Compute
+    rasp_newline_detected = false;
+    while(Rasp.getc() != '$'){
+        }
+    for(int i = 0 ; i < sizeof(rasp_data); i ++){
+        rasp_data[i] = Rasp.getc();
+    if(rasp_data[i] == '\n'){
+        rasp_data_flag = 1;
+        break;
+    }
+    }
+    //debugprint.printf("Running rasp %s \n",rasp_data);
+    Thread::wait(100);
+//    if (rasp_data_flag == 1){
+//   debugprint.printf(" %.2f Running 5 rasp rx \n", imuTime);
+//    memcpy(waypoint_data, rasp_data, sizeof(rasp_data));
+    waypoint_parser_fn(rasp_data);
+    for(int i = 0 ; i < sizeof(rasp_data); i ++){
+    rasp_data[i] = 0;
+    }
+    rasp_data_flag = 0; 
+     
+    Thread::wait(RaspReceive_UpdatePeriodMS);
+    
+    }   
+}
+
+//******End***********************************************
+
+/*****Extract waypoint from rasp_data*/
+//void waypoint_parser(void const *n){
+//     char waypoint_x[5];
+//     char waypoint_y[5];
+//     while(1){
+//     //Print the data for debugging    
+////     for(int i =0 ; i < sizeof(waypoint_data); i++){
+////        debugprint.putc(waypoint_data[i]);
+////     } 
+//     //debugprint.printf("Waypoint data %s \n",waypoint_data);
+//     
+//     memcpy(waypoint_x, &waypoint_data[0], 4);
+//     waypoint_x[sizeof(waypoint_x-1)] = '\0';
+////     debugprint.printf("waypoint x data char: %s  \n", waypoint_x);
+//
+//     memcpy(waypoint_y, &waypoint_data[0]+5, 4);
+//     waypoint_y[sizeof(waypoint_y-1)] = '\0';
+////     debugprint.printf("waypoint y data char: %s  \n", waypoint_y);
+//     
+//     waypoints_set[1][0] = strtol(waypoint_x,NULL,10);
+//     waypoints_set[1][1] = strtol(waypoint_y,NULL,10);
+//     waypoint_ready = 1;
+////     debugprint.printf("waypoint data: %d %d \n", waypoints_set[2][0],waypoints_set[2][1]);
+//     
+//     Thread::wait(100);
+//     }      
+//}
+
+//Use function to call when necessary
+//void waypoint_parser_fn(char* waypoint_data){
+//     char waypoint_x[5];
+//     char waypoint_y[5];
+//     char target_vel[3];
+//     //Print the data for debugging    
+////     for(int i =0 ; i < sizeof(waypoint_data); i++){
+////        debugprint.putc(waypoint_data[i]);
+////     } 
+//     //debugprint.printf("Waypoint data %s \n",waypoint_data);
+//     
+//     memcpy(waypoint_x, &waypoint_data[0], 4);
+//     waypoint_x[sizeof(waypoint_x-1)] = '\0';
+////     debugprint.printf("waypoint x data char: %s  \n", waypoint_x);
+//
+//     memcpy(waypoint_y, &waypoint_data[0]+5, 4);
+//     waypoint_y[sizeof(waypoint_y-1)] = '\0';
+////     debugprint.printf("waypoint y data char: %s  \n", waypoint_y);
+//     memcpy(target_vel, &waypoint_data[0]+10, 2);
+//     target_vel[sizeof(target_vel-1)] = '\0';
+//     
+//     waypoints_set[1][0] = strtol(waypoint_x,NULL,10);  //convert string to int
+//     waypoints_set[1][1] = strtol(waypoint_y,NULL,10);
+//     waypoints_set[1][2] = strtol(target_vel,NULL,10);
+//     waypoint_ready = 1;
+//     debugprint.printf("waypoint data: %d %d %d \n", waypoints_set[1][0],waypoints_set[1][1], waypoints_set[1][2]);
+//    
+//}
+
+void waypoint_parser_fn(char* waypoint_data){
+     char header;
+//     char waypoint_x[5];
+//     char waypoint_y[5];
+//     char target_vel[3];
+     //Print the data for debugging    
+//     for(int i =0 ; i < sizeof(waypoint_data); i++){
+//        debugprint.putc(waypoint_data[i]);
+//     } 
+//     Rasp.printf("Waypoint data %s \n",waypoint_data);
+     header = waypoint_data[0];
+     switch (header) {
+         case '1':              purePursuit_enable = 0; //turn off waypoint controller
+                                char linear[5],angular[5];
+                                memcpy(linear, &waypoint_data[0]+2, 4);
+                                linear[sizeof(linear-1)] = '\0';
+                                //Rasp.printf("%s \n", linear);
+                                
+                                memcpy(angular, &waypoint_data[0]+7, 4);
+                                angular[sizeof(angular-1)] = '\0';
+                                //Rasp.printf("%s \n", angular);
+                                
+                                
+                                purePursuit_velocity = strtol(linear,NULL,10);  //convert string to int
+                                purePursuit_gamma = strtol(angular,NULL,10);
+                                //Rasp.printf("%.2f \n", purePursuit_velocity);
+                                
+                                motor_enable = 1;
+                                
+                                break;
+                                
+        case '2':               purePursuit_enable = 1;
+                                char waypoint_x[5], waypoint_y[5], target_vel[3];
+                                memcpy(waypoint_x, &waypoint_data[0]+2, 4);
+                                waypoint_x[sizeof(waypoint_x-1)] = '\0';
+  //                              Rasp.printf("%s \n", waypoint_x); //Debug print
+                                
+                                Rasp.printf("%s \n", waypoint_data); //Debug print
+
+                                memcpy(waypoint_y, &waypoint_data[0]+7, 4);
+                                waypoint_y[sizeof(waypoint_y-1)] = '\0';
+//                                Rasp.printf("%s \n", waypoint_y);
+
+                                memcpy(target_vel, &waypoint_data[0]+12, 2);
+                                target_vel[sizeof(target_vel-1)] = '\0';
+  //                              Rasp.printf("%s \n", target_vel);
+     
+                                waypoints_set[1][0] = strtol(waypoint_x,NULL,10);  //convert string to int
+                                waypoints_set[1][1] = strtol(waypoint_y,NULL,10);
+                                waypoints_set[1][2] = strtol(target_vel,NULL,10);
+                                waypoint_ready = 1;
+                                motor_enable = 1;
+                                
+                                break;
+         case '3':              motor_enable = 0; //Turn off the motor controller
+                                                
+         default: break;
+     
+     }
+}
+
+
+//-*****************************UWB***********************
+void uwb_thread(void const *n)
+{
+//    float uwb_time = 0.0;
+//    float time_out = 0.0;
+    uwb.baud(115200);
+//    uwb.attach(&rxUwbCallback, RawSerial::RxIrq);
+    uwb.attach(&rxUwbCallback, MODSERIAL::RxIrq);
+    for (int j = 0; j< sizeof(uwb_data); j++) { 
+        uwb_data[j] = NULL;
+        }
+    while(1){
+//   debugprint.printf("%.2f Running 5 uwb update \n",imuTime);
+//   debugprint.printf("Running uwb %s \n",uwb_data);
+
+//NEW:
+    while (! newline_detected ); // debugprint.printf("detecting the line \n");    //should be: If newline_detected --> Compute : No because : if else, the data will be skip.
+    newline_detected = false;
+    //checking start of the message with letter "m"
+    while(uwb.getc() != 'm'){
+        }
+    for(int i = 0 ; i < sizeof(uwb_data); i ++){
+        uwb_data[i] = uwb.getc();
+    if(uwb_data[i] == '\n'){
+        uwb_data_flag = 1;
+        break;
+        }
+
+//   debugprint.printf("%.2f Running 5 uwb update \n",imuTime);
+    uwbtriangulation_fn(uwb_data); // Running Triateration (The function nam is misleading)
+//    ekf_fn(&ekf); //run ekf
+    debugprint.printf("%s",uwb_data);
+    for (int j = 0; j< sizeof(uwb_data); j++) { 
+    uwb_data[j] = 0;
+    }
+    uwb_data_flag = 0;
+    }
+
+//OLD
+//    if(uwb_data_flag == 1){
+////    memcpy(uwb_data1, uwb_data  /* Offset */, 67 /* Length */); //copy data from buffer
+//    uwbtriangulation_fn(uwb_data);
+//    for (int j = 0; j< sizeof(uwb_data); j++) { 
+//    uwb_data[j] = 0;
+//    }
+//    uwb_data_flag = 0;
+//    
+//    }
+
+   // debugprint.printf("\n");
+    //debugprint.printf("%s \n",range);
+    Thread::wait(200);
+    }
+    
+}
+
+//void uwbtriangulation_thread(void const *n)
+//{   
+//    int anchorheight = 1.8;
+//    anchorArray[0].x = 0.0;
+//    anchorArray[0].y = 0.0;
+//    anchorArray[0].z = anchorheight;
+//
+//    anchorArray[1].x = 3.0;
+//    anchorArray[1].y = 0.0;
+//    anchorArray[1].z = anchorheight;
+//
+//    anchorArray[2].x = 0.0;
+//    anchorArray[2].y = 4.0;
+//    anchorArray[2].z = anchorheight;
+//
+//    range_array[0] = 0;
+//    range_array[1] = 0;
+//    range_array[2] = 0;
+//    range_array[3] = 0;
+//    
+//    while(1){
+////    debugprint.printf("%.2f Running 6 uwb triangulation \n", imuTime);
+//    //memcpy(uwb_data1, uwb_data  /* Offset */, 67 /* Length */);
+//    
+//    memcpy(rangestring_array[0], &uwb_data1[0] + 3 /* Offset */, 9 /* Length */);  //copy substring from a ranging string
+//    rangestring_array[0][sizeof(rangestring_array[0])-1] = '\0';                               //add NULL terminal (memcpy requires)
+//    range_array[0] = strtol(rangestring_array[0],NULL, 16);                 //Convert a ranging string to float 
+//                      
+//    memcpy(rangestring_array[1], &uwb_data1[0] + 13 /* Offset */, 9 /* Length */);
+//    rangestring_array[1][sizeof(rangestring_array[1])-1] = '\0';
+//    range_array[1] = strtol(rangestring_array[1],NULL, 16);
+//    
+//    memcpy(rangestring_array[2], &uwb_data1[0] + 23 /* Offset */, 9 /* Length */);
+//    rangestring_array[2][sizeof(rangestring_array[2])-1] = '\0';
+//    range_array[2] = strtol(rangestring_array[2],NULL, 16);
+//    
+//    trilateration.GetLocation (&bestsolution, 1, anchorArray, range_array);
+//    //memcpy(range[1], &uwb_data1[0] + 13 /* Offset */, sizeof(range[1]) /* Length */);
+//   // range_array[1] = strtol(range[1],NULL, 16)/1000.0;
+//   // memcpy(range[2], &uwb_data[0] + 23 /* Offset */, 9 /* Length */);
+//   // range_float[2] = strtol(range[2],NULL, 16)/1000.0;
+//   // range_float[0] = strtol(range[0],NULL, 16)/1000.0;
+// //   range_float[1] = strtol(range[1],NULL, 16)/1000.0;
+//  //  range_float[2] = strtol(range[2],NULL, 16)/1000.0;
+//   // debugprint.printf("\n");
+//   // debugprint.printf(range[0]);
+////    debugprint.puts(range[1]);
+//   // debugprint.puts(range[2]);
+//   // debugprint.printf("\n");
+//    //debugprint.printf("%s",uwb_data);
+//    //debugprint.printf("%s \n",uwb_data[66]);
+//    Thread::wait(250);     
+//    }
+//    
+//}
+
+void uwbtriangulation_fn(char* uwb_data)
+{   
+        char rangestring_array[3][10];
+        memcpy(rangestring_array[0], &uwb_data[0] + 3 /* Offset */, 9 /* Length */);  //copy substring from a ranging string
+        rangestring_array[0][sizeof(rangestring_array[0])-1] = '\0';                               //add NULL terminal (memcpy requires)
+        trilateration.range_array[0] = strtol(rangestring_array[0],NULL, 16);                 //Convert a ranging string to float 
+                      
+        memcpy(&rangestring_array[1], &uwb_data[0] + 13 /* Offset */, 9 /* Length */);
+        rangestring_array[1][sizeof(rangestring_array[1])-1] = '\0';
+        trilateration.range_array[1] = strtol(rangestring_array[1],NULL, 16);
+    
+        memcpy(&rangestring_array[2], &uwb_data[0] + 23 /* Offset */, 9 /* Length */);
+        rangestring_array[2][sizeof(rangestring_array[2])-1] = '\0';
+        trilateration.range_array[2] = strtol(rangestring_array[2],NULL, 16);
+    
+        trilateration.GetLocation (&trilateration.robot_pos, 1, trilateration.anchor_pos, trilateration.range_array);    
+}
+
+
+//void rxUwbCallback() {
+//    NVIC_DisableIRQ(USART2_IRQn);
+//    while(uwb.getc() != 'm'){
+//    }
+//    for(int i = 0 ; i < sizeof(uwb_data); i ++){
+//    uwb_data[i] = uwb.getc();
+//    if(uwb_data[i] == '\n'){
+//        uwb_data_flag = 1;
+//        break;
+//    }
+//    }
+//    NVIC_EnableIRQ(USART2_IRQn);
+//}
+
+void rxUwbCallback(MODSERIAL_IRQ_INFO *q) {
+    MODSERIAL *serial = q->serial;
+    if ( serial->rxGetLastChar() == '\n') {
+        newline_detected = true;
+    }
+}
+
+//*******************************************************
+
+
+
+
+
+/**
+/**
+ * purepursuit loop as an individual thread
+ */
+void purePursuit_thread(void const *n)
+{
+    while(true) {
+//        debugprint.printf("%.2f Running 7 purePursuit \n", imuTime);
+        if(imu.imu_stabilized[0] ==1 && purePursuit_enable == 1) {
+            //purePursuit.GenVGW(&purePursuit_velocity, &purePursuit_gamma, &purePursuit_omega, target_waypoint, 400.0, localization.position, DEG_TO_RAD(imu.Pose[2]));
+            purePursuit.GenVGW(&purePursuit_velocity, &purePursuit_gamma, &purePursuit_omega, target_waypoint, target_velocity, localization.position, DEG_TO_RAD(imu.Pose[2]));
+
+            if(purePursuit.robotFrame_targetDistance <= waypointZone)
+                waypointReached_flag = 1;
+            else
+                waypointReached_flag = 0;
+        }
+        Thread::wait(imu_UpdatePeriodMS);
+    }
+}
+
+/**
+ * waypoint tracking loop as individual thread
+ */
+void waypointCmd_thread(void const *n)
+{
+    while(true) {
+//        debugprint.printf("%.2f waypoint cmd \n", imuTime);
+        //if((imu.imu_stabilized[0] ==1) && (go_cmd == 1)) {
+        if(imu.imu_stabilized[0] ==1 && purePursuit_enable == 1) {
+
+//            if(waypoint_index > totalWaypoints) {
+//                target_velocity = 0.0; //stop the robot
+//                waypointSetFinish_flag = 1;
+//            }
+            
+            if(waypointReached_flag == 1 && waypoint_ready == 0) {
+                target_velocity = 0.0; //stop the robot;
+                motor_enable = 0;
+            }
+
+//            debugprint.printf("waypointReached_flag = %d, waypoint_ready = %d \n", waypointReached_flag,waypoint_ready);
+//            debugprint.printf("target waypoint %.2f %.2f \n", target_waypoint[0], target_waypoint[1]);
+            if(waypointReached_flag == 1 && waypointSetFinish_flag == 0 && waypoint_ready == 1) {
+                waypoint_index = 1;
+//            if(waypointReached_flag == 1 && waypointSetFinish_flag == 0){
+                target_waypoint[0] = waypoints_set[waypoint_index][0] * 10.0; //convert coordinate from centimeters to millimeters
+                target_waypoint[1] = waypoints_set[waypoint_index][1] * 10.0; //convert coordinate from centimeters to millimeters
+                target_velocity = waypoints_set[waypoint_index][2] * (driveTrain_maxV/100.0); //convert speed from percentage to mm/s
+                //target_velocity = 90*(driveTrain_maxV/100.0);
+                waypoint_ready = 0;
+//                waypoint_index++;
+            }
+        }
+        Thread::wait(100); //waypoint update doesnt need to be very fast, 10Hz is more than sufficient
+    }
+}
+
+///**
+///**
+// * nRF network communications as an individual thread
+// */
+//void comm_thread(void const *n)
+//{
+//    comm.init(); //initialize communications unit
+//    Thread::wait(1000); //wait for a bit for radio to complete setup
+//    dataSend_flag=0;
+//
+//    float data[2];
+//    wirelessCmd.sendData(0x00, RE_CurrentPose, 0, 0);
+//    //wirelessCmd.sendCmd(0x00, getCurrentPosition, 0);
+//
+//    while(true) {
+//        dataSend_flag =1;
+//
+//        if((dataSend_flag == 1) && (comm.tx_ready == 1)) {
+//
+//            comm.DataOut.addr = 0; //send to node address
+//
+//            comm.DataOut.parameter[0] = 1; //parameter def 0
+//            comm.DataOut.parameter[1] = 2; //parameter def 1
+//
+//            comm.DataOut.dataLen = 20; //length of data to be sent
+//
+//            comm.DataOut.data[0] = imuTime;                             //timestamp
+//            comm.DataOut.data[1] = imu.Pose[0];                         //euler x / pitch angle
+//            comm.DataOut.data[2] = imu.Pose[1];                         //euler x / roll angle
+//            comm.DataOut.data[3] = imu.Pose[2];                         //euler z / yaw angle
+//            comm.DataOut.data[4] = imu.AngVel[0];                       //euler x / pitch velocity
+//            comm.DataOut.data[5] = imu.AngVel[1];                       //euler y / roll velocity
+//            comm.DataOut.data[6] = imu.AngVel[2];                       //euler z / yaw velocity
+//            comm.DataOut.data[7] = imu.LinAcc[0];                       //x acc
+//            comm.DataOut.data[8] = imu.LinAcc[1];                       //y acc
+//            comm.DataOut.data[9] = imu.LinAcc[2];                       //z acc
+//            comm.DataOut.data[10] = localization.position[0];           //localization position x
+//            comm.DataOut.data[11] = localization.position[1];           //localization position y            
+//            comm.DataOut.data[12] = odometry.revolutions[0] * 2*M_PI;   //left wheel position
+//            comm.DataOut.data[13] = odometry.revolutions[1] * 2*M_PI;   //right wheel position
+//            comm.DataOut.data[14] = odometry.rpm[0] * 2*M_PI / 60;      //left wheel velocity
+//            comm.DataOut.data[15] = odometry.rpm[1] * 2*M_PI / 60;      //right wheel velocity
+//            comm.DataOut.data[16] = bestsolution.x;                 // uwb x position //Harry changed here
+//            comm.DataOut.data[17] = bestsolution.y;                 // uwb y position
+////            comm.DataOut.data[16] = pwm_cmd[0] * 100.0;                 //left wheel PWM %
+////            comm.DataOut.data[17] = pwm_cmd[1] * 100.0;                 //right wheel PWM %
+//            comm.DataOut.data[18] = rpm_compensated[0] * 2*M_PI / 60;   //compensated left wheel velocity command
+//            comm.DataOut.data[19] = rpm_compensated[1] * 2*M_PI / 60;   //compensated right wheel velocity command
+//
+//
+//            comm_status[2] = comm.send();
+//            comm_status[0] = (comm_status[2] & 0b0001);
+//            comm_status[1] = (comm_status[2] & 0b0010) >> 1;
+//
+//            if(comm_status[0] == 1) dataSend_flag = 0; //if send succeeded, set dataSend_flag to 0
+//        }
+//
+//        else {
+//            comm_status[2] = comm.update();
+//
+//            comm_status[0] = (comm_status[2] & 0b0001);
+//            comm_status[1] = (comm_status[2] & 0b0010) >> 1;
+//
+//            if(comm_status[1] == 1) {
+//                //wirelessCmd.parseCmd(comm.DataIn.addr, comm.DataIn.parameter, comm.DataIn.data, comm.DataIn.dataLen);
+//                if(go_cmd == 0) {
+//                    if(comm.DataIn.parameter[1] == 0x10) go_cmd=1;
+//                }
+//            }
+//
+//
+//        }
+//
+//        comm_status[0] = (comm_status[2] & 0b0001);
+//        comm_status[1] = (comm_status[2] & 0b0010) >> 1;
+//
+//        Thread::wait(1); //slow down loop a bit so that CPU usage doesnt shoot up unnecessarily
+//    }
+//} 
+
+
+    
+ /**
+ * debug data print loop as an individual thread
+ */
+#define print_lines 15 //number of info lines being printed on screen
+void print_thread(void const *n)
+{
+    //clear 14 lines while going up, these are the initilization lines printed on screen
+    for(int l=14; l>0; l--) {
+        debugprint.printf("\e[1A"); //go up 1 line
+        debugprint.printf("\e[K"); //clear line
+    }
+
+    debugprint.printf("************ VIRGO v3: Status Monitor *************\n\n");
+    for(int l=print_lines; l>0; l--) debugprint.printf("\n");
+    debugprint.printf("\n===================================================");
+    debugprint.printf("\e[1A"); //go up 1 line
+
+    while(true) {
+        //move cursor up # of lines printed to create a static display and clear the first line
+        for(int l=print_lines; l>0; l--) debugprint.printf("\e[1A");
+        debugprint.printf("\e[K");
+
+        debugprint.printf("Elapsed time: %.2f s\n\e[K", imuTime); //
+//        debugprint.printf("Ranging: %.2f, %u\n\e\n", RangeSensor.theta_idx,RangeSensor.distance);
+        debugprint.printf("Position: %.2f , %.2f\n\e[K", localization.position[0], localization.position[1]); //
+        debugprint.printf("Orientation (X-Y-Z): (%.2f , %.2f , %.2f)\n\e[K", imu.Pose[0], imu.Pose[1], imu.Pose[2]);
+        debugprint.printf("Calib Status : %d, %d \n\e[K", imu.imu_stabilized[0], imu.imu_stabilized[1]);
+        debugprint.printf("Odometry : %f, %f \n\e[K", odometry.revolutions[0], odometry.revolutions[1]);
+//        debug.printf("Calib Status (M-A-G-S-O): (%d , %d , %d , %d , %d)\n\e[K", imu.calib_stat[0], imu.calib_stat[1], imu.calib_stat[2], imu.calib_stat[3], imu.calib_stat[4]);
+//
+//        //debug.printf("Battery Status: %3.2f%%, %1.2fV\n\e[K", battery.getSOC(), battery.getVcell());
+//
+        debugprint.printf("Waypoint Tracking: waypointReached %d, waypointSetFinish %d waypointIndex %d\n\e[K", waypointReached_flag, waypointSetFinish_flag, waypoint_index);
+        debugprint.printf("Waypoint Tracking: distanceToWaypoint %.1f, purePursuit_headingE %.1f \n\e[K", purePursuit.robotFrame_targetDistance, RAD_TO_DEG(purePursuit.purePursuit_headingE));
+        debugprint.printf("Waypoint being tracked (X,Y): %.2f, %.2f\n\e[K", target_waypoint[0], target_waypoint[1]);
+//
+//        debug.printf("SMC: ref_beta %.2f, ref_dbeta %.3f\n\e[K", RAD_TO_DEG(ref_beta), RAD_TO_DEG(ref_dbeta));
+//        debug.printf("SMC: ref_gamma %.2f, ref_dgamma %.3f\n\e[K", RAD_TO_DEG(ref_gamma), RAD_TO_DEG(ref_dgamma));
+//        debug.printf("SMC: ref_theta %.2f, ref_dtheta %.3f\n\e[K", RAD_TO_DEG(ref_theta), RAD_TO_DEG(ref_dtheta));
+//        debug.printf("SMC: u1*tc %.2f rpm, u2*tc %.2f rpm\n\e[K", u1*0.005*60/(2*M_PI), u2*0.005*60/(2*M_PI));
+//
+        debugprint.printf("Compensated RPM (L,R): %.1f, %.1f\n\e[K", rpm_compensated[0], rpm_compensated[1]);
+        debugprint.printf("Computed PWM (L,R): %.1f, %.1f\n\e[K", pwm_cmd[0]*100.0, pwm_cmd[1]*100.0);
+        debugprint.printf("Measured RPM (L,R): %.1f, %.1f\n\e[K", odometry.rpm[0], odometry.rpm[1]);
+//        //debug.printf("Measured Revolutions (L,R): %.1f, %.1f\n\e[K", odometry.revolutions[0], odometry.revolutions[1]);
+//
+//        //debug.printf("PID_L: P %0.3f, I %0.3f, D %0.3f, Ff %0.3f, Summ %0.3f\n\e[K", PID_L.PIDFf_terms[0], PID_L.PIDFf_terms[1], PID_L.PIDFf_terms[2], PID_L.PIDFf_terms[3], PID_L.Summ_term);
+//        //debug.printf("PID_R: P %0.3f, I %0.3f, D %0.3f, Ff %0.3f, Summ %0.3f\n\e[K", PID_R.PIDFf_terms[0], PID_R.PIDFf_terms[1], PID_R.PIDFf_terms[2], PID_R.PIDFf_terms[3], PID_R.Summ_term);
+//
+//        debug.printf("Comm Status: Tx %d, Rx %d, Overall %d, comm.tx_ready %d\n\e[K", comm_status[0], comm_status[1], comm_status[2], comm.tx_ready);
+//        //debug.printf("Comm Status: %d\n\e[K", comm_status[0]);
+//        debugprint.printf("Raspberry waypoint: %s \n\e[K", rasp_data);
+        debugprint.printf("Ranging: %u, %u, %u, %u, %u\n\e\K", RangeSensor.right,RangeSensor.right_d,RangeSensor.fwd, RangeSensor.left_d, RangeSensor.left);
+//        debugprint.printf("UWB ranging: %s %s %s\n\e[K", rangestring_array[0],rangestring_array[1], rangestring_array[2]);
+        debugprint.printf("UWB ranging: %d %d %d \n\e[K", trilateration.range_array[0],trilateration.range_array[1],trilateration.range_array[2]);
+        debugprint.printf("x : %f , y : %f , z : %f \n\e[K", trilateration.robot_pos.x, trilateration.robot_pos.y, trilateration.robot_pos.z);
+       // debugprint.printf("Comm Status: Tx %d, Rx %d, Overall %d, comm.tx_ready %d\n\e[K", comm_status[0], comm_status[1], comm_status[2], comm.tx_ready);
+        
+        Thread::wait(PrintLoop_PeriodMS);
+    }
+}
+
+