Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MX12 ServoRingBuffer mbed-src
Fork of SpindleBot by
main.cpp
- Committer:
- labmrd
- Date:
- 2015-05-06
- Revision:
- 7:b4b95e5f0fce
- Parent:
- 6:b4347c69816a
- Child:
- 8:cef07a8bdc42
File content as of revision 7:b4b95e5f0fce:
#define USE_DYNAMIXELS
//#define USE_BLUETOOTH
#define USE_SD_CARD
#define ROD_IS_RIGHT
// We have different modes for different things
#define MODE_MANUAL 1
#define MODE_AUTOMATIC 2
#define MODE_IDLE 3
#define MODE_NULL 0
// We always want to know if we are closing or opening
#define DIRECTION_CLOSING 1
#define DIRECTION_OPENING 2
#define DIRECTION_SLACK_WATER 3
#define DIRECTION_NULL 0
// General includes
#include "mbed.h"
#include "ServoRingBuffer.h"
#include "ram_test.h"
#include "Serial_Receive.h"
#include "data_set.h"
#include <string>
// Specific to Dynamixels
#ifdef USE_DYNAMIXELS
#include "AD7730.h"
#endif
// Specific to SD Card
#ifdef USE_SD_CARD
#include "SDFileSystem.h"
#endif
// Everyone should know pi...
#ifndef M_PI
#define M_PI 3.14159265358979323846 /* pi */
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#endif
// Create enum for the Jaw state (Closing, hold, opening)
enum jaw_state{
STATE_CLOSING=0,
STATE_CLOSE_HOLD=1,
STATE_OPENING=2,
STATE_OPEN_HOLD=3
};
// Define pins and interrupts
Ticker potISR; //Define a recurring timer interrupt
DigitalOut led1(LED1); //Led 1 for debugging purposes
DigitalOut led2(LED2); //Led 2 for debugging purposes
DigitalOut led3(LED3); //Led 3 for debugging purposes
DigitalOut led4(LED4); //Led 4 for debugging purposes
DigitalOut triggerOut(p11);
Serial pc(USBTX, USBRX); //Set up serial connection to pc
#ifdef USE_BLUETOOTH
Serial bt(p13,p14); //Set up serial connection to bluetooth adapter
#endif
AnalogIn AinLeftForce(p16); //Set up potentiometer on pin 20
AnalogIn AinRightForce(p15); //Set up potentiometer on pin 20
#ifdef USE_SD_CARD
// Attach SD card
SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
FILE *fp = NULL;
#define SAMPLES_PER_FILE 10000
#endif
// Dummy variable for debugging
unsigned int global_count=0;
float max_percent_full=0;
// Define variables for the program
char g_tissue_type_name[32];
float g_frequency;
int g_max_force;
int g_num_cycles;
float g_current_trajectory_time;
float g_theta;
float g_theta_last=0;
unsigned char g_current_mode=MODE_NULL;
jaw_state g_current_direction=STATE_OPEN_HOLD;
unsigned char g_current_cycle=0;
int g_input_pot_1;
#define NUMBER_OF_TISSUES 2
float g_error_norm[NUMBER_OF_TISSUES];
bool g_we_are_grasping=false;
#define CALIBRATION_READS 5000.0
float g_calibration_offset;
///////////Magic numbers courtesy Rod///////////////
float Phi1[5]={-8.02086003501975e-08,
1.55286905458007e-05,
0.00795344249784777,
8.23733045077119,
-0.00299236282304311};
float Phi2[5]={-1.24436831310503e-08,
1.23673348605010e-05,
0.00652545188345528,
6.75893262890734,
-0.00228098997419065};
float entry_threshold=8.70e6;
float velocty_threshold=-0.01;
float g_thresh_force[NUMBER_OF_TISSUES]={8.80e6,8.75e6};
///////////Magic numbers courtesy Rod///////////////
int g_command_corrected;
Timer mytimer;
// Warning, this buffer is large!
ServoRingBuffer Buffer;
spindleData tempSpindleData; //For sending to the buffer
#ifdef ROD_IS_RIGHT
int angle_sum=0;
int angle_count=0;
int angledot_sum=0;
int angledot_count=0;
int last_angle=0;
int angledotdot_sum=0;
int angledotdot_count=0;
int last_angledot=0;
#else
data_set recent_pos(30,"Data","Time (us)","Position (encoder counts)");
float coeffs[4];
bool crunching_data_flag;
#endif
int bits_received;
Timer ISRDurationTimer;
Timer AuxSerialTimer;
int worst_latency=0;
int current_latency;
#ifdef USE_DYNAMIXELS
Serial cm(p28,p27); //Set up serial connection to OpenCM 9.04
unsigned short left_servo_measured=0;
unsigned short right_servo_measured=0;
char input_buffer[16];
int input_buffer_location=0;
float samplingPeriod = 0.001; //This is the sampling period for the timer interrupt
#define LEFT_JAW_DYNAMIXEL_ID 3
#define RIGHT_JAW_DYNAMIXEL_ID 4
// #define CLOSED_SERVO_ANGLE_LEFT 1001 //This is the closed in encoder counts
// #define OPEN_SERVO_ANGLE_LEFT 2663 //This is the open in encoder counts
// #define CLOSED_SERVO_ANGLE_RIGHT 3259 //This is the closed in encoder counts
// #define OPEN_SERVO_ANGLE_RIGHT 1486 //This is the open in encoder counts
#define CLOSED_SERVO_ANGLE_LEFT 1975 //This is the closed in encoder counts
#define OPEN_SERVO_ANGLE_LEFT 2560 //This is the open in encoder counts
#define CLOSED_SERVO_ANGLE_RIGHT 1975 //This is the closed in encoder counts
#define OPEN_SERVO_ANGLE_RIGHT 2560 //This is the open in encoder counts
//AD7730( mosi, miso, sclk, ready, cs)
AD7730 adc(p11, p12, p13, p14, p15);
//AD7730 adc2(p11, p12, p13, p18, p19);
AnalogIn AinJoystickFwdBk(p17); //Set up potentiometer on pin 17
AnalogIn AinJoystickLftRt(p16); //Set up potentiometer on pin 16
float JoystickFwdBk_Zero=0.5;
float JoystickLftRt_Zero=0.5;
/// Set these to inputs so that they don't interfere with the serial communication
DigitalIn nullOut1(p21);
DigitalIn nullOut2(p22);
DigitalIn nullOut3(p23);
DigitalIn nullOut4(p24);
/// This one is in the way of the SMD pads
DigitalIn nullOut5(p20);
#else
float samplingPeriod = 0.001; //This is the sampling period for the timer interrupt
#define SERVO_DEGREE_0 900 //This is the pulse width value for HiTEC-422 in microseconds to turn 0 degrees
#define SERVO_DEGREE_180 2100 //This is the pulse width value for HiTEC-422 in microseconds to turn 180 degrees
#define MIN_SERVO_ANGLE 0.0 //This is the minimum servo angle in degrees
#define MAX_SERVO_ANGLE 180.0 //This is the maximum servo angle in degrees
#define MIN_SERVO_ANGLE_Da_VINCI 20.0 //This is the minimum servo angle in degrees
#define MAX_SERVO_ANGLE_Da_VINCI 100.0 //This is the maximum servo angle in degrees
const float servoConversion = ((SERVO_DEGREE_180-SERVO_DEGREE_0)/(MAX_SERVO_ANGLE - MIN_SERVO_ANGLE))/1000000.0; //This is the interpolation between min and max servo values
const float servoOffset = SERVO_DEGREE_0/1000000.0; //This is the pulsewidth value (in seconds) that corresponds to 0 degrees (i.e.-the offset)
PwmOut myServoLeft(p21); //Set up servo on pin 21
PwmOut myServoRight(p22); //Set up servo on pin 22
AnalogIn AinLeftPosition(p20); //Set up potentiometer on pin 20
AnalogIn AinRightPosition(p19); //Set up potentiometer on pin 20
// Function moveServoTo: Convert a degree value to pulsewidth for Servo
void moveServoTo(float angle) {
// Make sure none of the user input falls outside of min and max angle limits
if( angle < MIN_SERVO_ANGLE){angle = MIN_SERVO_ANGLE;}
else if(angle > MAX_SERVO_ANGLE){angle = MAX_SERVO_ANGLE;}
myServoLeft.pulsewidth(servoOffset + servoConversion*(180-angle));
myServoRight.pulsewidth(servoOffset + servoConversion*(angle));
}
#endif
void serialInterrupt(char buffer){
input_buffer[input_buffer_location]=buffer;
input_buffer_location++;
bits_received+=8;
//pc.printf("RC:%d\n",buffer);
//Is the packet looking good so far??
if(input_buffer[0]==0xFF){
//Is the packet looking good so far??????
if(input_buffer[1]==0xFF || input_buffer_location ==1){
//Do we have a complete packet??
if(input_buffer_location>=6){ //This is 6 because we already incremented
//We do! Extract the jucy datas
left_servo_measured = ( input_buffer[2] << 8 ) | input_buffer[3];
right_servo_measured = ( input_buffer[4] << 8 ) | input_buffer[5];
//pc.printf("RP:%d,%d\n",left_servo_measured,right_servo_measured);
//Reset the buffer location so we can start over
input_buffer_location=0;
}
}else{
//Something is wrong. We may just not be at the correct location in the packet
//Reset the buffer location so we can start over
input_buffer_location=0;
//printf("Error, Byte 2 not what was expected: 0xFF!=0x%02x\n",input_buffer[1]);
}
}else{
//Something is wrong. We may just not be at the correct location in the packet
//Reset the buffer location so we can start over
input_buffer_location=0;
//printf("Error, Byte 1 not what was expected: 0xFF!=0x%02x\n",input_buffer[0]);
}
}
// Function trapezoidalTrajectory: Function that takes in a time (float in seconds) and outputs a float (0 to 1) that corresponds to a trapezoidal trajectory
float trapezoidalTrajectory(float t, jaw_state &state, unsigned char &cycle_num) {
// Define variables specific to this function
float y_trapezoid = 0.0;
float timeMod;
float modifiedFrequency = g_frequency/2.0;
float period = 1/modifiedFrequency;
cycle_num=t*modifiedFrequency;
// Take the time and mod it with the period to be able to break up each cycle into 4 piecewise sections
timeMod = fmodf(t,period);
//
if (timeMod < period/4.0)
{
y_trapezoid = (-4.0/period)*(timeMod)+1.0;
state = STATE_CLOSING;
}
else if (timeMod >= period/4.0 && timeMod < period/2.0)
{
y_trapezoid = 0.0;
state = STATE_CLOSE_HOLD;
}
else if (timeMod >= period/2.0 && timeMod < 3*period/4.0)
{
y_trapezoid = (4.0/period)*(timeMod)-2;
state = STATE_OPENING;
}
else if (timeMod >= 3*period/4.0)
{
y_trapezoid = 1.0;
state = STATE_OPEN_HOLD;
}
return y_trapezoid;
}
void sinusoidalTrajectory(float t, jaw_state &state, unsigned char &cycle_num) {
//Fill me with SCIENCE!!!
}
// Function timerISRFunction: Timer ISR function to collect data and write to ring buffer
void timerISRFunction() {
//led 1 is used as a 'thinking' light, brighter=worse
led1 = 1;
led2 = 0;
triggerOut = 1;
ISRDurationTimer.reset();
ISRDurationTimer.start();
if(g_current_mode==MODE_AUTOMATIC){
// Warning, this calculation is in the ISR and as such is probably slower than we would prefer.
// @todo The math could certainly be optimized with some precalculated constants. Lookup tables are faster than sin()
float percent=trapezoidalTrajectory(g_current_trajectory_time,g_current_direction,g_current_cycle);
g_current_trajectory_time+=samplingPeriod;
//float angle=g_current_trajectory_time*g_frequency*2.0*M_PI-M_PI_2;
//g_current_direction=(cos(angle)<0);
//g_current_cycle=(angle+M_PI_2)/(2.0*M_PI);
#ifdef USE_DYNAMIXELS
//float percent=(sin(angle)+1)/2.0;
if(adc.isReady()){
adc.interruptRead();
}
while(cm.readable()){
led4=1;
serialInterrupt(cm.getc());
}
led4=0;
short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT;
//Send the commanded position to the OpenCM board
cm.putc(0xFF);
cm.putc(0xFF);
cm.putc(left_servo >> 8); //Top 4 bits
cm.putc(left_servo & 0xFF); //Bottom 8 bits
cm.putc(right_servo >> 8); //Top 4 bits
cm.putc(right_servo & 0xFF); //Bottom 8 bits
tempSpindleData.myServoData[LEFT_SERVO_INDEX].force = adc.read();
tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos = left_servo_measured;
tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = 0;
tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos = right_servo_measured;
tempSpindleData.direction=g_current_direction;
tempSpindleData.cycle=g_current_cycle;
Buffer.write(tempSpindleData);
#else
g_theta=(1.0-percent)*(MAX_SERVO_ANGLE_Da_VINCI-MIN_SERVO_ANGLE_Da_VINCI)+MIN_SERVO_ANGLE_Da_VINCI;
tempSpindleData.myServoData[LEFT_SERVO_INDEX].force = AinLeftForce.read_u16();
tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos = AinLeftPosition.read_u16();
tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16();
tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos = AinRightPosition.read_u16();
tempSpindleData.direction=g_current_direction;
tempSpindleData.cycle=g_current_cycle;
Buffer.write(tempSpindleData);
moveServoTo(g_theta); // in degrees, son
#endif
}else if(g_current_mode==MODE_MANUAL){
g_current_trajectory_time+=samplingPeriod;
if(adc.isReady()){
adc.interruptRead();
}
int im_tired_of_this_game=0;
while(cm.readable() && im_tired_of_this_game++<100){
serialInterrupt(cm.getc());
}
// float pot_open=0.75;
// float pot_closed=0.48;
//
// float percent=AinJoystickFwdBk.read();
// percent=(pot_open-percent)/(pot_open-pot_closed);
// float skew =0;//AinJoystickLftRt.read()-JoystickLftRt_Zero;
//
// // The 'pulling' of the trigger corresponds to open/closed
// short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
// short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT;
//
// g_input_pot_1=left_servo;
short left_servo =g_command_corrected;
short right_servo=g_command_corrected;
// // The 'skewing' of the trigger corresponds to yawing the jaws left or right, while maintaining open/closed
// left_servo +=skew*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT );
// right_servo-=skew*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT);
//
// /// Todo: There is undoubtedly a cleaner way to do this.
// if(OPEN_SERVO_ANGLE_LEFT < CLOSED_SERVO_ANGLE_LEFT && left_servo < OPEN_SERVO_ANGLE_LEFT ){left_servo =OPEN_SERVO_ANGLE_LEFT; }
// if(OPEN_SERVO_ANGLE_LEFT > CLOSED_SERVO_ANGLE_LEFT && left_servo > OPEN_SERVO_ANGLE_LEFT ){left_servo =OPEN_SERVO_ANGLE_LEFT; }
// if(OPEN_SERVO_ANGLE_RIGHT < CLOSED_SERVO_ANGLE_RIGHT && right_servo < OPEN_SERVO_ANGLE_RIGHT){right_servo=OPEN_SERVO_ANGLE_RIGHT;}
// if(OPEN_SERVO_ANGLE_RIGHT > CLOSED_SERVO_ANGLE_RIGHT && right_servo > OPEN_SERVO_ANGLE_RIGHT){right_servo=OPEN_SERVO_ANGLE_RIGHT;}
//
// // Just to make sure
// // left_servo=(left_servo+4096)%4096;
// if(left_servo < 0){left_servo = 0;}
// if(left_servo >4095){left_servo =4095;}
// if(right_servo< 0){right_servo= 0;}
// if(right_servo>4095){right_servo=4095;}
//Send the commanded position to the OpenCM board
cm.putc(0xFF);
cm.putc(0xFF);
cm.putc(left_servo >> 8); //Top 4 bits
cm.putc(left_servo & 0xFF); //Bottom 8 bits
cm.putc(right_servo >> 8); //Top 4 bits
cm.putc(right_servo & 0xFF); //Bottom 8 bits
#ifdef ROD_IS_RIGHT
//Famous Rod's Magical World of Good Ideas Part 1
int angle=left_servo_measured;
angle_sum+=angle;
if(angle_count!=0){
int angledot=(angle-last_angle);
angledot_sum+=angledot;
if(angledot_count!=0){
int angledotdot=(angledot-last_angledot);
angledotdot_sum+=angledotdot;
angledotdot_count++;
}
angledot_count++;
last_angledot=angledot;
}
angle_count++;
last_angle=angle;
#else
// John's worse than Rod ideas of terribleness
if(!crunching_data_flag){ // Only add data if no one is using it
recent_pos.add_data(left_servo_measured,g_current_trajectory_time);
}
#endif
}
//done thinking
led1 = 0;
led2 = 1;
triggerOut = 0;
ISRDurationTimer.stop();
current_latency=ISRDurationTimer.read_us();
if(current_latency>worst_latency){
worst_latency=current_latency;
}
}
// Calibrate Load Cell Function
void calibrateLoadCell() {
int loadCellTotal = 0;
for(int ii=0;ii<CALIBRATION_READS;ii++){
loadCellTotal=adc.read();
pc.printf("Am I crazy?!?!?!?!: %d \n",loadCellTotal);
//pc.printf("We are calibrating load cells...\n");
}
g_calibration_offset=loadCellTotal/CALIBRATION_READS;
}
int main() {
// Crazy fast baud rate!
pc.baud(115200);
// For communication with OpenCM 9.04 Board
cm.baud(1000000);
#ifdef USE_BLUETOOTH
bt.baud(9600);
#endif
// Attach ISR routines
potISR.attach(&timerISRFunction, samplingPeriod); // setup serialPot to call every samplingPeriod
// Some debug info:
//DisplayRAMBanks();
//printf ("System clock = %d\r\n", SystemCoreClock);
pc.printf("\n\n\n");
pc.printf("----------------------------------\n");
pc.printf("| |\n");
pc.printf("| Welcome to our mbed! |\n");
pc.printf("| |\n");
pc.printf("| John and Trevor, Proprietors |\n");
pc.printf("| |\n");
pc.printf("----------------------------------\n");
pc.printf(" ||\n");
pc.printf(" ||\n");
pc.printf(" || _\n");
pc.printf(" || _( )_\n");
pc.printf(" || (_(#)_)\n");
pc.printf(" || (_)\\\n");
pc.printf(" || | __\n");
pc.printf(" \\ / | || |/_/\n");
pc.printf(" / | | / / / | || | \\ \\ | / \n");
pc.printf("/ / \\ \\ / / / || / | / / \\ \\ \n");
pc.printf("#################################\n");
pc.printf("#################################\n");
pc.printf("\n\n");
#ifdef USE_DYNAMIXELS
adc.setFilter(256 , false, 1);
adc.start();
JoystickLftRt_Zero=0;
int calib_N=100;
for(int ii=0;ii<calib_N;ii++){JoystickLftRt_Zero+=AinJoystickLftRt.read();}
JoystickLftRt_Zero=JoystickLftRt_Zero/calib_N;
g_current_mode=MODE_MANUAL;
#else
// Configure Servo for HiTec 422
myServoLeft.period_ms(20);
myServoRight.period_ms(20);
#endif
// Begin Calibration of load cells
// Calibrate Load Cells (Does this need to get moved somewhere else?)
//calibrateLoadCell();
printf("Setup Complete.\n");
AuxSerialTimer.start();
mytimer.start();
while(1)
{
// spin in a main loop. serialISR will interrupt it to call serialPot
#ifdef USE_DYNAMIXELS
#endif
///This checks for any new serial bytes, and returns true if
///we have an entire packet ready. The new packet will live
///in newData.
if(
#ifdef USE_BLUETOOTH
receivePacket(bt)
#else
receivePacket(pc)
#endif
)
{
// < Tissue Type (string), Frequency Value (Hz) (int), Force Max (N) (int), # Cycles (in) >
//<date/tissue/time,2,3,4>
//g_tissue_type_name=tissue_type_name;
std::string file_name_in=inString.substr(0, inString.find(","));
g_frequency=newData[1]/10.0; // Since all we send are ints
g_max_force=newData[2];
g_num_cycles=newData[3];
g_current_trajectory_time=0;
g_current_cycle=0;
#ifdef USE_SD_CARD
int first_slash=file_name_in.find("/");
std::string new_dir="/sd/"+file_name_in.substr(0, first_slash);
std::string new_subdir="/sd/"+file_name_in.substr(0, file_name_in.find("/",first_slash+1));
mkdir(new_dir.c_str(), 0777);
mkdir(new_subdir.c_str(), 0777);
std::string file_name="/sd/"+file_name_in+".csv";
//pc.printf("subdir=\"%s\"\n",file_name.c_str());
fp = fopen(file_name.c_str(), "w");
//FILE *fp = fopen("/sd/data/sdtest.txt", "w");
if(fp == NULL) {
error("Could not open file for write\n");
}
fprintf(fp, "%%Starting New Trajectory\n");
fprintf(fp, "%%File Name=\"%s\"\n",file_name.c_str());
fprintf(fp, "%%Current Mode=AUTOMATIC\n");
fprintf(fp, "%%Trajectory Type=TRAPEZOIDAL\n");
fprintf(fp, "%%Frequency=%f Hz\n",g_frequency);
fprintf(fp, "%%Max Force=%f ??\n",g_max_force);
fprintf(fp, "%%Num Cycles=%d\n",g_num_cycles);
fprintf(fp, "%%Re. Direction: ,Closing=%d,Opening=%d,Undef=%d\n", DIRECTION_CLOSING , DIRECTION_OPENING , DIRECTION_SLACK_WATER );
fprintf(fp, "%%PositionLeft,ForceLeft,PositionRight,ForceRight,Time(ms),Direction,CycleNum\n");
#endif
// We are go-times!
g_current_mode=MODE_AUTOMATIC;
}
if( g_current_mode==MODE_AUTOMATIC && g_current_cycle >= g_num_cycles)
{
// STOOOOOOOOOP
g_current_mode=MODE_NULL;
#ifdef USE_SD_CARD
// Close the file
fclose(fp);
fp = NULL;
#endif
}
// This section of code should run whenever there is free time to save datas
#ifdef USE_SD_CARD
if(fp != NULL) {
// Only write to SD if there is a valid file handle
led3 = 1;
Buffer.dumpBufferToSD(fp);
led3 = 0;
}
#else
//Warning, this is a big fat stream of data, 1 minute is approx 3MB
//I certainly recommend using the SD card.
Buffer.dumpBufferToSerial();
#endif
if(g_current_mode!=MODE_NULL && AuxSerialTimer.read_us()>30000){
//Send some extra data for GUI purposes
#ifdef ROD_IS_RIGHT
float angle=0,angledot=0,angledotdot=0;
if(angledotdot_count>0){
angle =float(angle_sum )/angle_count;
angledot =float(angledot_sum )/angledot_count;
angledotdot=float(angledotdot_sum)/angledotdot_count;
}
angle_sum=0;angle_count=0;
angledot_sum=0;angledot_count=0;
angledotdot_sum=0;angledotdot_count=0;
#else
crunching_data_flag=true;
recent_pos.least_squares_3rd(coeffs);
crunching_data_flag=false;
float x=g_current_trajectory_time;
int angle =coeffs[0]+coeffs[1]*x+coeffs[2]*x*x+coeffs[3]*x*x*x;
int angledot = coeffs[1]+2*coeffs[2]*x+3*coeffs[3]*x*x ;
int angledotdot= 2*coeffs[2] +6*coeffs[3]*x ;
#endif
float pot_open=0.75;
float pot_closed=0.48;
float percent=0.0;
//Average the pot a bunch, it's NOISY
for(int i=0;i<100;i++){
percent+=AinJoystickFwdBk.read();
}
percent=percent/100.0;
percent=(pot_open-percent)/(pot_open-pot_closed);
// The 'pulling' of the trigger corresponds to open/closed
int potread =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
//angle=left_servo_measured;
int loadcell=adc.read();
// Code to determine if we should toggle the variable of "g_we_are_grasping"
if(!g_we_are_grasping && loadcell>entry_threshold && angledot<velocty_threshold){
//Grasp is starting
g_we_are_grasping=true;
for(int i=0;i<NUMBER_OF_TISSUES;i++){
g_error_norm[i]=0.0;
}
}
if(g_we_are_grasping && angledot>-velocty_threshold){
//Grasp is over
g_we_are_grasping=false;
}
float alpha=0;
std::string sstr;
if(g_we_are_grasping){
//D_x = [thetadotdot,thetadot,theta,theta^2,theta^3];
g_error_norm[0]+=fabs(float(loadcell)-(Phi1[0]*angledotdot+Phi1[1]*angledot+Phi1[2]*angle+Phi1[3]*angle*angle+Phi1[4]*angle*angle*angle));
g_error_norm[1]+=fabs(float(loadcell)-(Phi2[0]*angledotdot+Phi2[1]*angledot+Phi2[2]*angle+Phi2[3]*angle*angle+Phi2[4]*angle*angle*angle));
float offset1 = 100000;
float offset2 = 300000;
int tissue_id=0;
if(g_error_norm[1]>g_error_norm[0]){alpha=(g_error_norm[1]-g_error_norm[0])/(g_error_norm[1]+offset1);sstr="HARD";tissue_id=0;}
if(g_error_norm[0]>g_error_norm[1]){alpha=(g_error_norm[0]-g_error_norm[1])/(g_error_norm[0]+offset2);sstr="SOFT";tissue_id=1;}
float force_err=loadcell-g_thresh_force[tissue_id];
float k=20/0.1e6;
g_command_corrected=(1-alpha)*potread+alpha*(k*force_err+angle);
}else{
g_command_corrected=potread;
}
//std::vector<int> data_in=<angle, angledot, angledotdot, loadcell, potread>
printf("Data:,%6.3f,%0.0f,% 2.3f,% 2.3f,%d,%d,%0.0f,%0.0f,%12.3f,%s\n",mytimer.read_us()/1000.0,angle, angledot, angledotdot, loadcell, potread,g_error_norm[1]*angle,g_error_norm[1],g_calibration_offset,sstr.c_str());
//printf("%s",recent_pos.get_string().c_str());
// printf("<%d,%d,%d,%d,%d,%d,%d> ",tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos,
// tempSpindleData.myServoData[LEFT_SERVO_INDEX].force,
// tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos,
// tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force,
// tempSpindleData.time,
// tempSpindleData.direction,
// tempSpindleData.cycle);
// printf(" %dus", worst_latency);
// worst_latency=0;
// printf(" %0.0fbps\n", bits_received*1000.0/AuxSerialTimer.read_ms());
// bits_received=0;
AuxSerialTimer.reset();
}
}
}
