I HAVE A PROBLEM WHILE EXECUTING THE CODE, IF YOU CAN HELP ME I'D LOVE IT
navbot
> #include "Motor.h"
> #include <ros.h>
> #include <geometry_msgs/Twist.h>
> #include<PID_v1.h>
> #include <geometry_msgs/Vector3Stamped.h>
> #include <ros/time.h>
> #include <std_msgs/Int16.h>
>
>
> ros::NodeHandle nh;
>
> int updatenh;
> int pos_act_left;
> int pos_act_right;
>
> #define LOOPTIME 10
>
> Motor right(11,10,3,2);
> Motor left(9,8,5,4);
>
> volatile long encoder0Pos = 0; // encoder 1
> volatile long encoder1Pos = 0; // encoder 2
>
> double left_kp = 17 , left_ki = 0 , left_kd = 0; // modify for optimal performance
> double right_kp = 20 , right_ki = 0 , right_kd = 0;
>
>
> float demandx=0;
> float demandz=0;
>
> double demand_speed_left;
> double demand_speed_right;
>
> double right_input = 0, right_output = 0, right_setpoint = 0;
> PID rightPID(&right_input, &right_output, &right_setpoint, right_kp, right_ki, right_kd, DIRECT);
>
> double left_input = 0, left_output = 0, left_setpoint = 0;
> PID leftPID(&left_input, &left_output, &left_setpoint, left_kp, left_ki, left_kd, DIRECT);
>
> unsigned long currentMillis;
> unsigned long prevMillis;
>
> float encoder0Diff;
> float encoder1Diff;
>
> float encoder0Error;
> float encoder1Error;
>
> float encoder0Prev;
> float encoder1Prev;
>
> void cmd_vel_cb( const geometry_msgs::Twist& twist){
> demandx = twist.linear.x;
> demandz = twist.angular.z;
> }
>
> ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", cmd_vel_cb ); //create a "speed_msg" ROS message
> std_msgs::Int16 left_wheel_msg;
> ros::Publisher left_wheel_pub("lwheel" , &left_wheel_msg);
> std_msgs::Int16 right_wheel_msg;
> ros::Publisher right_wheel_pub("rwheel" , &right_wheel_msg); //create a publisher to ROS topic "speed" using the "speed_msg" type
>
> double pos_act_left = 0;
> double pos_act_right = 0;
>
> void setup() {
> nh.initNode();
> nh.subscribe(sub);
> nh.advertise(left_wheel_pub);
> nh.advertise(right_wheel_pub); //prepare to publish speed in ROS topic
> // Serial.begin(115200);
>
> rightPID.SetMode(AUTOMATIC);
> rightPID.SetSampleTime(1);
> rightPID.SetOutputLimits(-100, 100);
>
> leftPID.SetMode(AUTOMATIC);
> leftPID.SetSampleTime(1);
> leftPID.SetOutputLimits(-100, 100);
>
> int change_left_a;
> int change_left_b;
> int change_right_a;
> int change_right_b;
>
> // Serial.println("Basic Encoder Test:");
> attachInterrupt(digitalPinToInterrupt(left.en_a), change_left_a, CHANGE);
> attachInterrupt(digitalPinToInterrupt(left.en_b), change_left_b, CHANGE);
> attachInterrupt(digitalPinToInterrupt(right.en_a), change_right_a, CHANGE);
> attachInterrupt(digitalPinToInterrupt(right.en_b), change_right_b, CHANGE);
> }
>
> void loop() {
> currentMillis = millis();
> if (currentMillis - prevMillis >= LOOPTIME){
> prevMillis = currentMillis;
>
> demand_speed_left = demandx - (demandz*0.2);
> demand_speed_right = demandx + (demandz*0.2);
>
> /*PID controller for speed control
> Base speed being 1 ms and the demand_speed variables controlling it at fractions of the base.
> The PID controller keeps trying to match the difference
> in encoder counts to match with the required amount, hence controlling the speed. */
> encoder0Diff = encoder0Pos - encoder0Prev; // Get difference between ticks to compute speed
> encoder1Diff = encoder1Pos - encoder1Prev;
>
> int pos_act_left;
> int pos_act_right;
>
>
> pos_act_left = encoder0Pos;
> pos_act_right = encoder1Pos;
>
> encoder0Error = (demand_speed_left*39.65)-encoder0Diff; // 3965 ticks in 1m = 39.65 ticks in 10ms, due to the 10 millis loop
> encoder1Error = (demand_speed_right*39.65)-encoder1Diff;
>
>
> encoder0Prev = encoder0Pos; // Saving values
> encoder1Prev = encoder1Pos;
>
>
> left_setpoint = demand_speed_left*39.65; //Setting required speed as a mul/frac of 1 m/s
> right_setpoint = demand_speed_right*39.65;
>
>
> left_input = encoder0Diff; //Input to PID controller is the current difference
> right_input = encoder1Diff;
>
> leftPID.Compute();
> left.rotate(left_output);
> rightPID.Compute();
> right.rotate(right_output);
> // Serial.print(encoder0Pos);
> // Serial.print(",");
> // Serial.println(encoder1Pos);
>
>
>
> publishPos(LOOPTIME);
>
> if(updatenh>10){
> nh.spinOnce();
> updatenh=0;
> }else{
> updatenh++;
> }
> }
>
> }
>
>
> //Publish function for odometry, uses a vector type message to send the data (message type is not meant for that but that's easier than creating a specific message type)
> void publishPos(double time) {
> left_wheel_msg.data = pos_act_left; //timestamp for odometry data
> right_wheel_msg.data = pos_act_right; //left wheel speed (in m/s)
> left_wheel_pub.publish(&left_wheel_msg); //right wheel speed (in m/s)
> right_wheel_pub.publish(&right_wheel_msg); //looptime, should be the same as specified in LOOPTIME (in s)
>
> }
>
>
> // ************** encoders interrupts **************
>
> // ************** encoder 1 *********************
>
>
> void change_left_a(){
>
> // look for a low-to-high on channel A
> if (digitalRead(left.en_a) == HIGH) {
> // check channel B to see which way encoder is turning
> if (digitalRead(left.en_b) == LOW) {
> encoder0Pos = encoder0Pos + 1; // CW
> }
> else {
> encoder0Pos = encoder0Pos - 1; // CCW
> }
> }
> else // must be a high-to-low edge on channel A
> {
> // check channel B to see which way encoder is turning
> if (digitalRead(left.en_b) == HIGH) {
> encoder0Pos = encoder0Pos + 1; // CW
> }
> else {
> encoder0Pos = encoder0Pos - 1; // CCW
> }
> }
>
> }
>
> void change_left_b(){
>
> // look for a low-to-high on channel B
> if (digitalRead(left.en_b) == HIGH) {
> // check channel A to see which way encoder is turning
> if (digitalRead(left.en_a) == HIGH) {
> encoder0Pos = encoder0Pos + 1; // CW
> }
> else {
> encoder0Pos = encoder0Pos - 1; // CCW
> }
> }
> // Look for a high-to-low on channel B
> else {
> // check channel B to see which way encoder is turning
> if (digitalRead(left.en_a) == LOW) {
> encoder0Pos = encoder0Pos + 1; // CW
> }
> else {
> encoder0Pos = encoder0Pos - 1; // CCW
> }
> }
>
>
> }
>
> // ************** encoder 2 *********************
>
> void change_right_a(){
>
> // look for a low-to-high on channel A
> if (digitalRead(right.en_a) == HIGH) {
> // check channel B to see which way encoder is turning
> if (digitalRead(right.en_b) == LOW) {
> encoder1Pos = encoder1Pos - 1; // CW
> }
> else {
> encoder1Pos = encoder1Pos + 1; // CCW
> }
> }
> else // must be a high-to-low edge on channel A
> {
> // check channel B to see which way encoder is turning
> if (digitalRead(right.en_b) == HIGH) {
> encoder1Pos = encoder1Pos - 1; // CW
> }
> else {
> encoder1Pos = encoder1Pos + 1; // CCW
> }
> }
>
> }
>
> void change_right_b(){
>
> // look for a low-to-high on channel B
> if (digitalRead(right.en_b) == HIGH) {
> // check channel A to see which way encoder is turning
> if (digitalRead(right.en_a) == HIGH) {
> encoder1Pos = encoder1Pos - 1; // CW
> }
> else {
> encoder1Pos = encoder1Pos + 1; // CCW
> }
> }
> // Look for a high-to-low on channel B
> else {
> // check channel B to see which way encoder is turning
> if (digitalRead(right.en_a) == LOW) {
> encoder1Pos = encoder1Pos - 1; // CW
> }
> else {
> encoder1Pos = encoder1Pos + 1; // CCW
> }
> }
>
>
> }
motor.cpp
#include "Arduino.h"
#include "Motor.h"
Motor::Motor(int plus, int minus, int en_a, int en_b) {
pinMode(plus,OUTPUT);
pinMode(minus,OUTPUT);
pinMode(en_a,INPUT_PULLUP);
pinMode(en_b,INPUT_PULLUP);
Motor::plus = plus;
Motor::minus = minus;
Motor::en_a = en_a;
Motor::en_b = en_b;
}
void Motor::rotate(int value) {
if(value>=0){
//Max Voltage with 16V battery with 12V required
//(12/16)*255 ~=190
// Serial.println("called");
// Serial.println(plus);
int out = map(value, 0, 100, 0, 190);
analogWrite(plus,out);
analogWrite(minus,0);
}else{
//Max Voltage with 16V battery with 12V required
//(12/16)*255 ~=190
int out = map(value, 0, -100, 0, 190);
analogWrite(plus,0);
analogWrite(minus,out);
}
}
motor.h
/*
Motor.h - Library for working with the Cytron SPG30E-30K.
Created by Vinay Lanka, January 27, 2021.
*/
#ifndef Motor_h
#define Motor_h
#include "Arduino.h"
class Motor {
public:
//Constructor - Plus and Minus are the Motor output / en_a and en_b are the encoder inputs
Motor(int plus, int minus, int en_a, int en_b);
//Spin the motor with a percentage value
void rotate(int value);
//Motor Outputs - plus is one direction and minus is the other
int plus;
int minus;
//Encoder Inputs
int en_a;
int en_b;
};
#endif
Arduino:1.8.15 (Linux), Kart:"Arduino Uno"
navbot_test:67:8: error: conflicting declaration 'double pos_act_left'
double pos_act_left = 0;
^~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:17:5: note: previous declaration as 'int pos_act_left'
int pos_act_left;
^~~~~~~~~~~~
navbot_test:68:8: error: conflicting declaration 'double pos_act_right'
double pos_act_right = 0;
^~~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:18:5: note: previous declaration as 'int pos_act_right'
int pos_act_right;
^~~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino: In function 'void setup()':
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:91:74: warning: invalid conversion from 'int' to 'void (*)()' [-fpermissive]
attachInterrupt(digitalPinToInterrupt(left.en_a), change_left_a, CHANGE);
^
In file included from sketch/navbot_test.ino.cpp:1:0:
/snap/arduino/61/hardware/arduino/avr/cores/arduino/Arduino.h:151:6: note: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)'
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
^~~~~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:92:74: warning: invalid conversion from 'int' to 'void (*)()' [-fpermissive]
attachInterrupt(digitalPinToInterrupt(left.en_b), change_left_b, CHANGE);
^
In file included from sketch/navbot_test.ino.cpp:1:0:
/snap/arduino/61/hardware/arduino/avr/cores/arduino/Arduino.h:151:6: note: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)'
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
^~~~~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:93:76: warning: invalid conversion from 'int' to 'void (*)()' [-fpermissive]
attachInterrupt(digitalPinToInterrupt(right.en_a), change_right_a, CHANGE);
^
In file included from sketch/navbot_test.ino.cpp:1:0:
/snap/arduino/61/hardware/arduino/avr/cores/arduino/Arduino.h:151:6: note: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)'
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
^~~~~~~~~~~~~~~
/home/ahmet/Masaüstü/navbot_test/navbot_test.ino:94:76: warning: invalid conversion from 'int' to 'void (*)()' [-fpermissive]
attachInterrupt(digitalPinToInterrupt(right.en_b), change_right_b, CHANGE);
^
In file included from sketch/navbot_test.ino.cpp:1:0:
/snap/arduino/61/hardware/arduino/avr/cores/arduino/Arduino.h:151:6: note: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)'
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
^~~~~~~~~~~~~~~
exit status 1
conflicting declaration 'double pos_act_left'
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.