-
Notifications
You must be signed in to change notification settings - Fork 2
5. Controlling the car
Once all hardware is configured and all software is installed, you should be able to control the car. If the steps on this page are not working, please double-check if you executed all previous steps properly. If problems keep occurring, please contact the organization for further support.
On the side of the RF controller, you'll see a small grey button. When you hold the RF controller properly, the button should be somewhere around your thumb. This button is the emergency stop button for your RC car.
When the button is pressed, the car will execute an emergency stop. All commands to the wheels of the car will be ignored immediately and this will bring the car to a halt instantaneously. This feature is particularly useful when testing an AI model, as it is very likely that the car will make some unpredictable moves. To cancel emergency stop, click the button again. The car will react to the wheel commands again now.
Note: It is possible that the car is in 'emergency stop mode' when it is booted, depending on your action in the previous run. If your car seems to ignore all driving commands from the RF controller or the software, try toggling the emergency stop by simply clicking the button again.
TODO add picture of emergency button
2 driving modes are available to control the car: manual mode and software (AI) mode. In manual mode you use the RF controller to steer the car. In software mode, the AI module in the car driver component will take over control of the wheels.
By default, the driving mode will be set to manual driving. To switch to software mode, you'll have to execute some commands.
First of all, make sure you are connected with your Raspberry Pi and that you have an open terminal in the cardrivers container.
View the Accessing your Raspberry Pi
page to see the necessary steps to do this.
If you want to switch on software/AI driving, perform the following command:
rostopic pub /master/ai/start_driving std_msgs/Bool True --once
Likewise, to stop the AI steering (software driving mode), execute the command below:
rostopic pub /master/ai/start_driving std_msgs/Bool False --once
Important!! Note that the emergency stop button will still be available when the AI is driving. Make sure to stay alert when your software is steering the car and to put it to a halt when things go wrong!
We provide a simple script that shows basic communication with the car drivers. This example is used in the default version of the car AI as well. The challenge for all teams will be to adjust the code to their own implementation, to create the fastest car on the circuit.
You'll find some extra information about this script below the code block.
#!/usr/bin/env python
import os
from stat import ST_CTIME, ST_MODE, S_ISREG
import numpy as np
import cv2
from cv_bridge import CvBridge, CvBridgeError
import rospy
import time
from driving_module.utils import get_model_by_type
from edgecar_msgs.msg import UpdateAi, WheelsCmdStamped
from std_msgs.msg import Bool
from sensor_msgs.msg import CompressedImage
class DrivingModule():
def __init__(self):
rospy.loginfo('[{}]ctor DrivingModule'.format(rospy.get_name()))
self.vehicle_name = rospy.get_param("~veh", "edgecar")
self.update_model_subscription_name = "/{}/ai/update_model".format(self.vehicle_name)
self.start_driving_subscription_name = "/{}/ai/start_driving".format(self.vehicle_name)
self.image_subscription_name = '/{}/camera_node/image/compressed'.format(self.vehicle_name)
self.pub_car_cmd_name = '/{}/wheels_driver_node/wheels_cmd'.format(self.vehicle_name)
rospy.loginfo("[{}] Starting with vehicle_name {}".format(rospy.get_name(), self.vehicle_name))
rospy.loginfo("[{}] Subscribing to {}, {}".format(rospy.get_name(), self.update_model_subscription_name,
self.start_driving_subscription_name))
#self.sub_update_model = rospy.Subscriber(self.update_model_subscription_name, UpdateAi, self.update_ai_callback)
self.sub_start_using_ai = rospy.Subscriber(self.start_driving_subscription_name, Bool, self.start_using_ai)
self.pub_car_cmd = rospy.Publisher(self.pub_car_cmd_name, WheelsCmdStamped, queue_size=1)
self.wheels_cmd = WheelsCmdStamped()
self.image_subscriber = None # will be used later on when we start using AI
self.running = False
#self.kl = None
#self.model_name_to_use = self.get_initial_model_name()
#rospy.loginfo("[{}] Model name to use: {}".format(rospy.get_name(), self.model_name_to_use))
self.bridge = CvBridge()
def start_using_ai(self, data):
rospy.loginfo("START USING AI")
if data.data:
rospy.loginfo("[{}] Start Driving making use of CV AI : {}".format(rospy.get_name(), data.data))
self.running = True
self.image_subscriber = rospy.Subscriber(self.image_subscription_name, CompressedImage, self.process_img)
rospy.loginfo("[{}] Subscribed to image topic".format(rospy.get_name()))
elif not data.data:
self.stop_running()
# process camera image
def process_img(self, data):
if data:
try:
img = self.bridge.compressed_imgmsg_to_cv2(data)
#cv_image = self.bridge.compressed_imgmsg_to_cv2(data, "bgr8")
hsv_data = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# TODO: Add some AI magic
(angle, throttle) = magic_ai_method(hsv_data)
# Send angle & throttle command to wheel & motor
self.wheels_cmd.header.stamp = data.header.stamp
self.wheels_cmd.velocity = throttle
self.wheels_cmd.rotation = angle
self.pub_car_cmd.publish(self.wheels_cmd)
except CvBridgeError as e:
rospy.logerr("error cvbridge stuff : ", e)
def magic_ai_method(self, image):
return (0, 0.1)
def stop_running(self):
rospy.loginfo("[{} Must stop running AI container".format(rospy.get_name()))
if not self.image_subscriber is None:
self.image_subscriber.unregister()
self.image_subscriber = None
rospy.logdebug("[{}] Finished unsubscribing from image stream".format(rospy.get_name()))
self.running = False
def on_shutdown(self):
rospy.loginfo('[DrivingModule] onShutdown ...')
if self.running:
self.stop_running()
if __name__ == '__main__':
rospy.init_node('driving_node', anonymous=False)
driving_module = DrivingModule()
rospy.on_shutdown(driving_module.on_shutdown)
rospy.spin()
In the above example, which doesn't include an actual AI solution, we show all the basics needed to direct the car.
self.sub_start_using_ai = rospy.Subscriber(self.start_driving_subscription_name, Bool, self.start_using_ai)
We subscribe to the /ai/start_driving
topic. When we press the according button on the remote control, we get a notification and our callback function is executed.
In the callback function start_using_ai()
we install a new subscriber to our camera topic (/camera_node/image/compressed
) and tie it to the process_img()
method. This will be executed every frame and is our main entry point to steer the car.
On receiving a new frame or image, we can execute an AI algorithm to determine which way the car should go and how fast it should drive.
The implementation of this AI method(s) will be the main challenge for all teams in this competition.
Afterwards, the resulting angle
and throttle
values will be published on a ROS topic, so the car drivers get notified and execute the command given:
self.wheels_cmd.header.stamp = data.header.stamp
self.wheels_cmd.velocity = throttle
self.wheels_cmd.rotation = angle
self.pub_car_cmd.publish(self.wheels_cmd)
© Race to the Future 2023 - by PXL-Digital, VOKA Young & Strong & Corda Campus