Sam
main.cpp
- Committer:
- s0313045
- Date:
- 2020-09-13
- Revision:
- 2:611a5eb132a1
- Parent:
- 1:58d1caed28d4
File content as of revision 2:611a5eb132a1:
#include "mbed.h"
#include "ros.h"
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Twist.h>
#include <geometry_msgs/Quaternion.h>
#include <geometry_msgs/TransformStamped.h>
#include <tf/tf.h>
#include <tf/transform_broadcaster.h>
#include "actiondrv.h"
#include "millis.h"
/*
* ActionEncoder.cpp
*
* Created on: 7 Mar 2018
* Author: tung
*/
#include "ActionEncoder.hpp"
#include "Timer.h"
///////////////////////////
//Serial Action(D8,D2 ); // tx, rx
Serial Action(PB_6, PB_7 );
//Serial pc(USBTX, USBRX);
union {
uint8_t data[24];
float val[6];
} posture;
int count=0;
int i=0;
int done=0;
float xangle=0;
float yangle=0;
float zangle=0;
float d_angle=0;
float pos_x=0;
float pos_y=0;
float angleSpeed=0;
float temp_zangle=0;
int LastRead=0;
bool newDataArrived=false;
char buffer[8];
//Serial pc(USBTX, USBRX);
char counter = 0;
actionDrv action1(3); //1
actionDrv action2(1); //2
actionDrv action3(2); //3
int motor1 = 0;
int motor2 = 0;
int motor3 = 0;
int motor4 = 0;
float pi = 3.14159265;
double pi_div_3 = 1.04719755;
float d = 0.525;//0.43;
float wheelR = 0.0508; //4 inch wheel
float gear = 10;
Ticker motor_updater;
Ticker odom_updater;
Ticker ros_updater;
////////////////////////////////////
float now_x=0;
float now_y=0;
float now_w=0;
float target_x=0;
float target_y=0;
float target_w=0;
float tolerance_x=0.02;
float tolerance_y=0.02;
float tolerance_w=0.01;
float speed_max_x=1;
float speed_max_y=1;
float speed_max_w=1;
long odom_last_read= millis();
/////////////////////////////////////
const float RATE = 0.18;
//////////////////////////
///////////////////////////
float encoder_2_global_angle = -90; //encoder coordinate system + 30 degree => global coordinate system
//float encoder_2_global_x = 0.34; //encoder to center distance in x (tung)
//float encoder_2_global_y = -0.235; //encoder to center distance in y (tung)
float encoder_2_global_x = 0.33;//0.125; //encoder to center distance in x (tung)
float encoder_2_global_y = 0.24;//0.37; //encoder to center distance in y (tung)
////////////////////TUNG////////////////
float transformed_real_now_x=0;
float transformed_real_now_y=0;
float transformed_real_now_w=0;
float startup_offset_x_encoder =0;
float startup_offset_y_encoder =0;
float startup_offset_w_encoder=0;
float encoder_to_center = sqrt( ( encoder_2_global_x * encoder_2_global_x ) + ( encoder_2_global_y * encoder_2_global_y ) );
//#########################//
float encoder2local_angle = -90 *pi/float(180);
float encoder_position_angle =( ( 360-36.02737) ) / float(180) * pi ; //90 + angle to encoder location
float r = sqrt( ( encoder_2_global_x * encoder_2_global_x ) + ( encoder_2_global_y * encoder_2_global_y ) ); //encoder to center radius
void calculatePos(float _X,float _Y,float _A)
{
float zangle = _A- 360 * int(_A / 360);
float zrangle = zangle *pi/float(180); //degree 2 rad
float tx = ( ( _X / float(1000) ) * cos( -encoder2local_angle) ) - ( ( _Y / float(1000) ) * sin( -encoder2local_angle) );
float ty = ( ( _X / float(1000) ) * sin( -encoder2local_angle) ) + ( ( _Y / float(1000) ) * cos( -encoder2local_angle) );
float s = copysign( sqrt( 2*( r*r ) - 2*(r*r)*cos(zrangle) ) , zrangle );
float x_bias = s * cos( zrangle / 2 );
float y_bias = s * sin( zrangle / 2 );
float x_tbias = ( x_bias ) * ( cos( encoder_position_angle) ) - ( y_bias ) * ( sin( encoder_position_angle ) ) ;
float y_tbias = ( x_bias ) * ( sin( encoder_position_angle) ) + ( y_bias ) * ( cos( encoder_position_angle ) ) ;
transformed_real_now_x = tx + y_tbias - startup_offset_x_encoder; //-
transformed_real_now_y = ty - x_tbias - startup_offset_y_encoder;
//transformed_real_now_x = tx + y_tbias - startup_offset_x_encoder; //+
//transformed_real_now_y = ty - x_tbias - startup_offset_y_encoder;
transformed_real_now_w= _A *pi/float(180) - startup_offset_w_encoder;
}
///////////////////////
float x_PID_P = 0.5;
float y_PID_P = 0.5;
float w_PID_P = 1;
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
//////////////////////////////
void start_calculatePos(float _X,float _Y,float _A)
{
float zangle = _A- 360 * int(_A / 360);
float zrangle = zangle *pi/float(180); //degree 2 rad
float tx = ( ( _X / float(1000) ) * cos( -encoder2local_angle) ) - ( ( _Y / float(1000) ) * sin( -encoder2local_angle) );
float ty = ( ( _X / float(1000) ) * sin( -encoder2local_angle) ) + ( ( _Y / float(1000) ) * cos( -encoder2local_angle) );
float s = copysign( sqrt( 2*( r*r ) - 2*(r*r)*cos(zrangle) ) , zrangle );
float x_bias = s * cos( zrangle / 2 );
float y_bias = s * sin( zrangle / 2 );
float x_tbias = ( x_bias ) * ( cos( encoder_position_angle) ) - ( y_bias ) * ( sin( encoder_position_angle ) ) ;
float y_tbias = ( x_bias ) * ( sin( encoder_position_angle) ) + ( y_bias ) * ( cos( encoder_position_angle ) ) ;
startup_offset_x_encoder = tx + y_tbias ; //-
startup_offset_y_encoder = ty - x_tbias ;
//startup_offset_x_encoder = tx + y_tbias ;
//startup_offset_y_encoder = ty - x_tbias ; //+
startup_offset_w_encoder = _A *pi/float(180); //degree 2 rad
}
void ActionEncoder_init()
{
count=0;
i=0;
done=0;
xangle=0;
yangle=0;
zangle=0;
d_angle=0;
pos_x=0;
pos_y=0;
angleSpeed=0;
temp_zangle=0;
LastRead=0;
newDataArrived=false;
}
bool readEncoder(char c)
{
//sprintf(buffer,"%02X",c);
//sprintf(buffer,"%X",c);
//pc.printf(buffer);
//pc.printf("\r\n");
//sprintf(buffer,"%d",count);
//pc.printf(buffer);
//pc.printf("\r\n");
switch(count) {
case 0:
if (c==0x0d) count++;
else count=0;
break;
case 1:
if(c==0x0a) {
i=0;
count++;
} else if(c==0x0d) {}
else count=0;
break;
case 2:
posture.data[i]=c;
i++;
if(i>=24) {
i=0;
count++;
}
break;
case 3:
if(c==0x0a)count++;
else count=0;
break;
case 4:
if(c==0x0d) {
d_angle=posture.val[0]-temp_zangle;
if (d_angle<-180) {
d_angle=d_angle+360;
} else if (d_angle>180) {
d_angle=d_angle-360;
}
now_w+=d_angle;
temp_zangle=posture.val[0];
//xangle=posture.val[1];
//yangle=posture.val[2];
now_x=posture.val[3];
now_y=posture.val[4];
//angleSpeed=posture.val[5];
newDataArrived=true;
}
count=0;
done=1;
LastRead=millis();
return true;
//break;
default:
count=0;
break;
}
return false;
}
//void inverse(float global_x_vel, float global_y_vel, float w_vel) const std_msgs::UInt16& cmd_msg
void inverse(const geometry_msgs::Twist& cmd_vel)
{
float global_vel_x = cmd_vel.linear.x;
float global_vel_y = cmd_vel.linear.y;
float w_vel = cmd_vel.angular.z;
float local_x_vel = global_vel_x * cos( -transformed_real_now_w ) - global_vel_y * sin( -transformed_real_now_w );
float local_y_vel = global_vel_x * sin( -transformed_real_now_w ) + global_vel_y * cos( -transformed_real_now_w ); //local to global transformation (angle only)
motor1 = int( ( (-1) * sin(pi_div_3) * local_x_vel + cos(pi_div_3) * local_y_vel + d * w_vel ) * 60 / (wheelR * 2 * pi) * gear );
motor2 = int( ( (-1) * local_y_vel + d * w_vel ) * 60 / (wheelR * 2 * pi) * gear );
motor3 = int( ( sin(pi_div_3) * local_x_vel + cos(pi_div_3) * local_y_vel + d * w_vel ) * 60 / (wheelR * 2 * pi) * gear );
}
/////////////////////////
ros::NodeHandle nh;
ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", &inverse );
nav_msgs::Odometry odom;
geometry_msgs::TransformStamped odom_trans;
ros::Publisher odom_publisher("odom", &odom);
tf::TransformBroadcaster odom_broadcaster;
/////////////////////////
void motor_update()
{
action1.SetVelocity_mod(motor1 * -1 );
action2.SetVelocity_mod(motor2 * -1 );
action3.SetVelocity_mod(motor3 * -1 );
wait(0.005);
}
void ros_update()
{
odom_publisher.publish( &odom );
odom_broadcaster.sendTransform(odom_trans);
wait(0.005);
nh.spinOnce();
}
void odom_update()
{
calculatePos(now_x,now_y,now_w);
//geometry_msgs::Quaternion odom_quat = createQuaternionMsg(transformed_real_now_w );
geometry_msgs::Quaternion odom_quat = tf::createQuaternionFromYaw(transformed_real_now_w); // *57.2957795
//first, we'll publish the transform over tf
odom_trans.header.stamp = nh.now();
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";
odom_trans.transform.translation.x = transformed_real_now_x ;
odom_trans.transform.translation.y = transformed_real_now_y ;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = odom_quat;
//send the transform
//next, we'll publish the odometry message over ROS
//nav_msgs::Odometry odom;
odom.header.stamp = nh.now();
odom.header.frame_id = "odom";
odom.child_frame_id = "base_link";
//set the position
odom.pose.pose.position.x = transformed_real_now_x;
odom.pose.pose.position.y = transformed_real_now_y ;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = odom_quat;
//set the velocity
//odom.child_frame_id = "base_link";
//odom.twist.twist.linear.x = vx;
//odom.twist.twist.linear.y = vy;
//odom.twist.twist.angular.z = vth;
//publish the message
//
}
int main() {
millisStart();
Action.baud(115200);
Action.format(8,SerialBase::None,1);
ActionEncoder_init();
nh.initNode();
odom_broadcaster.init(nh);
nh.advertise(odom_publisher);
nh.subscribe(sub);
while (!nh.connected() ) {nh.spinOnce();}
odom_trans.header.stamp = nh.now();
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";
odom_trans.transform.translation.x = 0.0;
odom_trans.transform.translation.y = 0.0 ;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = tf::createQuaternionFromYaw(0);
odom.header.stamp = nh.now();
odom.header.frame_id = "odom";
odom.child_frame_id = "base_link";
//set the position
odom.pose.pose.position.x = transformed_real_now_x;
odom.pose.pose.position.y = transformed_real_now_y ;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = tf::createQuaternionFromYaw(0);;
ros_updater.attach(&ros_update, 0.3);
while(1)
{
if (Action.readable())
{
char c = Action.getc();
if (readEncoder(c))
{
//startup_offset_x_encoder = now_x/1000;
//startup_offset_y_encoder = now_y/1000;
//startup_offset_w_encoder = now_w/float(180)*pi;
start_calculatePos( (now_x),(now_y), now_w ); //global
break;
}
}
} //start first to take offset from encoder... in case already moved
for( int a = 1; a < 2; a++ ){
action1.Enable();
action2.Enable();
action3.Enable();
wait(0.1);
action1.SetOperationalMode();
action2.SetOperationalMode();
action3.SetOperationalMode();
wait(0.1);
action1.Configvelocity(100000, 100000);
action2.Configvelocity(100000, 100000);
action3.Configvelocity(100000, 100000);
wait(0.1);
}
motor_updater.attach(&motor_update, RATE);
//odom_updater.attach(&odom_update, RATE);
ros_updater.attach(&ros_update, 0.5);
while(1)
{
if (Action.readable())
{
//pc.putc('a');
char c = Action.getc();
if(readEncoder(c)) odom_update();
}
}
}