- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- import rospy
- import tf
- from nav_msgs.msg import Odometry
- from geometry_msgs.msg import Twist
- from turtlesim.msg import Pose
- from sensor_msgs.msg import LaserScan
- from math import pi
- from math import atan2
- goal = (9.5, 1.5)
- perpendicular_compare = 0
- state = 0
- previous_front = 0
- # funkcja wywolywana przy przyjsciu danych ze skanera laserowego
- move_x = 1
- move_theta = 1
- def choose_direction (directions):
- num_in_list = 0
- global angle
- global dir
- global front
- global back
- global turn_left_detector
- global turn_right_detector
- global perpendicular
- global head_min
- head_min = min(min(directions[0:10]), min(directions[350:359]))
- dir = min(directions)
- for direction in directions:
- if (direction == dir):
- print "INDEX", num_in_list
- angle = num_in_list*2*pi/360
- print "LOOP ANGLE", angle
- else:
- num_in_list += 1
- turn_left_detector = directions[45]
- #turn_right_detector = direstions[]
- front = directions[70]
- back = directions[110]
- perpendicular = directions[90]
- return (dir, angle, front, back, turn_left_detector)
- def check_front():
- global previous_front
- if (previous_front == 0):
- previous_front = front
- return False
- else:
- if(front > previous_front + 0.5):
- return True
- else:
- previous_front = front
- return False
- def scan_callback(scan):
- choose_direction(scan.ranges)
- #print "ANGLE", angle
- #print "DIR", dir
- #print scan
- def count_dest_angle(c2y, c1y, c2x, c1x):
- global dest_angle
- dest_angle = atan2 (c2y-c1y, c2x-c1x)
- return dest_angle
- angle_to_goal = float(atan2(0.5-0.5, 9.5-0.5))
- def drive_to_finish (position_theta):
- global state
- if abs(position_theta - angle_to_goal) > 0.1 and dir > 0.4:
- if position_theta <= angle_to_goal:
- new_vel.angular.z = 0.3
- elif position_theta > angle_to_goal:
- new_vel.angular.z = -0.3
- new_vel.linear.x = 0
- state = 1
- print ("Rotating to goal angle")
- else:
- state = 1
- #print ("Following goal angle")
- print ("DISTOWALL", dir)
- print ("FRONT", front)
- print ("BACK", back)
- if dir >= 0.4:
- new_vel.angular.z = 0
- new_vel.linear.x = 0.3
- print ("GO AHEAD")
- elif dir < 0.4:
- #jezeli najblizsza odleglosc od sciany jest pod katem 90 lub 270 stopni to jedz do przodu
- # or (round(angle, 2) != (round((pi, 2)*1.5))))
- #(round(angle, 2) != (round((pi*0.5, 2))))
- if (round(front, 1) != round(back, 1) or perpendicular > 0.5):
- new_vel.angular.z = -0.3
- new_vel.linear.x = 0
- print ("ROTATE TO WALL FOLLOW")
- else:
- new_vel.linear.x = 0
- state = 3
- #if (perpendicular > 0.4 or (round(front, 1) != round(back, 1))):
- # new_vel.linear.x = 0.3
- # new_vel.angular.z = 0.3
- #
- # state = 8
- def drive_next_wall():
- global state
- if check_front() == False:
- if (round(front, 2) == round(back, 2)):
- new_vel.linear.x = 0.4
- new_vel.angular.z = 0
- state = 3
- print ("LINE FOLLOW")
- else:
- if front >= back:
- new_vel.angular.z = 0.2
- new_vel.linear.x = 0.2
- state = 3
- print ("EQUALISE FROM FRONT TO BACK")
- else:
- new_vel.angular.z = -0.2
- new_vel.linear.x = 0.2
- state = 3
- print ("EQUALISE FROM BACK TO FRONT")
- return state
- elif check_front() == True:
- new_vel.angular.z = 0
- new_vel.linear.x = 0
- state = 4
- print ("LEFT TURN DETECTED")
- def turn_left():
- global state
- #if (head_min < 1):
- if (perpendicular > 0.4 or (round(front, 1) == round(back, 1))):
- new_vel.linear.x = 0.04
- new_vel.angular.z = 0.04
- print ("TURN LEFT")
- else:
- state = 3
- print ("NEXT TO WALL AGAIN")
- # funkcja wywolywana przy przyjsciu danych o lokalizacji robota
- def odom_callback(odom):
- global new_vel
- global distance_to_goal
- #global perpendicular_compare
- pose = Pose()
- pose.x = odom.pose.pose.position.x
- pose.y = odom.pose.pose.position.y
- pose.theta = tf.transformations.euler_from_quaternion([odom.pose.pose.orientation.x,odom.pose.pose.orientation.y,odom.pose.pose.orientation.z,odom.pose.pose.orientation.w])[2]
- #print "Pozycja x: ",odom.pose.pose.position.x
- #print "Pozycja y: ",odom.pose.pose.position.y
- print "Pozycja theta: ",pose.theta
- print "Kat do celu:", angle_to_goal
- curr_angle_to_goal = count_dest_angle(9.5, pose.y, 1.5, pose.x)
- #print "ANGLE ABS", abs(angle_to_goal - curr_angle_to_goal)
- #print "ANGLE", angle
- #print "FRONT", front
- if state == 0 or state == 1:
- drive_to_finish(pose.theta)
- elif state == 3:
- drive_next_wall()
- elif state == 4:
- turn_left()
- if __name__== "__main__":
- global new_vel
- new_vel = Twist()
- rospy.init_node('wr_zad', anonymous=True)
- print("ready")
- rospy.Subscriber( '/odom' , Odometry, odom_callback)
- pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
- rospy.Subscriber( '/scan' , LaserScan, scan_callback)
- rate=rospy.Rate(10) # 10Hz
- while not rospy.is_shutdown():
- pub.publish(new_vel)#wyslanie predkosci zadanej
- rate.sleep()
- print("END")