Skip to content

Commit 436e557

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 1667009 + 8ad3b6b commit 436e557

File tree

8 files changed

+82
-57
lines changed

8 files changed

+82
-57
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#Xenobot
22

3-
A lightweight replica of MIT duckietown project.
3+
Inspired by MIT, this is a lightweight replica of MIT duckietown project.
4+
5+
Our goal is to build a low cost self-driving car based on realtime Linux (patched by Xenomai)
6+
7+
#Demo videos
8+
9+
[![lane_following](https://github.com/ncku-ros2-research/xenobot/blob/master/materials/demo_video1.jpeg?raw=true)](https://www.youtube.com/watch?v=84MXc0_F61o)
10+
11+
[![rviz](https://github.com/ncku-ros2-research/xenobot/blob/master/materials/demo_video2.jpeg?raw=true)](https://www.youtube.com/watch?v=XK602hzbORY&feature=youtu.be)
412

513
##Installation
614

@@ -62,6 +70,18 @@ roslaunch xenobot activate_controller.launch veh:=machine_name calibrate:=true
6270
roslaunch xenobot activate_controller.launch veh:=machine_name
6371
```
6472

73+
###4. Setup .bashrc
74+
75+
Add:
76+
77+
```
78+
. /opt/ros/kinetic/setup.bash
79+
. ~/catkin_ws/devel/setup.bash
80+
export ROS_IP=`hostname -I`
81+
alias play="roslaunch xenobot activate_controller.launch veh:=colin calibrate:=1"
82+
alias stop=". ~/catkin_ws/src/xenobot/halt_motor.sh"
83+
```
84+
6585
##Analysing
6686

6787
###Scatter plot

config/colin/pid.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pid_d:
2-
kp: 3.5
2+
kp: 3
33
ki: 0
44
kd: 0
55

materials/demo_video1.jpeg

28.8 KB
Loading

materials/demo_video2.jpeg

31.7 KB
Loading

system/controller.cpp

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ void bound(float min, float max, float& x)
6767
}
6868
}
6969

70-
static float pid_d_control(int d_current, float d_setpoint, pid_control_t& pid)
70+
static float pid_control(int current_value, float setpoint, pid_control_t& pid)
7171
{
72-
float p_term, d_term;
73-
float current_error = d_current - d_setpoint;
72+
float p_term, d_term, i_term;
73+
float current_error = current_value - setpoint;
7474

7575
ros::Time current_time = ros::Time::now();
7676

@@ -80,52 +80,25 @@ static float pid_d_control(int d_current, float d_setpoint, pid_control_t& pid)
8080
if(pid.been_init == false) {
8181
pid.been_init = true;
8282
d_term = 0; //No D term
83+
i_term = 0; //No I term
8384
} else if(pid.been_halted == true) {
8485
pid.been_halted = false;
8586
d_term = 0; //No D term
87+
i_term = 0; //No I term
8688
} else {
8789
//Calculate the time interval
8890
float delta_t = current_time.toSec() - pid.previous_time.toSec();
8991

90-
//Calculate the D term
92+
//Calculate I and D terms
9193
d_term = pid.kd * (current_error - pid.previous_error) / delta_t;
94+
i_term = pid.ki * current_error * delta_t;
9295
}
9396

9497
pid.previous_error = current_error;
9598
pid.previous_time = current_time;
99+
pid.previous_i_term = i_term;
96100

97-
return p_term + d_term;
98-
}
99-
100-
static float pid_phi_control(float phi_current, float phi_setpoint, pid_control_t& pid)
101-
{
102-
float p_term, d_term;
103-
float current_error = phi_current - phi_setpoint;
104-
105-
ros::Time current_time = ros::Time::now();
106-
107-
//Calculate the P term
108-
p_term = pid.kp * current_error;
109-
110-
if(pid.been_init == false) {
111-
pid.been_init = true;
112-
d_term = 0; //No D term
113-
} else if(pid.been_halted == true) {
114-
pid.been_halted = false;
115-
d_term = 0; //No D term
116-
} else {
117-
//Calculate the time interval
118-
float delta_t = current_time.toSec() - pid.previous_time.toSec();
119-
120-
//Calculate the D term
121-
d_term = pid.kd * (current_error - pid.previous_error) / delta_t;
122-
}
123-
124-
pid.previous_error = current_error;
125-
pid.previous_time = current_time;
126-
127-
return p_term + d_term;
128-
101+
return p_term + d_term + i_term;
129102
}
130103

131104
void pid_halt()
@@ -138,11 +111,11 @@ void self_driving_controller(float d, float phi)
138111
{
139112
int pwm_left, pwm_right;
140113

141-
float phi_setpoint = pid_d_control(d, 0, pid_d);
114+
float phi_setpoint = pid_control(d, 0, pid_d);
142115

143116
bound(PHI_MIN, PHI_MAX, phi_setpoint);
144117

145-
int pwm = (int)pid_phi_control(phi, phi_setpoint, pid_phi);
118+
int pwm = (int)pid_control(phi, phi_setpoint, pid_phi);
146119

147120
pwm_left = THROTTLE_BASE + pwm;
148121
pwm_right = THROTTLE_BASE - pwm;

system/controller.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef struct {
2222
bool been_init;
2323

2424
float previous_error;
25+
float previous_i_term;
2526

2627
ros::Time previous_time; //XXX:This is not realtime!
2728
} pid_control_t;

system/lane_detector.cpp

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cv_bridge/cv_bridge.h>
77
#include <yaml-cpp/yaml.h>
88

9+
#include <std_msgs/Float32.h>
910
#include <xenobot/segment.h>
1011
#include <xenobot/segmentArray.h>
1112

@@ -17,6 +18,7 @@
1718
#define DRAW_DEBUG_INFO 1
1819

1920
#define rad_to_deg(phi) (phi * 57.2957795)
21+
#define PI 3.141592
2022

2123
using namespace std;
2224
using namespace cv;
@@ -57,7 +59,13 @@ LaneDetector::LaneDetector(string _yaml_path, bool calibrate_mode) :
5759
node.advertise<sensor_msgs::Image>("xenobot/bird_view_image", 10);
5860

5961
histogram_publisher =
60-
node.advertise<xenobot::segmentArray>("/xenobot/segment_data", 10);;
62+
node.advertise<xenobot::segmentArray>("/xenobot/segment_data", 10);
63+
64+
pose_d_publisher =
65+
node.advertise<std_msgs::Float32>("/xenobot/pose/d", 10);
66+
67+
pose_phi_publisher =
68+
node.advertise<std_msgs::Float32>("/xenobot/pose/phi", 10);
6169
}
6270
}
6371

@@ -482,6 +490,12 @@ void LaneDetector::send_sucess_visualize_image_thread(
482490

483491
histogram_publisher.publish(segments_msg);
484492

493+
std_msgs::Float32 pose_msg;
494+
pose_msg.data = d;
495+
pose_d_publisher.publish(pose_msg);
496+
pose_msg.data = phi;
497+
pose_phi_publisher.publish(pose_msg);
498+
485499
ROS_INFO("phi:%f | d:%f", phi, d);
486500
}
487501

@@ -509,8 +523,6 @@ void LaneDetector::send_failed_visualize_image_thread(
509523
outer_threshold_image, inner_threshold_image,
510524
bird_view_image
511525
);
512-
513-
ROS_INFO("Failed to estimate the lane");
514526
}
515527

516528

@@ -616,7 +628,7 @@ bool LaneDetector::lane_estimate(cv::Mat& raw_image, float& final_d, float& fina
616628
inner_threshold_image
617629
);
618630

619-
ROS_INFO("[No segment found]");
631+
ROS_INFO("Failed to estimate the lane [No segment found]");
620632

621633
return false;
622634
}
@@ -728,7 +740,7 @@ bool LaneDetector::lane_estimate(cv::Mat& raw_image, float& final_d, float& fina
728740
inner_threshold_image
729741
);
730742

731-
ROS_INFO("[Less than threshold value]");
743+
ROS_INFO("Failed to estimate the lane [Less than threshold value]");
732744

733745
return false;
734746
}
@@ -789,7 +801,7 @@ bool LaneDetector::lane_estimate(cv::Mat& raw_image, float& final_d, float& fina
789801
inner_threshold_image
790802
);
791803

792-
ROS_INFO("Sample count equals zero");
804+
ROS_INFO("Failed to estimate the lane [Sample count equals zero]");
793805

794806
return false;
795807
}
@@ -856,31 +868,45 @@ bool LaneDetector::generate_vote(segment_t& lane_segment, float& d,
856868
normalize(t_hat);
857869

858870
/* Estimate phi */
859-
phi = rad_to_deg(atan2f(t_hat.y, t_hat.x)) + 90.0f;
871+
phi = atan2f(t_hat.y, t_hat.x) + PI / 2;
860872

861873
Point2f n_hat(-t_hat.y, t_hat.x); //normal vector
862874

863-
float d1 = inner_product(n_hat, p1);
864-
float d2 = inner_product(n_hat, p2);
875+
Point2f offset_vector = n_hat;
865876

866-
d = (d1 + d2) / 2; //lateral displacement
877+
float steady_bias = 4; //cm
867878

868879
if(color == WHITE) {
869-
d -= W / 2;
870-
871880
if(lane_segment.side == RIGHT_EDGE) {
872-
d -= L_W;
881+
offset_vector *= -(W / 2) - L_W;
882+
} else {
883+
offset_vector *= -(W / 2);
873884
}
874885
} else if(color == YELLOW) {
875-
d += W / 2;
876-
877886
if(lane_segment.side == LEFT_EDGE) {
878-
d += L_Y;
887+
offset_vector *= +(W / 2) + L_Y + steady_bias;
888+
} else {
889+
offset_vector *= +(W / 2) + steady_bias;
879890
}
880891
}
881892

893+
p1 += offset_vector;
894+
p2 += offset_vector;
895+
896+
p1.x -= CAMERA_TO_CENTER * sin(phi);
897+
p1.y -= CAMERA_TO_CENTER * cos(phi);
898+
p2.x -= CAMERA_TO_CENTER * sin(phi);
899+
p2.y -= CAMERA_TO_CENTER * cos(phi);
900+
901+
float d1 = inner_product(n_hat, p1);
902+
float d2 = inner_product(n_hat, p2);
903+
904+
d = (d1 + d2) / 2; //lateral displacement
905+
882906
//TODO:referive the geometry formulas!
883907
d *= -1;
884908

909+
phi = rad_to_deg(phi);
910+
885911
return true;
886912
}

system/lane_detector.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ using namespace std;
2727
#define L_Y 2.5
2828
#define W 16.5
2929

30+
/* Car parameter */
31+
#define CAMERA_TO_CENTER 10.0 //cm
32+
3033
/* Historgram filter parameters */
3134
#define DELTA_PHI 2.0 //degree
3235
#define DELTA_D 2.0 //cm
@@ -40,7 +43,7 @@ using namespace std;
4043

4144
/* Lane detector parameter */
4245
#define CANNY_THRESHOLD_1 50
43-
#define CANNY_THRESHOLD_2 300
46+
#define CANNY_THRESHOLD_2 200
4447
#define HOUGH_THRESHOLD 50
4548
#define SIDE_DETECT_PIXEL_CNT 20
4649
#define SIDE_DETECT_THREDHOLD 14
@@ -103,6 +106,8 @@ class LaneDetector {
103106
ros::Publisher marked_image_publisher;
104107
ros::Publisher bird_view_img_publisher;
105108
ros::Publisher histogram_publisher;
109+
ros::Publisher pose_d_publisher;
110+
ros::Publisher pose_phi_publisher;
106111

107112
bool read_threshold_setting(string yaml_path);
108113
bool read_extrinsic_calibration(string yaml_path);

0 commit comments

Comments
 (0)