Robot unable to localize itself
I have a robot that uses an RPLIDAR for scanning and an arduino that controls BLDC motor via pwm. I have been able to create a map using GMAPPING, publish odom messages and subscribe my arduino to cmd_vel topic. My arduino calculates the pwm according to the velocity and rotates the wheel. What I am still unable to do is that my robots location doesnot change when I move it around or give it a 2d nav goal. The wheels just keep rotating and robot doesnot stop at the goal.
I URGENTLY NEED HELP I have no idea, what am I doing wrong?
Also, I launched by noxbringup file and view tf on rviz and the gave i a velocity via TELEOPKEYBOARD. I saw on rviz that my robot doesnot move straight even when i donot turn it.
these are my launch and yaml files and arduino code P.S. my code is a version of NOX ROBOT available on ROS website http://wiki.ros.org/Robots/Nox nox_navigation.launch:
<param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
<!-- param name="controller_frequency" value="5.0" /> -->
<param name="controller_patience" value="15.0" />
<param name="clearing_rotation_allowed" value="false" /> <!-- Nox is able to rotate in place -->
<!-- <param name= "allow_none" value="True" /> -->
</node>
nox_bringup.launch:
commoncostmapparams.yaml:
footprint: [ [-0.27,-0.19], [0.13,-0.19], [0.13,0.19], [-0.27,0.19] ]
transformtolerance: 0.4 maptype: costmap
obstaclelayer: enabled: true obstaclerange: 5.0 raytracerange: 5.5 inflationradius: 0.1 trackunknownspace: false combination_method: 1
observationsources: laserscansensor laserscansensor: {datatype: LaserScan, topic: scan, marking: true, clearing: true}
inflationlayer:
enabled: true
costscalingfactor: 10.0
inflationradius: 0.1
staticlayer: enabled: true maptopic: "map"
globalcostmapparams.yaml:
globalcostmap: globalframe: map robotbaseframe: baselink updatefrequency: 1.0 publishfrequency: 0.5 staticmap: true
transformtolerance: 0.5 plugins: - {name: staticlayer, type: "costmap2d::StaticLayer"} - {name: obstaclelayer, type: "costmap2d::VoxelLayer"} - {name: inflationlayer, type: "costmap_2d::InflationLayer"}
localcostmapparams: localcostmap: globalframe: map robotbaseframe: baselink updatefrequency: 2.0 publishfrequency: 1.0 staticmap: false rollingwindow: true width: 10 height: 10 resolution: 0.1 transformtolerance: 0.3
plugins: - {name: staticlayer, type: "costmap2d::StaticLayer"} - {name: obstaclelayer, type: "costmap2d::ObstacleLayer"}
baselocalplanner_params.yaml:
TrajectoryPlannerROS: # for details see: http://www.ros.org/wiki/base_local_planner odom_topic: odom
maxvelx: 0.2229
minvelx: 0.2026
maxrotationalvel: 0.12 # 0.1 rad/sec = 5.7 degree/sec
mininplacerotationalvel: 0.04
acclimth: 0.12
acclimx: 0.05
acclimy: 0
holonomic_robot: false
# goal tolerance parameters
yawgoaltolerance: 0.4 # 0.1 means 5.7 degrees
xygoaltolerance: 0.1
latchxygoal_tolerance: false
# Forward Simulation Parameters
sim_time: 1
sim_granularity: 0.025
angularsimgranularity: 0.01
vx_samples: 10
vtheta_samples: 20
controller_frequency: 10
# Trajectory Scoring Parameters meter_scoring: true
pathdistancebias: 1.0
goaldistancebias: 0.8
occdist_scale: 0.01
heading_lookahead: 0.325
oscillationresetdist: 0.05
publishcostgrid: true
dwa: true
dwalocalplanner_params.yaml:
DWAPlannerROS:
odom_topic: odom
Robot Configuration Parameters
maxvelx: 0.2229
minvelx: 0.2026
maxvely: 0.0 # 0 for non-holonomic robot
minvely: 0.0 # 0 for non-holonomic robot
The velocity when robot is moving in a straight line
maxtransvel: 0.2229
mintransvel: 0.2026
maxrotvel: 0.03
minrotvel: 0.02
acclimx: 0.09
acclimy: 0.0
acclimtheta: 3.2
Goal Tolerance Parametes
xygoaltolerance: 0.1
yawgoaltolerance: 0.07
latchxygoal_tolerance: false
Forward Simulation Parameters
sim_time: 2.0
sim_granularity: 0.4
vx_samples: 20
vy_samples: 0
vtheta_samples: 40
controller_frequency: 10.0
Trajectory Scoring Parameters
pathdistancebias: 34.0
goaldistancebias: 20.0
occdist_scale: 0.02
forwardpointdistance: 0.325
stoptimebuffer: 0.2
scaling_speed: 0.25
maxscalingfactor: 0.2
Oscillation Prevention Parameters
oscillationresetdist: 0.05
Debugging
publishtrajpc : true
publishcostgrid_pc: true
teb local planner parameters:
TebLocalPlannerROS:
odomtopic: odom publishfeedback: True
# Trajectory
tebautosize: True dtref: 0.4
dt_hysteresis: 0.04
globalplanoverwrite_orientation: True
allowinitwithbackwardsmotion: True
maxglobalplanlookaheaddist: 6.0
feasibilitycheckno_poses: 2
# Robot
maxvelx: 0.04
maxvelx_backwards: 0.0
maxvely: 0.0
maxveltheta: 0.1
acclimx: 0.015
acclimtheta: 0.12
# ********************** Carlike robot parameters ******************** minturningradius: 0.734
wheelbase: 0.32
cmdangleinstead_rotvel: False
# ********************************************************************
footprintmodel: # types: "point", "circular", "twocircles", "line", "polygon"
type: "circular"
radius: 0.17 # for type "circular"
line_start: [-0.19, 0.0] # for type "line"
line_end: [0.14, 0.0] # for type "line"
frontoffset: 0.2 # for type "twocircles"
frontradius: 0.2 # for type "twocircles"
rearoffset: 0.2 # for type "twocircles"
rearradius: 0.2 # for type "twocircles"
vertices: [ [0.25, -0.05], [0.18, -0.05], [0.18, -0.18], [-0.19, -0.18], [-0.25, 0], [-0.19, 0.18], [0.18, 0.18], [0.18, 0.05], [0.25, 0.05] ]
# GoalTolerance
xygoaltolerance: 0.05
yawgoaltolerance: 0.05
freegoalvel: False
# Obstacles
minobstacledist: 0.1
includecostmapobstacles: True
costmapobstaclesbehindrobotdist: 1.0
obstacleposesaffected: 30
costmapconverterplugin: ""
costmapconverterspin_thread: True
costmapconverterrate: 5
# Optimization
noinneriterations: 5
noouteriterations: 4
optimization_activate: True
optimization_verbose: False
penalty_epsilon: 0.1
weightmaxvel_x: 2
weightmaxvel_theta: 2
weightacclim_x: 1
weightacclim_theta: 1
weightkinematicsnh: 1000
weightkinematicsforward_drive: 1
weightkinematicsturning_radius: 1
weight_optimaltime: 1
weight_obstacle: 50
weightdynamicobstacle: 10 # not in use yet
# Homotopy Class Planner
enablehomotopyclass_planning: True
enable_multithreading: True
simple_exploration: False
maxnumberclasses: 4
selectioncosthysteresis: 1.0
selectionobstcost_scale: 1.0
selectionalternativetime_cost: False
roadmapgraphno_samples: 15
roadmapgrapharea_width: 5
hsignatureprescaler: 0.5
hsignaturethreshold: 0.1
obstaclekeypointoffset: 0.1
obstacleheadingthreshold: 0.45
visualizehcgraph: False
ARDUINO CODE:
include
//initializing all the variables
define LOOPTIME 100 Looptime in millisecond
const byte noCommLoopMax = 10;
unsigned int noCommLoops = 0; main loop without communication counter
double speedcmdleft2 = 0;
const int PINENCODAMOTORLEFT = 20; //A channel for encoder of left motor const int PINENCODBMOTORLEFT = 19; //B channel for encoder of left motor
const int PINENCODAMOTORRIGHT = 2; //A channel for encoder of right motor const int PINENCODBMOTORRIGHT = 3; //B channel for encoder of right motor
const int PINSIDELIGHT_LED = 46; //Side light blinking led pin
unsigned long lastMilli = 0;
//--- Robot-specific constants --- const double radius = 0.085; //Wheel radius, in m const double wheelbase = 0.35; //Wheelbase, in m const double encodercpr = 91; //Encoder ticks or counts per rotation const double speedtopwmratio = 0.00235;
const double minspeedcmd = 0.0882; //(minspeedcmd/speedtopwm_ratio)
double speedreq = 0; //Desired linear speed for the robot, in m/s double angularspeed_req = 0; //Desired angular speed for the robot, in rad/s
double speedreqleft = 0; //Desired speed for left wheel in m/s double speedactleft = 0; //Actual speed for left wheel in m/s double speedcmdleft = 0; //Command speed for left wheel in m/s
double speedreqright = 0; //Desired speed for right wheel in m/s double speedactright = 0; //Actual speed for right wheel in m/s double speedcmdright = 0; //Command speed for right wheel in m/s
const double max_speed = 0.1; //Max speed in m/s
int PWMleftMotor = 0; //PWM command for left motor int PWMrightMotor = 0; //PWM command for right motor
// PID Parameters const double PIDleftparam[] = { 0.011, 0, 0 }; //Respectively Kp, Ki and Kd for left motor PID const double PIDrightparam[] = { 0.03, 0, 0 }; //Respectively Kp, Ki and Kd for right motor PID
volatile float posleft = 0; //Left motor encoder position volatile float posright = 0; //Right motor encoder position
PID PIDleftMotor(&speedactleft, &speedcmdleft, &speedreqleft, PIDleftparam[0], PIDleft_param[1],
PIDleftparam[2], DIRECT); //Setting up the PID for left motor
PID PIDrightMotor(&speedactright, &speedcmdright, &speedreqright, PIDrightparam[0], PIDrightparam[1], PIDright_param[2], DIRECT); //Setting up the PID for right motor
ros::NodeHandle nh;
//function that will be called when receiving command from host
void handlecmd (const geometrymsgs::Twist& cmd_vel) { noCommLoops = 0; //Reset the counter for number of main loops without communication
speedreq = cmdvel.linear.x; //Extract the commanded linear speed from the message
angularspeedreq = cmd_vel.angular.z; //Extract the commanded angular speed from the message
speedreqleft = speedreq - angularspeedreq * (wheelbase / 2); //Calculate the required speed for the left motor to comply with commanded linear and angular speeds speedreqright = speedreq + angularspeedreq * (wheelbase / 2); //Calculate the required speed for the right motor to comply with commanded linear and angular speeds }
ros::Subscriber
geometrymsgs::Vector3Stamped speedmsg; //create a "speed_msg" ROS message
ros::Publisher speedpub("speed", &speedmsg); //create a publisher to ROS topic "speed" using the "speed_msg" type
void setup() {
nh.initNode();
nh.subscribe(cmd_vel);
nh.advertise(speed_pub);
//setting motor speeds to zero analogWrite(9, 0);
analogWrite(11, 0);
//setting PID parameters PID_leftMotor.SetSampleTime(95);
PID_rightMotor.SetSampleTime(95);
PIDleftMotor.SetOutputLimits(0.2, maxspeed);
PIDrightMotor.SetOutputLimits(0.2, maxspeed);
PID_leftMotor.SetMode(AUTOMATIC);
PID_rightMotor.SetMode(AUTOMATIC);
// Define the rotary encoder for left motor pinMode(PINENCODAMOTORLEFT, INPUT);
pinMode(PINENCODBMOTORLEFT, INPUT);
digitalWrite(PINENCODAMOTORLEFT, HIGH); // turn on pullup resistor
digitalWrite(PINENCODBMOTORLEFT, HIGH);
attachInterrupt(digitalPinToInterrupt(21), encoderLeftMotor, CHANGE);
// Define the rotary encoder for right motor pinMode(PINENCODAMOTORRIGHT, INPUT);
pinMode(PINENCODBMOTORRIGHT, INPUT);
digitalWrite(PINENCODAMOTORRIGHT, HIGH); // turn on pullup resistor
digitalWrite(PINENCODBMOTORRIGHT, HIGH);
attachInterrupt(digitalPinToInterrupt(18), encoderRightMotor, CHANGE);
}
//_________________________________________________________________________
void loop() { nh.spinOnce(); if ((millis() - lastMilli) >= LOOPTIME) { // enter timed loop lastMilli = millis();
if (abs(pos_left) < 5) { //Avoid taking in account small disturbances
speed_act_left = 0;
}
else {
speed_act_left = ((pos_left / encoder_cpr) * 2 * PI) * (1000 / LOOPTIME) * radius; // calculate speed of left wheel
}
if (abs(pos_right) < 5) { //Avoid taking in account small disturbances
speed_act_right = 0;
}
else {
speed_act_right = ((pos_right / encoder_cpr) * 2 * PI) * (1000 / LOOPTIME) * radius; // calculate speed of right wheel
}
pos_left = 0;
pos_right = 0;
speed_cmd_left = constrain(speed_cmd_left, 0, max_speed);
PID_leftMotor.Compute(); // compute PWM value for left motor
PWM_leftMotor = constrain(((speed_req_left + sgn(speed_req_left) * min_speed_cmd) / speed_to_pwm_ratio) + (speed_cmd_left / speed_to_pwm_ratio), -255, 255); //
if (noCommLoops >= noCommLoopMax) { //Stopping if too much time without command
analogWrite(9, 0);
}
else if (speed_req_left == 0) { //Stopping
analogWrite(9, 0);
}
else if (PWM_leftMotor > 0) { //Going forward
analogWrite(9, abs(PWM_leftMotor));
}
speed_cmd_right = constrain(speed_cmd_right, 0, max_speed);
PID_rightMotor.Compute(); // compute PWM value for right motor.
PWM_rightMotor = constrain(((speed_req_right + sgn(speed_req_right) * min_speed_cmd) / speed_to_pwm_ratio) + (speed_cmd_right / speed_to_pwm_ratio), 110, 255);
if (noCommLoops >= noCommLoopMax) { //Stopping if too much time without command
analogWrite(11, 0);
}
else if (speed_req_right == 0) { //Stopping
analogWrite(11, 0);
}
else if (PWM_rightMotor > 0) { //Going forward
analogWrite(11, abs(PWM_rightMotor));
}
if ((millis() - lastMilli) >= LOOPTIME) { //write an error if execution time of the loop in longer than the specified looptime
// Serial.println(" TOO LONG ");
}
noCommLoops++;
if (noCommLoops == 65535) {
noCommLoops = noCommLoopMax;
}
publishSpeed(LOOPTIME); //Publish odometry on ROS topic
} }
void publishSpeed(double time) {
speed_msg.header.stamp = nh.now(); //timestamp for odometry data
speedmsg.vector.x = speedact_left; //left wheel speed (in m/s)
speedmsg.vector.y = speedact_right; //right wheel speed (in m/s)
speed_msg.vector.z = time / 100; //looptime, should be the same as specified in LOOPTIME (in s)
speedpub.publish(&speedmsg);
nh.spinOnce();
nh.loginfo("Publishing odometry");
}
//Left motor encoder counter void encoderLeftMotor() {
if (digitalRead(PINENCODAMOTORLEFT) == digitalRead(PINENCODBMOTORLEFT)) pos_left++;
else pos_left--;
}
//Right motor encoder counter void encoderRightMotor() {
if (digitalRead(PINENCODAMOTORRIGHT) == digitalRead(PINENCODBMOTORRIGHT)) pos_right--;
else pos_right++;
}
}
Asked by Haadi on 2020-10-06 08:44:52 UTC
Comments
Hi. It is probably because you have a static transform between the map and odom, so it doesn't change:
<node pkg="tf" type="static_transform_publisher" name="map_to_odom" args="0.0 0.0 0.0 0 0 0.0 /map /odom 0"/>
. Try to comment it. Also, can you runrqt_graph
when the system is running and post a screenshot of the graph. Set group to 1, and uncheck Dead sinks and Leaf topics.Asked by tropic on 2020-10-13 14:32:07 UTC