This repository has been archived by the owner on Jan 6, 2022. It is now read-only.
/
random_walk.cpp
110 lines (77 loc) · 3.16 KB
/
random_walk.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <ros/ros.h>
// Publish to a topic with this message type
#include <ackermann_msgs/AckermannDriveStamped.h>
// AckermannDriveStamped messages include this message type
#include <ackermann_msgs/AckermannDrive.h>
// Subscribe to a topic with this message type
#include <nav_msgs/Odometry.h>
// for printing
#include <iostream>
// for RAND_MAX
#include <cstdlib>
class RandomWalker {
private:
// A ROS node
ros::NodeHandle n;
// car parameters
double max_speed, max_steering_angle;
// Listen for odom messages
ros::Subscriber odom_sub;
// Publish drive data
ros::Publisher drive_pub;
// previous desired steering angle
double prev_angle=0.0;
public:
RandomWalker() {
// Initialize the node handle
n = ros::NodeHandle("~");
// get topic names
std::string drive_topic, odom_topic;
n.getParam("rand_drive_topic", drive_topic);
n.getParam("odom_topic", odom_topic);
// get car parameters
n.getParam("max_speed", max_speed);
n.getParam("max_steering_angle", max_steering_angle);
// Make a publisher for drive messages
drive_pub = n.advertise<ackermann_msgs::AckermannDriveStamped>(drive_topic, 10);
// Start a subscriber to listen to odom messages
odom_sub = n.subscribe(odom_topic, 1, &RandomWalker::odom_callback, this);
}
void odom_callback(const nav_msgs::Odometry & msg) {
// publishing is done in odom callback just so it's at the same rate as the sim
// initialize message to be published
ackermann_msgs::AckermannDriveStamped drive_st_msg;
ackermann_msgs::AckermannDrive drive_msg;
/// SPEED CALCULATION:
// set constant speed to be half of max speed
drive_msg.speed = max_speed / 2.0;
/// STEERING ANGLE CALCULATION
// random number between 0 and 1
double random = ((double) rand() / RAND_MAX);
// good range to cause lots of turning
double range = max_steering_angle / 2.0;
// compute random amount to change desired angle by (between -range and range)
double rand_ang = range * random - range / 2.0;
// sometimes change sign so it turns more (basically add bias to continue turning in current direction)
random = ((double) rand() / RAND_MAX);
if ((random > .8) && (prev_angle != 0)) {
double sign_rand = rand_ang / std::abs(rand_ang);
double sign_prev = prev_angle / std::abs(prev_angle);
rand_ang *= sign_rand * sign_prev;
}
// set angle (add random change to previous angle)
drive_msg.steering_angle = std::min(std::max(prev_angle + rand_ang, -max_steering_angle), max_steering_angle);
// reset previous desired angle
prev_angle = drive_msg.steering_angle;
// set drive message in drive stamped message
drive_st_msg.drive = drive_msg;
// publish AckermannDriveStamped message to drive topic
drive_pub.publish(drive_st_msg);
}
}; // end of class definition
int main(int argc, char ** argv) {
ros::init(argc, argv, "random_walker");
RandomWalker rw;
ros::spin();
return 0;
}