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 :
- Publishing left and right encoder ticks from Arduino so that the Rpi subscribe and use them to publish odom message on RPi (Python)
- 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