2022-10-21 12:55:06 +02:00
# include <Braccio.h>
# include <Servo.h>
# include <math.h>
Servo base ;
Servo shoulder ;
Servo elbow ;
Servo wrist_rot ;
Servo wrist_ver ;
Servo gripper ;
2022-10-03 12:00:55 +02:00
# define PI 3.14159265359
# define PIdiv2 PI / 2
2022-10-07 13:01:02 +02:00
const float shoulder_and_elbow_length = 12.5 ;
2022-10-03 12:00:55 +02:00
const float shoulder_plus_elbow_length = shoulder_and_elbow_length * 2 ;
2022-10-07 13:01:02 +02:00
const float wrist_length = 19 ;
2022-10-03 12:00:55 +02:00
class Vec2 {
public :
Vec2 ( float _x , float _y ) : x ( _x ) , y ( _y ) { }
float x , y ;
} ;
class Vec4 {
public :
Vec4 ( float _x , float _y , float _z , float _w ) : x ( _x ) , y ( _y ) , z ( _z ) , w ( _w ) { }
Vec4 to_rotation ( ) {
float base_angle = atan2 ( x , y ) ;
float wRAD = w * PI / 180 ;
// take the wrist into account
Vec2 target_position = Vec2 ( hypotf ( x , y ) - sin ( wRAD ) * wrist_length , - z + cos ( wRAD ) * wrist_length ) ;
/////// shoulder and elbow angles calculations ///////
// calculate distance beetween the arm base and the target position and then clamp it to 1
float target_base_distance = hypotf ( target_position . x , target_position . y ) / shoulder_plus_elbow_length ;
if ( target_base_distance > 1 ) {
target_base_distance = 1 ;
}
// set shoulder angle to arm bend angle from distance from target position to base position
float shoulder_angle = asin ( target_base_distance ) ;
// calculate shoulder angle from the shoulder angle before performing another calculation on it
float elbow_angle = PI - ( shoulder_angle * 2 ) ;
// add angle beetween the target position and the base position to the shoulder angle
shoulder_angle + = atan2 ( target_position . y , target_position . x ) ;
///////// wrist angle calculation ///////
float shoulder_plus_elbow_angle = shoulder_angle + elbow_angle ; // shoulder angle + elbow angle
//Serial.println(shoulder_plus_elbow_angle);
//Serial.println(wRAD);
float wrist_angle = wRAD - shoulder_plus_elbow_angle ; // # target wrist angle - shoulder_plus_elbow_angle so the wrist angle is always fixes to the base rotation
return Vec4 ( base_angle * 180 / PI , shoulder_angle * 180 / PI + 90 , elbow_angle * 180 / PI + 90 , wrist_angle * 180 / PI + 90 ) ;
}
void print ( ) {
//Serial.println(x);
Serial . println ( y ) ;
Serial . println ( z ) ;
Serial . println ( w ) ;
Serial . println ( " ================== " ) ;
}
float x , y , z , w ;
} ;
2022-10-21 12:55:06 +02:00
// communication
Vec4 read ( ) {
float x = parseFloat ( ) ;
float y = parseFloat ( ) ;
float z = parseFloat ( ) ;
float w = parseFloat ( ) ;
return Vec4 ( x , y , z , w ) ;
}
void setup ( ) {
Serial . begin ( 9600 ) ;
Braccio . begin ( ) ;
pinPeripheral ( PIN_SERIAL1_TX , PIO_SERCOM ) ;
pinPeripheral ( PIN_SERIAL1_RX , PIO_SERCOM ) ;
}
void loop ( ) {
Vec4 targ = read ( ) ;
Vec4 rot = targ . to_rotation ( ) ;
// speed inverse knematics wrist rot grip
Braccio . ServoMovement ( 30 , rot . x , rot . y , rot . z , rot . w , 90 , 70 ) ;
}