Robotics StackExchange | Archived questions

How to publish odom on Arduino

Hello,

I have a robot which uses a Me Auriga, equivalent to an Arduino Mega2650 board, and 180 optical encoder motors. On the Me Auriga board, I have uploaded the following Arduino firmware CreativeBottypeA_firmware . I am using rosserial_python on my Raspberry Pi 3+

RPi Terminal

 rosrun rosserialpython serialnode.py 

I am trying to publish odometry information using encoder ticks on Arduino. If I'm right, We can do this by two ways :

  1. Publishing left and right encoder ticks from Arduino so that the Rpi subscribe and use them to publish odom message on RPi (Python)
  2. Publishing odom message from Arduino using the encoder ticks (I would like to do this). Could you please help me?

1. Arduino A few lines of the robot's firmware :

#include 

include

include

include

include "MeAuriga.h"

MeOnBoardTemp OnBoardTemp(PORT13); MeEncoderOnBoard Encoder1(SLOT1); MeEncoderOnBoard Encoder_2(SLOT2);

ros::NodeHandle nh;

stdmsgs::Int16 leftticksmsg; stdmsgs::Int16 rightticksmsg;

ros::Publisher publeftticks("/leftticks",&leftticksmsg); ros::Publisher pubrightticks("/rightticks",&rightticksmsg);

long ticks_time;

void lwheelvtarget(const stdmsgs::Float32& vel){ if(motorOn){ Encoder2.runSpeed(vel.data); } else { Encoder2.runSpeed(0); } }

void rwheelvtarget(const stdmsgs::Float32& vel){ if(motorOn){ Encoder1.runSpeed(-vel.data); } else { Encoder1.runSpeed(0); } }

void isrprocessencoder1(void){ if(digitalRead(Encoder1.getPortB()) == 0){ Encoder1.pulsePosMinus(); } else { Encoder_1.pulsePosPlus();; } }

void isrprocessencoder2(void) { if(digitalRead(Encoder2.getPortB()) == 0) { Encoder2.pulsePosMinus(); } else { Encoder2.pulsePosPlus(); } } ros::Subscriber<stdmsgs::Float32> subleft("lwheelvtarget", &lwheelvtarget); ros::Subscriber<stdmsgs::Float32> subright("rwheelvtarget", &rwheel_vtarget);

void setup() { /* Encoder motor drives */ attachInterrupt(Encoder1.getIntNum(), isrprocessencoder1, RISING); attachInterrupt(Encoder2.getIntNum(), isrprocessencoder2, RISING);

//Set PWM 8KHz TCCR1A = _BV(WGM10); TCCR1B = _BV(CS11) | _BV(WGM12);

TCCR2A = _BV(WGM21) | _BV(WGM20); TCCR2B = _BV(CS21);

Encoder1.setPulse(9); Encoder2.setPulse(9); Encoder1.setRatio(39.267); Encoder2.setRatio(39.267); Encoder1.setPosPid(0.18,0,0); Encoder2.setPosPid(0.18,0,0); Encoder1.setSpeedPid(0.18,0,0); Encoder2.setSpeedPid(0.18,0,0); Encoder1.runSpeed(0); Encoder2.runSpeed(0); Encoder1.setMotionMode(PIDMODE); Encoder2.setMotionMode(PIDMODE);

nh.getHardware()->setBaud(115200); nh.initNode(); nh.advertise(publeftticks); nh.advertise(pubrightticks); nh.subscribe(subleft); nh.subscribe(subright); }

void loop() {
// publish wheel pos in ticks for each wheel if(millis() >= tickstime){ leftticksmsg.data = Encoder2.getPulsePos(); publeftticks.publish(&leftticksmsg); rightticksmsg.data = Encoder1.getPulsePos(); pubrightticks.publish(&rightticksmsg); tickstime = millis()+10; } if(!motorOn){ Encoder1.runSpeed(0); Encoder2.runSpeed(0); } Encoder1.loop(); Encoder2.loop(); nh.spinOnce(); delay(100); } }

Thank you, :)

Shanika

Asked by Shanika on 2019-06-19 09:36:20 UTC

Comments

The nav_msgs/Odometry message type is about 1000 bytes, which is too big to easily fit in RAM in most Arduinos. I recommend keep your current approach.

Asked by ahendrix on 2019-06-19 11:02:13 UTC

Thank you ahendrix, I will try to publish odometry information on my Raspberry Pi. Just to confirm, how do I compute odometry from encoder ticks ? Some people use ICC and others don't use it.

Asked by Shanika on 2019-06-20 09:46:26 UTC

Is it a differential drive robot? We use the http://wiki.ros.org/diff_drive_controller from ros_control on our custom robot. It reads in encoder ticks and publishes odom and tf.

Asked by Wilco Bonestroo on 2019-11-27 16:46:37 UTC

Answers