Difference between revisions of "2021FallTeam5"

From MAE/ECE 148 - Introduction to Autonomous Vehicles
Jump to navigation Jump to search
 
(23 intermediate revisions by the same user not shown)
Line 1: Line 1:
We collaborated with Team 6 and formed Team 5.5. We designed a two-car project which includes a lead car and a follower car. You can find information about follower car in our team's page. More information about the lead car please refer to [https://guitar.ucsd.edu/maeece148/index.php/2021FallTeam6 Team 6's page].
We collaborated with Team 6 and formed Team 5.5. We designed a two-car project which includes a lead car and a follower car. You can find information about follower car in our team's page. More information about the lead car please refer to [https://guitar.ucsd.edu/maeece148/index.php/2021FallTeam6 Team 6's page].


Our car is named BumbleBee. and the Team 6 car is named AutoPrime.
Our car is named BumbleBee. and the Team 6 car is named Autonomous Prime.


[[File:Bumblebee.jpg|520px|right]]
[[File:Bumblebee.jpg|520px|right]]
Line 11: Line 11:
'''Team 5 Members'''
'''Team 5 Members'''


Zeyu Huang-Aerospace Engineering
Zeyu Huang, Aerospace Engineering


[[File:Zoey.jpg|200px]]
[[File:Zoey.jpg|200px]]


Jason Almeda-Computer Engineering
Jason Almeda, Computer Engineering


[[File:Jason.jpg|200px]]
[[File:Jason.jpg|200px]]
Line 57: Line 57:
[[File:Emergency Stop Demo.mp4|600px]]
[[File:Emergency Stop Demo.mp4|600px]]


==== <big>Autonomous Laps Demonstration</big> ====
==== <big>Autonomous Laps</big> ====


[https://youtu.be/HiGb3pnfM2k 3 Autonomous Laps Donkey-Car Classroom Track]
[https://youtu.be/HiGb3pnfM2k 3 Autonomous Laps Donkey-Car Classroom Track]
Line 111: Line 111:
On the lead car '''Autonomous Prime''', we set up the talker node python file and its corresponding ROS launch file from scratch. We were able to read data from the IMU and filter the data we wanted to read from a certain axis. We achieved this by directly reading from serial ports with pySerial package, parsing the string we read from the serial, and converting them to numbers.
On the lead car '''Autonomous Prime''', we set up the talker node python file and its corresponding ROS launch file from scratch. We were able to read data from the IMU and filter the data we wanted to read from a certain axis. We achieved this by directly reading from serial ports with pySerial package, parsing the string we read from the serial, and converting them to numbers.


On the follower car '''Bumblebee''', we have programmed a “listener_node“ and its corresponding launch file for reading the values and calling a newly developed function in the lane_guidance_node for stopping the car.
On the follower car '''Bumblebee''', we have programmed a "listener_node" and its corresponding launch file for reading the values and calling a newly developed function in the lane_guidance_node for stopping the car. We've changed all the node name and updated all the topic name using <code>catkin build</code> to update the ucsd_robo_car package.


We have also been able to connect our follower car to the network and read the published values from the lead car.  We are confident that this method is fully functioning. We have also implemented a security mechanism for the communication. In the listener node, we have specified that the "Stop" method is only getting called if a specific String is attached to the published message. We are able to publish and receive this message. Unfortunately, we have not been able to test our system and get rid of the last bugs.
We have also been able to connect our follower car to the network and read the published values from the lead car.  We are confident that this method is fully functioning. We have also implemented a security mechanism for the communication. In the listener node, we have specified that the "Stop" method is only getting called if a specific String is attached to the published message. We are able to publish and receive this message. Unfortunately, we have not been able to test our system and get rid of the last bugs.
Line 123: Line 123:
You can find the GitHub repository to our code here: https://github.com/LiamEFowler/ECE-MAE-148-Group5.5-Black-Ice
You can find the GitHub repository to our code here: https://github.com/LiamEFowler/ECE-MAE-148-Group5.5-Black-Ice


====== listener_node.py ======
====== listener_node_follow.py ======
  <nowiki>
  <nowiki>
  #!/usr/bin/env python3
  #!/usr/bin/env python3
Line 147: Line 147:
     rospy.Subscriber("SecurityCode", String, callbackSec)
     rospy.Subscriber("SecurityCode", String, callbackSec)
     rospy.Subscriber("CrashAlert", String, callbackAlert)
     rospy.Subscriber("CrashAlert", String, callbackAlert)
    #stopSignal = rospy.Publisher('ThrottleStop', String, queue_size=10)
   
   
     if sec == 'I am Autonomous Prime, Autobots, roll out!':
     if sec == 'I am Autonomous Prime, Autobots, roll out!':
Line 157: Line 156:
     global stopSignal
     global stopSignal
     stopSignal = 'stop'
     stopSignal = 'stop'
    #stopSignal.publish('Stop')
   
   
  if __name__ == '__main__':
  if __name__ == '__main__':
     listener()
     listener()</nowiki>
</nowiki>


====== listener_node_launch.launch ======
====== listener_node_launch_follow.launch ======
  <nowiki>
  <nowiki>
  <launch>
  <launch>
   <node name="listener_node" pkg="ucsd_robo_car_simple_ros" type="listener_node.py" />
   <node name="listener_node" pkg="ucsd_robo_car_simple_ros" type="listener_node_follow.py" />
  </launch>
  </launch></nowiki>
</nowiki>


==== '''lane_guidance_node.py (follower car only)''' ====
====== lane_guidance_node_follow.py ======
  <nowiki>
  <nowiki>
  #!/usr/bin/env python3
  #!/usr/bin/env python3
Line 178: Line 174:
   
   
   
   
  LANE_GUIDANCE_NODE_NAME = 'lane_guidance_node'
  LANE_GUIDANCE_NODE_NAME = 'lane_guidance_node_follow'
  STEERING_TOPIC_NAME = '/steering_follow'
  STEERING_TOPIC_NAME = '/steering_follow'
  THROTTLE_TOPIC_NAME = '/throttle_follow'
  THROTTLE_TOPIC_NAME = '/throttle_follow'
  CENTROID_TOPIC_NAME = '/centroid_follow'
  CENTROID_TOPIC_NAME = '/centroid_follow'
#LISTENER_TOPIC_NAME = 'ThrottleStop'
#throttle_message = 'go'
   
   
  class PathPlanner:
  class PathPlanner:
Line 194: Line 188:
         self.throttle_float = Float32()
         self.throttle_float = Float32()
         self.centroid_subscriber = rospy.Subscriber(CENTROID_TOPIC_NAME, Float32, self.controller)
         self.centroid_subscriber = rospy.Subscriber(CENTROID_TOPIC_NAME, Float32, self.controller)
        # self.listener_subscriber = rospy.Subscriber(LISTENER_TOPIC_NAME, String,queue_size=10) #initialize listener sub
   
   
         # Getting ROS parameters set from calibration Node
         # Getting ROS parameters set from calibration Node
Line 202: Line 195:
         self.error_threshold = rospy.get_param('error_threshold')
         self.error_threshold = rospy.get_param('error_threshold')
         self.zero_throttle = rospy.get_param('zero_throttle')
         self.zero_throttle = rospy.get_param('zero_throttle')
         # Display Parameters
         # Display Parameters
         rospy.loginfo(
         rospy.loginfo(
Line 243: Line 237:
         rate.sleep()
         rate.sleep()
  if __name__ == '__main__':
  if __name__ == '__main__':
     main()
     main()</nowiki>
</nowiki>
 
==== '''ros_racer_launch.launch (altered for different names on different cars, but if you implement then be sure to double check these names in all launch files and the scripts folder)''' ====


Lead Car:
====== ros_racer_launch_follow.launch ======
<nowiki>
<launch>
  <include file="$(find ucsd_robo_car_simple_ros)/launch/throttle_and_steering_launch.launch"> </include>
  <include file="$(find ucsd_robo_car_simple_ros)/launch/laneDetection_launch.launch"> </include>
  <include file="$(find ucsd_robo_car_simple_ros)/launch/talker_node_launch.launch"> </include>
</launch>
</nowiki>
 
Follower Car:
  <nowiki>
  <nowiki>
  <launch>
  <launch>
Line 263: Line 245:
   <include file="$(find ucsd_robo_car_simple_ros)/launch/laneDetection_follow_launch.launch"> </include>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/laneDetection_follow_launch.launch"> </include>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/listener_node_launch.launch"> </include>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/listener_node_launch.launch"> </include>
  </launch>
  </launch></nowiki>
</nowiki>


== Acknowledgements ==
==== <big>Resources Used for Final Project</big> ====
 
Instructor - Prof. Jack Silberman
 
TA - Dominic Nightingale
 
TA - Haoru Xue
 
ECE Makerspace
 
== Resources Used for Final Project ==


[https://learn.sparkfun.com/tutorials/openlog-artemis-hookup-guide?_ga=2.138529911.534599871.1638165181-1867547520.1638165181 IMU Hookup Guide]
[https://learn.sparkfun.com/tutorials/openlog-artemis-hookup-guide?_ga=2.138529911.534599871.1638165181-1867547520.1638165181 IMU Hookup Guide]
Line 289: Line 260:


And countless Google queries for debugging...
And countless Google queries for debugging...
== Acknowledgements ==
Instructor - Prof. Jack Silberman
TA - Dominic Nightingale
TA - Haoru Xue
ECE Makerspace

Latest revision as of 09:58, 12 December 2021

We collaborated with Team 6 and formed Team 5.5. We designed a two-car project which includes a lead car and a follower car. You can find information about follower car in our team's page. More information about the lead car please refer to Team 6's page.

Our car is named BumbleBee. and the Team 6 car is named Autonomous Prime.

Bumblebee.jpg


Team Members

Team 5 Members

Zeyu Huang, Aerospace Engineering

Zoey.jpg

Jason Almeda, Computer Engineering

Jason.jpg


Team 6 Members

Liam Fowler, Mechanical Engineering

Johannes Diehm, UCSD Extension

Robot Setup

Mechanical Design

Camera and Lidar Mount: The camera and lidar mount is consist of three components, base, link, and brace. The linkage design allows the camera to freely adjust its amgle and height in order to find the best view for training, calibration, and driving.

CameraSupport.png


Electronics Mounting Plate: The electronics are mount on this electronics plate which has trough to accomodate M4 screws. The distance between the center of two troughs is 12mm, and the trough allows us to easily adjust the positions of electronics.

ElectronicsMounting.pngAssembly.png


Jetson Case: The jetson case is consist of a top case and a bottom case

JetsonCaseTop.png JetsonCaseBottom.png

Electronics

Wiring Diagram

Schematics.png

Emergency Stop

File:Emergency Stop Demo.mp4

Autonomous Laps

3 Autonomous Laps Donkey-Car Classroom Track

3 Autonomous Laps Donkey-Car Twisty Track

3 Autonomous Laps ROS2 Classroom

Final Project

Project Proposal

Our goal was to develop a system of nodes in ROS to enable vehicle to vehicle communication between 2 cars. We took inspiration for our project from the "Black Ice" phenomenon, whereby cars in icy conditions slide out and crash due to difficult-to-see ice on the road. By allowing cars to communicate with one another, a car involved in a crash could tell other cars that there is an issue on the road ahead, allowing the cars to slow down or stop to avoid the road hazard.

Our project consists of two cars: the lead car and the follower car. If the lead car should crash, it shall publish a message to the follower car, which causes it to stop, thus preventing that the follower car from crashing into the same obstacle. For sensing the crash, we use the accelerometer sensor on an Openlog Artemis IMU in the lead car, which we initialized by adding the device when creating the Docker Container with the robot image. If a specific deceleration threshold is met (i.e. 10 milli g), the car publishes a message to a connected following car. If the follower car receives this specific message, it should cause an immediate stop.

In order to prevent hackers from slowing down or stopping the follower car without a road hazard being present, we also include a unique security string published by the lead car and subscribed to by the follower car. If the security string being sent to the follower car before a stop command does not match the expected security string stored on the follower car, then the follower car will not accept a message to stop, and will continue to move around the track.

In our case, we set the lead car to be the "Master" roscore, to which we connected the follower car (so that both cars use the same roscore). Both cars run many of the same nodes, clients, and servers as described in Dominic Nightingale's Simple ROS framework. However, in order to ensure the topics being published and subscribed do not cross cars (i.e. camera on one car is used by the lane guidance on the other car), we gave the each topic with the potential to cross over a new unique identifier.

Bumblebee Specification

Our car Bunblebee is the follower car implemented with listener node, by writing a listener node script and building a lisner node launch file. We also modified the ros racer launch file correspondingly to launch the listner node.

The listener node will first need to receive security message 'I am Autonomous Prime, Autobots, roll out!' from the lead car Autonomous Prime in order to process any further commands. After confirming the message is sent from Autonomous Prime, the listener node will pass the stop message to lane guidance node when the it receives the 'stop' command. The lane guidance node will then overwrite the throttle and the steering of the Bumblebee to zero and stops the driving.

All the innate node names and topic names are changed differently from Autonomous Prime in order to prevent overwriting information, including /camera_rgb, /centroid, /steering, /throttle.

Topic names.png

Project Gantt Chart

GanttChart.jpg

Presentation

Weekly Presentation

Final Proposal Slides

11/23 Status Update

12/2 Status Update

Final Presentation

Final Presentation Slides

Accomplishment

Interence.gif

On the lead car Autonomous Prime, we set up the talker node python file and its corresponding ROS launch file from scratch. We were able to read data from the IMU and filter the data we wanted to read from a certain axis. We achieved this by directly reading from serial ports with pySerial package, parsing the string we read from the serial, and converting them to numbers.

On the follower car Bumblebee, we have programmed a "listener_node" and its corresponding launch file for reading the values and calling a newly developed function in the lane_guidance_node for stopping the car. We've changed all the node name and updated all the topic name using catkin build to update the ucsd_robo_car package.

We have also been able to connect our follower car to the network and read the published values from the lead car. We are confident that this method is fully functioning. We have also implemented a security mechanism for the communication. In the listener node, we have specified that the "Stop" method is only getting called if a specific String is attached to the published message. We are able to publish and receive this message. Unfortunately, we have not been able to test our system and get rid of the last bugs.

Retrospection

We are confident that our mechanism of stopping the follower car after a crash of the lead car is in principle functioning, but in the end, even though we have worked all night, we haven't had enough time to finish our project. In the end, we have had an issue with messed up file names that stopped the follower car from working. We found out too late that the nodes are not allowed to have the same names on the lead and the follower car. If we had just a little more time, we could have better checked all of our nodes and topics and renamed them. Because of that, we weren't able to test the system, but think that it was essentially working based on a brief test in which it appeared that the ESC switched from forward throttle (i.e. no_error_throttle) to zero throttle. At that point however, we had run out of battery and it was too late to fully verify whether that was truly because our system worked in its entirety.

Source Code

You can find the GitHub repository to our code here: https://github.com/LiamEFowler/ECE-MAE-148-Group5.5-Black-Ice

listener_node_follow.py
 #!/usr/bin/env python3
 
 import rospy
 from std_msgs.msg import String
 sec = None
 alert = None
 stopSignal = 'continue'
 
 def callbackSec(data):
     global sec
     sec = data.data
     rospy.loginfo(rospy.get_caller_id() + "%s", data.data)
 
 def callbackAlert(data):
     global alert
     alert = data.data
     rospy.loginfo(rospy.get_caller_id() + "%s", data.data)   
 
 def listener():
     rospy.init_node('listener', anonymous=True)
     rospy.Subscriber("SecurityCode", String, callbackSec)
     rospy.Subscriber("CrashAlert", String, callbackAlert)
 
     if sec == 'I am Autonomous Prime, Autobots, roll out!':
         if alert == 'stop':
             stop()
     rospy.spin()
 
 def stop():
     global stopSignal
     stopSignal = 'stop'
 
 if __name__ == '__main__':
     listener()
listener_node_launch_follow.launch
 <launch>
   <node name="listener_node" pkg="ucsd_robo_car_simple_ros" type="listener_node_follow.py" />
 </launch>
lane_guidance_node_follow.py
 #!/usr/bin/env python3
 import rospy
 import listener_node_follow as listener_node
 from std_msgs.msg import Float32, Int32, Int32MultiArray, String
 
 
 LANE_GUIDANCE_NODE_NAME = 'lane_guidance_node_follow'
 STEERING_TOPIC_NAME = '/steering_follow'
 THROTTLE_TOPIC_NAME = '/throttle_follow'
 CENTROID_TOPIC_NAME = '/centroid_follow'
 
 class PathPlanner:
      def __init__(self):
         # Initialize node and create publishers/subscribers
         self.init_node = rospy.init_node(LANE_GUIDANCE_NODE_NAME, anonymous=False)
         self.steering_publisher = rospy.Publisher(STEERING_TOPIC_NAME, Float32, queue_size=1)
         self.throttle_publisher = rospy.Publisher(THROTTLE_TOPIC_NAME, Float32, queue_size=1)
         self.steering_float = Float32()
         self.throttle_float = Float32()
         self.centroid_subscriber = rospy.Subscriber(CENTROID_TOPIC_NAME, Float32, self.controller)
 
         # Getting ROS parameters set from calibration Node
         self.steering_sensitivity = rospy.get_param('steering_sensitivity')
         self.no_error_throttle = rospy.get_param('no_error_throttle')
         self.error_throttle = rospy.get_param('error_throttle')
         self.error_threshold = rospy.get_param('error_threshold')
         self.zero_throttle = rospy.get_param('zero_throttle')

         # Display Parameters
         rospy.loginfo(
             f'\nsteering_sensitivity: {self.steering_sensitivity}'
             f'\nno_error_throttle: {self.no_error_throttle}'
             f'\nerror_throttle: {self.error_throttle}'
             f'\nerror_threshold: {self.error_threshold}')
     def controller(self,data):
         try:
             kp = self.steering_sensitivity
             error_x = data.data
             self.get_logger().info(f"{error_x}")
             if error_x <= self.error_threshold:
                 throttle_float = self.no_error_throttle
             else:
                 throttle_float = self.error_throttle
             steering_float = float(kp * error_x)
             if steering_float < -1.0:
                 steering_float = -1.0
             elif steering_float > 1.0:
                 steering_float = 1.0
             else:
                 pass
 
             if listener_node.stopSignal == 'stop':
                 self.throttle_publisher.data = self.zero_throttle
                 self.throttle_publisher.publish(self.throttle_float)
             else:
                 self.steering_float.data = steering_float
                 self.throttle_float.data = throttle_float
                 self.steering_publisher.publish(self.steering_float)
                 self.throttle_publisher.publish(self.throttle_float)
         except KeyboardInterrupt:
             self.throttle_publisher.data = self.zero_throttle
             self.throttle_publisher.publish(self.throttle_float)
 def main():
     path_planner = PathPlanner()
     rate = rospy.Rate(15)
     while not rospy.is_shutdown():
         rospy.spin()
         rate.sleep()
 if __name__ == '__main__':
    main()
ros_racer_launch_follow.launch
 <launch>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/throttle_and_steering_follow_launch.launch"> </include>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/laneDetection_follow_launch.launch"> </include>
   <include file="$(find ucsd_robo_car_simple_ros)/launch/listener_node_launch.launch"> </include>
 </launch>

Resources Used for Final Project

IMU Hookup Guide

Connecting Multiple ROS Machines

Rospy Tutorial

Pyserial Library Documentation

Jetson Nano Case (case used slightly modified from this one)

And countless Google queries for debugging...

Acknowledgements

Instructor - Prof. Jack Silberman

TA - Dominic Nightingale

TA - Haoru Xue

ECE Makerspace