Skip to content

5. Controlling the car

SamVanderstraeten edited this page Jun 1, 2021 · 16 revisions

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.

Emergency stop button

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

Switch driving mode

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!

Example SW drive script

` #!/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() `

Useful links

TODO

  • opencv
  • donkeycar
  • ...

RTTF logo

Clone this wiki locally