avatar_furo_source_codes
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
avatar_furo_source_codes [2022/06/27 00:46] – glee | avatar_furo_source_codes [2022/06/30 08:58] (current) – glee | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | =====Programming===== | + | ====Programming==== |
- | The findface_publisher.py is a publisher that detects people' | + | **<Face Tracking> |
+ | The '' | ||
Directory: '' | Directory: '' | ||
Line 86: | Line 87: | ||
+ | The '' | ||
+ | Directory: '' | ||
+ | |||
+ | <code python | face_tracks.py> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | |||
+ | import rospy | ||
+ | from geometry_msgs.msg import Twist | ||
+ | from std_msgs.msg import Float32 | ||
+ | from geometry_msgs.msg import Point | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | from time import sleep | ||
+ | GPIO.setmode(GPIO.BOARD) | ||
+ | GPIO.setwarnings(False) | ||
+ | AN2 =33 # | ||
+ | AN1 = 32 #roll | ||
+ | DIG2 = 18 #pitch | ||
+ | DIG1 = 37 #roll | ||
+ | GPIO.setup(AN2, | ||
+ | GPIO.setup(AN1, | ||
+ | GPIO.setup(DIG2, | ||
+ | GPIO.setup(DIG1, | ||
+ | sleep(1) | ||
+ | p1=GPIO.PWM(AN1, | ||
+ | p2=GPIO.PWM(AN2, | ||
+ | |||
+ | __author__= " | ||
+ | |||
+ | |||
+ | target_x = 0; | ||
+ | target_y = 0; | ||
+ | error_x = 0; | ||
+ | error_y = 0; | ||
+ | diff_x = 0; | ||
+ | diff_y = 0; | ||
+ | max_output_x = 76.7; | ||
+ | min_output_x = -76.7; | ||
+ | max_output_y = 76.7; | ||
+ | min_output_y = -76.7; | ||
+ | |||
+ | |||
+ | def head_motion_callback(rec_point): | ||
+ | global target_y, | ||
+ | global error_x, | ||
+ | global diff_x, | ||
+ | global max_output_x, | ||
+ | global max_output_y, | ||
+ | |||
+ | Px,Dx =20, 30 | ||
+ | Py,Dy = 20 , 30 | ||
+ | |||
+ | prev_x = 0 | ||
+ | prev_y = 0 | ||
+ | |||
+ | target_x = rec_point.x | ||
+ | target_y = rec_point.y | ||
+ | |||
+ | error_x = 0 - target_x | ||
+ | error_y = 0 - target_y | ||
+ | |||
+ | diff_x = prev_x - error_x | ||
+ | diff_y = prev_y - error_y | ||
+ | |||
+ | prev_x = error_x | ||
+ | prev_y = error_y | ||
+ | |||
+ | output_x = Px*error_x + Dx*diff_x | ||
+ | output_y = Py*error_y + Dy*diff_y | ||
+ | |||
+ | if output_x > max_output_x: | ||
+ | output_x = max_output_x | ||
+ | elif output_x < min_output_x: | ||
+ | output_x = min_output_x | ||
+ | |||
+ | if output_x < 0: | ||
+ | left_speed = abs(output_x) | ||
+ | GPIO.output(DIG2, | ||
+ | p2.start(left_speed) | ||
+ | elif output_x > 0: | ||
+ | right_speed = abs(output_x) | ||
+ | GPIO.output(DIG2, | ||
+ | p2.start(right_speed) | ||
+ | |||
+ | if output_y > max_output_y: | ||
+ | output_y = max_output_y | ||
+ | elif output_y < min_output_y: | ||
+ | output_y = min_output_y | ||
+ | |||
+ | if output_y < 0: | ||
+ | upward_speed = abs(output_y) | ||
+ | GPIO.output(DIG1, | ||
+ | p1.start(upward_speed) | ||
+ | elif output_y > 0: | ||
+ | downward_speed = abs(output_y) | ||
+ | GPIO.output(DIG1, | ||
+ | p1.start(downward_speed) | ||
+ | |||
+ | |||
+ | print(output_y) | ||
+ | |||
+ | def head_vel_callback(headCTR): | ||
+ | head_roll = headCTR.data | ||
+ | |||
+ | if head_roll==4: | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG2, | ||
+ | p1.start(0) # | ||
+ | p2.start(30) # | ||
+ | # | ||
+ | |||
+ | if head_roll==2: | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG2, | ||
+ | p1.start(0) | ||
+ | p2.start(30) | ||
+ | | ||
+ | | ||
+ | if head_roll==5: | ||
+ | rospy.loginfo(" | ||
+ | p1.start(0) | ||
+ | p2.start(0) | ||
+ | #delay for 3 second | ||
+ | |||
+ | def listener(): | ||
+ | rospy.init_node(" | ||
+ | rospy.Subscriber(" | ||
+ | rospy.Subscriber(" | ||
+ | |||
+ | rate = rospy.Rate(200) | ||
+ | while not rospy.is_shutdown(): | ||
+ | rate.sleep() | ||
+ | |||
+ | |||
+ | if __name__ == ' | ||
+ | listener() | ||
+ | </ | ||
+ | |||
+ | |||
+ | \\ | ||
+ | **< | ||
+ | |||
+ | The '' | ||
+ | Directory: '' | ||
+ | |||
+ | The '' | ||
+ | Directory: '' | ||
+ | CMakeList Directory: '' | ||
+ | <code cpp | CMakeLists.txt> | ||
+ | cmake_minimum_required(VERSION 2.8.3) | ||
+ | project(learning_joy) | ||
+ | |||
+ | ## Compile as C++11, supported in ROS Kinetic and newer | ||
+ | # add_compile_options(-std=c++11) | ||
+ | |||
+ | ## Find catkin macros and libraries | ||
+ | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) | ||
+ | ## is used, also find other catkin packages | ||
+ | find_package(catkin REQUIRED COMPONENTS | ||
+ | joy | ||
+ | roscpp | ||
+ | turtlesim | ||
+ | ) | ||
+ | |||
+ | ## System dependencies are found with CMake' | ||
+ | # find_package(Boost REQUIRED COMPONENTS system) | ||
+ | |||
+ | |||
+ | ## Uncomment this if the package has a setup.py. This macro ensures | ||
+ | ## modules and global scripts declared therein get installed | ||
+ | ## See http:// | ||
+ | # catkin_python_setup() | ||
+ | |||
+ | ########### | ||
+ | ## Build ## | ||
+ | ########### | ||
+ | |||
+ | ## Specify additional locations of header files | ||
+ | ## Your package locations should be listed before other locations | ||
+ | include_directories( | ||
+ | # include | ||
+ | ${catkin_INCLUDE_DIRS} | ||
+ | ) | ||
+ | |||
+ | |||
+ | ############# | ||
+ | ## Testing ## | ||
+ | ############# | ||
+ | |||
+ | ## Add gtest based cpp test target and link libraries | ||
+ | # catkin_add_gtest(${PROJECT_NAME}-test test/ | ||
+ | # if(TARGET ${PROJECT_NAME}-test) | ||
+ | # | ||
+ | # endif() | ||
+ | |||
+ | ## Add folders to be run by python nosetests | ||
+ | # catkin_add_nosetests(test) | ||
+ | add_executable(furo src/ | ||
+ | target_link_libraries(furo ${catkin_LIBRARIES}) | ||
+ | </ | ||
+ | \\ | ||
+ | The '' | ||
+ | Directory: '' | ||
+ | <code python | roboclaw.launch> | ||
+ | <?xml version=" | ||
+ | < | ||
+ | |||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | <arg name=" | ||
+ | | ||
+ | #launches furo.py script from roboclaw_node | ||
+ | <node if=" | ||
+ | <param name=" | ||
+ | <param name=" | ||
+ | <param name=" | ||
+ | <param name=" | ||
+ | <param name=" | ||
+ | <param name=" | ||
+ | </ | ||
+ | |||
+ | <node pkg=" | ||
+ | name=" | ||
+ | < | ||
+ | file=" | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | The '' | ||
+ | Directory: '' | ||
+ | <code python | furo.py> | ||
+ | # | ||
+ | from math import pi, cos, sin | ||
+ | |||
+ | import diagnostic_msgs | ||
+ | import diagnostic_updater | ||
+ | import roboclaw_driver.roboclaw_driver as roboclaw | ||
+ | import rospy | ||
+ | import tf | ||
+ | from geometry_msgs.msg import Quaternion, Twist | ||
+ | from nav_msgs.msg import Odometry | ||
+ | |||
+ | __author__ = " | ||
+ | |||
+ | |||
+ | # TODO need to find some better was of handling OSerror 11 or preventing it, any ideas? | ||
+ | |||
+ | class EncoderOdom: | ||
+ | def __init__(self, | ||
+ | self.TICKS_PER_METER = ticks_per_meter | ||
+ | self.BASE_WIDTH = base_width | ||
+ | self.odom_pub = rospy.Publisher('/ | ||
+ | self.cur_x = 0 | ||
+ | self.cur_y = 0 | ||
+ | self.cur_theta = 0.0 | ||
+ | self.last_enc_left = 0 | ||
+ | self.last_enc_right = 0 | ||
+ | self.last_enc_time = rospy.Time.now() | ||
+ | |||
+ | @staticmethod | ||
+ | def normalize_angle(angle): | ||
+ | while angle > pi: | ||
+ | angle -= 2.0 * pi | ||
+ | while angle < -pi: | ||
+ | angle += 2.0 * pi | ||
+ | return angle | ||
+ | |||
+ | def update(self, | ||
+ | left_ticks = enc_left - self.last_enc_left | ||
+ | right_ticks = enc_right - self.last_enc_right | ||
+ | self.last_enc_left = enc_left | ||
+ | self.last_enc_right = enc_right | ||
+ | |||
+ | dist_left = left_ticks / self.TICKS_PER_METER | ||
+ | dist_right = right_ticks / self.TICKS_PER_METER | ||
+ | dist = (dist_right + dist_left) / 2.0 | ||
+ | |||
+ | current_time = rospy.Time.now() | ||
+ | d_time = (current_time - self.last_enc_time).to_sec() | ||
+ | self.last_enc_time = current_time | ||
+ | |||
+ | # TODO find better what to determine going straight, this means slight deviation is accounted | ||
+ | if left_ticks == right_ticks: | ||
+ | d_theta = 0.0 | ||
+ | self.cur_x += dist * cos(self.cur_theta) | ||
+ | self.cur_y += dist * sin(self.cur_theta) | ||
+ | else: | ||
+ | d_theta = (dist_right - dist_left) / self.BASE_WIDTH | ||
+ | r = dist / d_theta | ||
+ | self.cur_x += r * (sin(d_theta + self.cur_theta) - sin(self.cur_theta)) | ||
+ | self.cur_y -= r * (cos(d_theta + self.cur_theta) - cos(self.cur_theta)) | ||
+ | self.cur_theta = self.normalize_angle(self.cur_theta + d_theta) | ||
+ | |||
+ | if abs(d_time) < 0.000001: | ||
+ | vel_x = 0.0 | ||
+ | vel_theta = 0.0 | ||
+ | else: | ||
+ | vel_x = dist / d_time | ||
+ | vel_theta = d_theta / d_time | ||
+ | |||
+ | return vel_x, vel_theta | ||
+ | |||
+ | def update_publish(self, | ||
+ | # 2106 per 0.1 seconds is max speed, error in the 16th bit is 32768 | ||
+ | # TODO lets find a better way to deal with this error | ||
+ | # | ||
+ | # | ||
+ | if abs(enc_left - self.last_enc_left) > 20000: | ||
+ | rospy.logerr(" | ||
+ | elif abs(enc_right - self.last_enc_right) > 20000: | ||
+ | rospy.logerr(" | ||
+ | else: | ||
+ | vel_x, vel_theta = self.update(enc_left, | ||
+ | self.publish_odom(self.cur_x, | ||
+ | |||
+ | def publish_odom(self, | ||
+ | quat = tf.transformations.quaternion_from_euler(0, | ||
+ | current_time = rospy.Time.now() | ||
+ | |||
+ | br = tf.TransformBroadcaster() | ||
+ | br.sendTransform((cur_x, | ||
+ | | ||
+ | | ||
+ | " | ||
+ | " | ||
+ | |||
+ | odom = Odometry() | ||
+ | odom.header.stamp = current_time | ||
+ | odom.header.frame_id = ' | ||
+ | |||
+ | odom.pose.pose.position.x = cur_x | ||
+ | odom.pose.pose.position.y = cur_y | ||
+ | odom.pose.pose.position.z = 0.0 | ||
+ | odom.pose.pose.orientation = Quaternion(*quat) | ||
+ | |||
+ | odom.pose.covariance[0] = 0.01 | ||
+ | odom.pose.covariance[7] = 0.01 | ||
+ | odom.pose.covariance[14] = 99999 | ||
+ | odom.pose.covariance[21] = 99999 | ||
+ | odom.pose.covariance[28] = 99999 | ||
+ | odom.pose.covariance[35] = 0.01 | ||
+ | |||
+ | odom.child_frame_id = ' | ||
+ | odom.twist.twist.linear.x = vx | ||
+ | odom.twist.twist.linear.y = 0 | ||
+ | odom.twist.twist.angular.z = vth | ||
+ | odom.twist.covariance = odom.pose.covariance | ||
+ | |||
+ | self.odom_pub.publish(odom) | ||
+ | |||
+ | |||
+ | class Node: | ||
+ | def __init__(self): | ||
+ | |||
+ | self.ERRORS = {0x0000: (diagnostic_msgs.msg.DiagnosticStatus.OK, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | rospy.init_node(" | ||
+ | rospy.on_shutdown(self.shutdown) | ||
+ | rospy.loginfo(" | ||
+ | dev_name = rospy.get_param(" | ||
+ | baud_rate = int(rospy.get_param(" | ||
+ | |||
+ | self.address = int(rospy.get_param(" | ||
+ | if self.address > 0x87 or self.address < 0x80: | ||
+ | rospy.logfatal(" | ||
+ | rospy.signal_shutdown(" | ||
+ | |||
+ | # TODO need someway to check if address is correct | ||
+ | try: | ||
+ | roboclaw.Open(dev_name, | ||
+ | except Exception as e: | ||
+ | rospy.logfatal(" | ||
+ | rospy.logdebug(e) | ||
+ | rospy.signal_shutdown(" | ||
+ | |||
+ | self.updater = diagnostic_updater.Updater() | ||
+ | self.updater.setHardwareID(" | ||
+ | self.updater.add(diagnostic_updater. | ||
+ | | ||
+ | |||
+ | try: | ||
+ | version = roboclaw.ReadVersion(self.address) | ||
+ | except Exception as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | pass | ||
+ | |||
+ | if not version[0]: | ||
+ | rospy.logwarn(" | ||
+ | else: | ||
+ | rospy.logdebug(repr(version[1])) | ||
+ | |||
+ | roboclaw.SpeedM1M2(self.address, | ||
+ | roboclaw.ResetEncoders(self.address) | ||
+ | |||
+ | self.MAX_SPEED = float(rospy.get_param(" | ||
+ | self.TICKS_PER_METER = float(rospy.get_param(" | ||
+ | self.BASE_WIDTH = float(rospy.get_param(" | ||
+ | |||
+ | self.encodm = EncoderOdom(self.TICKS_PER_METER, | ||
+ | self.last_set_speed_time = rospy.get_rostime() | ||
+ | |||
+ | rospy.Subscriber(" | ||
+ | |||
+ | rospy.sleep(1) | ||
+ | |||
+ | rospy.logdebug(" | ||
+ | rospy.logdebug(" | ||
+ | rospy.logdebug(" | ||
+ | rospy.logdebug(" | ||
+ | rospy.logdebug(" | ||
+ | rospy.logdebug(" | ||
+ | |||
+ | def run(self): | ||
+ | rospy.loginfo(" | ||
+ | r_time = rospy.Rate(10) | ||
+ | while not rospy.is_shutdown(): | ||
+ | # TODO need find solution to the OSError11 looks like sync problem with serial | ||
+ | status1, enc1, crc1 = None, None, None | ||
+ | status2, enc2, crc2 = None, None, None | ||
+ | | ||
+ | try: | ||
+ | status1, enc1, crc1 = roboclaw.ReadEncM1(self.address) | ||
+ | except ValueError: | ||
+ | pass | ||
+ | except OSError as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | |||
+ | try: | ||
+ | status2, enc2, crc2 = roboclaw.ReadEncM2(self.address) | ||
+ | except ValueError: | ||
+ | pass | ||
+ | except OSError as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | |||
+ | if (enc1 != None) & (enc2 != None): | ||
+ | rospy.logdebug(" | ||
+ | self.encodm.update_publish(enc1, | ||
+ | self.updater.update() | ||
+ | r_time.sleep() | ||
+ | |||
+ | def cmd_vel_callback(self, | ||
+ | self.last_set_speed_time = rospy.get_rostime() | ||
+ | |||
+ | linear_x = twist.linear.x | ||
+ | if linear_x==10: | ||
+ | roboclaw.ResetEncoders(self.address) | ||
+ | linear_x=0 | ||
+ | if linear_x > self.MAX_SPEED: | ||
+ | linear_x = self.MAX_SPEED | ||
+ | if linear_x < -self.MAX_SPEED: | ||
+ | linear_x = -self.MAX_SPEED | ||
+ | |||
+ | vr = linear_x - twist.angular.z * self.BASE_WIDTH / 2.0 # m/s | ||
+ | vl = linear_x + twist.angular.z * self.BASE_WIDTH / 2.0 | ||
+ | |||
+ | vr_ticks = int(vr * 60) # ticks/s | ||
+ | vl_ticks = int(vl * 60) | ||
+ | |||
+ | rospy.loginfo(" | ||
+ | |||
+ | try: | ||
+ | # This is a hack way to keep a poorly tuned PID from making noise at speed 0 | ||
+ | if vr_ticks is 0 and vl_ticks is 0: | ||
+ | roboclaw.ForwardM1(self.address, | ||
+ | roboclaw.ForwardM2(self.address, | ||
+ | else: | ||
+ | if vr_ticks> | ||
+ | roboclaw.BackwardM1(self.address, | ||
+ | else: | ||
+ | roboclaw.ForwardM1(self.address, | ||
+ | if vl_ticks> | ||
+ | roboclaw.BackwardM2(self.address, | ||
+ | else: | ||
+ | roboclaw.ForwardM2(self.address, | ||
+ | except OSError as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | |||
+ | # TODO: Need to make this work when more than one error is raised | ||
+ | def check_vitals(self, | ||
+ | try: | ||
+ | status = roboclaw.ReadError(self.address)[1] | ||
+ | except OSError as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | return | ||
+ | state, message = self.ERRORS[status] | ||
+ | stat.summary(state, | ||
+ | try: | ||
+ | stat.add(" | ||
+ | stat.add(" | ||
+ | stat.add(" | ||
+ | stat.add(" | ||
+ | except OSError as e: | ||
+ | rospy.logwarn(" | ||
+ | rospy.logdebug(e) | ||
+ | return stat | ||
+ | |||
+ | # TODO: need clean shutdown so motors stop even if new msgs are arriving | ||
+ | def shutdown(self): | ||
+ | rospy.loginfo(" | ||
+ | try: | ||
+ | roboclaw.ForwardM1(self.address, | ||
+ | roboclaw.ForwardM2(self.address, | ||
+ | except OSError: | ||
+ | rospy.logerr(" | ||
+ | try: | ||
+ | roboclaw.ForwardM1(self.address, | ||
+ | roboclaw.ForwardM2(self.address, | ||
+ | except OSError as e: | ||
+ | rospy.logerr(" | ||
+ | rospy.logdebug(e) | ||
+ | |||
+ | |||
+ | if __name__ == " | ||
+ | try: | ||
+ | node = Node() | ||
+ | node.run() | ||
+ | except rospy.ROSInterruptException: | ||
+ | pass | ||
+ | rospy.loginfo(" | ||
+ | | ||
+ | </ | ||
+ | The '' | ||
+ | Directory: '' | ||
+ | <code python | finalheadmotor.py> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | |||
+ | import rospy | ||
+ | from geometry_msgs.msg import Twist | ||
+ | from std_msgs.msg import Float32 | ||
+ | import RPi.GPIO as GPIO | ||
+ | from time import sleep | ||
+ | GPIO.setmode(GPIO.BOARD) | ||
+ | GPIO.setwarnings(False) | ||
+ | AN2 =33 | ||
+ | AN1 = 32 | ||
+ | DIG2 = 18 | ||
+ | DIG1 = 37 | ||
+ | GPIO.setup(AN2, | ||
+ | GPIO.setup(AN1, | ||
+ | GPIO.setup(DIG2, | ||
+ | GPIO.setup(DIG1, | ||
+ | sleep(1) | ||
+ | p1=GPIO.PWM(AN1, | ||
+ | p2=GPIO.PWM(AN2, | ||
+ | |||
+ | __author__= " | ||
+ | |||
+ | class callback: | ||
+ | |||
+ | def head_vel_callback(self, | ||
+ | head_roll = headCTR.data | ||
+ | |||
+ | if head_roll==1:# | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG1, | ||
+ | p1.start(60) # | ||
+ | p2.start(0) | ||
+ | |||
+ | |||
+ | elif head_roll==5: | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG1, | ||
+ | p1.start(60) | ||
+ | p2.start(0) | ||
+ | |||
+ | elif head_roll==3: | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG2, | ||
+ | p1.start(0) | ||
+ | p2.start(60) | ||
+ | |||
+ | elif head_roll==2: | ||
+ | rospy.loginfo(" | ||
+ | GPIO.output(DIG2, | ||
+ | p1.start(0) | ||
+ | p2.start(60) | ||
+ | | ||
+ | | ||
+ | elif head_roll==4: | ||
+ | rospy.loginfo(" | ||
+ | p1.start(0) #speed 0 out of 100 | ||
+ | p2.start(0) | ||
+ | | ||
+ | |||
+ | |||
+ | def __init__(self): | ||
+ | rospy.Subscriber(" | ||
+ | |||
+ | rate = rospy.Rate(10) | ||
+ | while not rospy.is_shutdown(): | ||
+ | rate.sleep() | ||
+ | | ||
+ | print(1) | ||
+ | |||
+ | if __name__ == ' | ||
+ | rospy.init_node(' | ||
+ | try: | ||
+ | wow = callback() | ||
+ | except rospy.ROSInitException: | ||
+ | pass | ||
+ | </ | ||
avatar_furo_source_codes.1656315979.txt.gz · Last modified: 2022/06/27 00:46 by glee