diff --git a/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Braking.rst b/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Braking.rst new file mode 100644 index 0000000..c82f2a7 --- /dev/null +++ b/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Braking.rst @@ -0,0 +1,84 @@ +Braking ROS Node (encoder_briter.py) +##################################### + +This is the braking system encoder node, it is pretty simple, there is no configuration mode, you do the configuration on the fly and it can save the previous config thanks to its internal memory. +This encoder is a Briter CANbus Multi-turn Absolute Rotary Encoder with 24 revolutions, 12-bit resolution. + +Datasheet/user manual here: https://briterencoder.com/wp-content/uploads/2021/09/CAN-Multi-Turns-User-manual-V2.2.pdf + +File Overview +^^^^^^^^^^^^^ +The file overview will explain the important parts of the node and furnish essential information about its overall function and key features + +Main +^^^^^ +The main function initializes the ros node and creates an instance of the Encoder which has the setup of the encoder and a publisher of the Encoder message (Encoder.msg custom ROS message) + +EncoderPublisher Class +^^^^^^^^^^^^^^^^^^^^^^ + +This class represents an interface for the Briter encoder in ROS2, it inherits the Node class from ROS2 and initializes the following attributes: + +#. id: Encoder id in hex +#. steps: steps per revolution +#. degrees: degrees +#. timer_period: period between the timer_callback executions (more about timer_callback below) + +Publishers: + +.. figure:: /images/ros_braking_node/braking_publisher.png + :align: center + :alt: publishers + :figclass: align-center + :width: 600px + +This publisher publishes encoder data to "encoder_freno" topic and it publishes at a 10Hz rate. + + +CAN Interface: + +.. figure:: /images/ros_braking_node/can_interface.png + :align: center + :alt: can_interface + :figclass: align-center + :width: 600px + +For aditional information about the can.interface.Bus() function visit the official documentation of the used CAN library: https://python-can.readthedocs.io/en/stable/api.html + +An instance of NewPrinter() class (more about this class below) is created as self.listener, the object is then passed to the can.Notifier() function in the instantiation of the self.notifier variable. The can.Notifier function is used as a message distributor for a bus. Notifier creates a thread to read messages from the bus and distributes them to listeners. + +.. figure:: /images/ros_braking_node/listener_creation.png + :align: center + :alt: listener + :figclass: align-center + :width: 600px + +.. figure:: /images/ros_braking_node/can_notifier.png + :align: center + :alt: notifier + :figclass: align-center + :width: 600px + + +After this, we have several functions for different purposes in the encoder. + +==================== =========================================================== =============================================================================================================================================================================================================== +Name Arguments Functionality +==================== =========================================================== =============================================================================================================================================================================================================== +shutdown None. Calls the CAN notifier stop function. +timer_callback None. Calls the ask_position function with the self.id as the argument. +ask_position id (Encoder CAN ID) Defines a CAN message variable with the data array that gets the position from the Encoder (check the datasheet's CAN commands data table at the start of this page for more information) and then it sends the message through the CAN bus. +query_mode id (Encoder CAN ID) Sets the encoder mode to query through a can.Message variable as the function above and also sends it through the CAN bus. +cambiar_id id, new (Encoder CAN ID, desired ID) Creates the CAN message and it sends it through the bus. +cambiar_baudrate id, baud (Encoder CAN ID, desired baudrate) If the baudrate argument matches one of the baudrate options it creates the CAN message and then it sends it throught the bus, if it doesn't match any option it raises an Exception. +set_return_time id, microsegundos (Encoder CAN ID, microseconds value) Sets the automatic return time of the encoder. Not working at the moment of writing this, more info about this functionality in the datasheet. +cambiar_posicion id, pos (Encoder CAN ID, desired position) Sets the current position value of the encoder. Not working at the moment of writing this, more info about this functionality in the datasheet. +position_reset id (Encoder CAN ID) Sets the current position to zero. Creates the CAN message and then sends it through the CAN bus. +==================== =========================================================== =============================================================================================================================================================================================================== + +NewPrinter Class +^^^^^^^^^^^^^^^^^ + +The NewPrinter() class is used to create a listener that can be called directly to handle the CAN messages sent. The NewPrinter() class implements the on_message_received function that is executed when theres a new message on the bus (visit https://python-can.readthedocs.io/en/stable/listeners.html#can.Listener for more info) + +When on_message_received is executed, the data is interpreted and processed so it can be usable, the data is decoded, the absolute position is adjusted and a step count is calculated based on the number of steps. Then it initializes the message to be sent as send_msg using the Encoder() custom message. After that it calculates the angle, the absolute angle and the turn, and if the angle is more than 30 degrees it calls the position_reset function from the Encoder. The data is published to the "encoder_freno" topic mentioned previously. diff --git a/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Steering.rst b/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Steering.rst new file mode 100644 index 0000000..32bb153 --- /dev/null +++ b/source/car/electronics_embedded_systems/embedded_modules/ROS_Stepper_Based_Modules/ROS_Steering.rst @@ -0,0 +1,75 @@ +Steering ROS Node (encoder_rm8004.py) +################################## + +The steering node starts can communication with rm8004 encoder, starts encoder in operational mode, listens to data recieved in the bus, interprets the data, publishes encoder interpreted data to topic "ifm_encoder" and publishes the absolute steering angle to topic "sdc_state_steering" + +File Overview +^^^^^^^^^^^^^ +The file overview will explain the important parts of the node and furnish essential information about its overall function and key features + +Main +^^^^^ +The main function initializes the node and creates an instance of RM8004Encoder() which itself is an encoder and angle data publisher + +RM8004Encoder Class +^^^^^^^^^^^^^^^^^^^ + +The RM8004Encoder Class represents an interface for the IFM RM8004 encoder in Ros2, it inherits the Node ros2 base class and initializes +the following attributes: + +#. steps: steps per revolution +#. revolution: revolution per unit +#. degrees: maximum degrees +#. encoder_data: instance of Encoder(), Encoder is a custom message type that stores encoder data (see sdv_msgs/msg/Encoder.msg) +#. encoder_id: node number id, according to encoder documentation: the address of an encoder without terminal cap is set to 32 as a standard +#. bit_res: bit resolution +#. car_steering_range: steerinng angle range +#. car_steering_pos: variable that stores the steering position in encoder steps besed on the specified steering range, encoder steps in one revolution and the total angles of rotation. The result of: self.car_steering_range * self.revolutions is the amount of encoder steps that are in the entire steering angle range and that result divided by degrees results in the total amount of steps in certain degree, giving you a step "position" + +Parameters: + +After the initial attributes are declared, two parameters are declared: "channel" of type string and "bitrate" of type int using the declare_parameter() function and retrieving their value using the get_parameter() function. The value of "channel" and "bitrate" are declared in a yaml file (see sdv_can/config/can_params.yaml) and made accesible by putting them in the share directory of the package using get_package_share_directory() function (see sdv_can/launch/can_devices.launch.py ) + +Publishers: + +Two important publishers are created: + +.. figure:: /images/ROS_steering_node/publishers.png + :align: center + :alt: publishers + :figclass: align-center + :width: 600px + +These two publishers publish encoder data to "ifm_enncoder" topic and a steerung angle to the "/sdc_state/steering" topic + +Starting can communication: + +.. figure:: /images/ROS_steering_node/can_com.png + :align: center + :alt: publishers + :figclass: align-center + :width: 600px + +For aditional information about the can.interface.Bus(), can.Message() and bus.send() functions visit the official documentation of the used can library: https://python-can.readthedocs.io/en/stable/api.html + +NewPrinter Class +^^^^^^^^^^^^^^^^^ + +At the end of RM8004Encoder() class an instance of NewPrinter() class is created, the object is then passed to the can.Notifier() function. The can.Notifier function is used as a message distributor for a bus. Notifier creates a thread to read messages from the bus and distributes them to listeners. + +.. figure:: /images/ROS_steering_node/notifier.png + :align: center + :alt: publishers + :figclass: align-center + :width: 600px + +The NewPrinter() class is used to create a listener that can be called directly to handle the CAN messages sent. The NewPrinter() class implements the on_message_recieved funtion that is executed when theres a new message on the bus (visit https://python-can.readthedocs.io/en/stable/listeners.html#can.Listener for more info) + +When on_message_recieved executes the data is interpreted and processed so it can be usable, the data is decoded, converted to decimal, the absolute position is adjusted and a step count is calculated based on the number of steps. If the absolute position exceeds half of the total resolution it is adjusted so it falls +in the acceptable range. The data is published to the encoder and steering angle topics discussed previously. + +.. figure:: /images/ROS_steering_node/publish_on_recieve.png + :align: center + :alt: publishers + :figclass: align-center + :width: 600px \ No newline at end of file diff --git a/source/car/electronics_embedded_systems/embedded_modules/embedded_modules.rst b/source/car/electronics_embedded_systems/embedded_modules/embedded_modules.rst index 3ca73f9..f46ca93 100644 --- a/source/car/electronics_embedded_systems/embedded_modules/embedded_modules.rst +++ b/source/car/electronics_embedded_systems/embedded_modules/embedded_modules.rst @@ -517,9 +517,19 @@ a maximum collector-emiter voltage of 45V. Stepper-Based Modules ===================== + The steering and pedal brake modules share essentially the same purpose: control stepper motors and read encoder and brake signals (optional). For this reason, the PCB for both modules is exactly the same. + +.. toctree:: + :maxdepth: 2 + :caption: Ros Nodes For Steering and Braking + + ROS_Stepper_Based_Modules/ROS_Steering + ROS_Stepper_Based_Modules/ROS_Braking + + --- I/O --- diff --git a/source/images/ROS_steering_node/can_com.png b/source/images/ROS_steering_node/can_com.png new file mode 100644 index 0000000..fde0513 Binary files /dev/null and b/source/images/ROS_steering_node/can_com.png differ diff --git a/source/images/ROS_steering_node/notifier.png b/source/images/ROS_steering_node/notifier.png new file mode 100644 index 0000000..7703c69 Binary files /dev/null and b/source/images/ROS_steering_node/notifier.png differ diff --git a/source/images/ROS_steering_node/publish_on_recieve.png b/source/images/ROS_steering_node/publish_on_recieve.png new file mode 100644 index 0000000..5e87629 Binary files /dev/null and b/source/images/ROS_steering_node/publish_on_recieve.png differ diff --git a/source/images/ROS_steering_node/publishers.png b/source/images/ROS_steering_node/publishers.png new file mode 100644 index 0000000..7c41e6e Binary files /dev/null and b/source/images/ROS_steering_node/publishers.png differ diff --git a/source/images/ros_braking_node/braking_publisher.png b/source/images/ros_braking_node/braking_publisher.png new file mode 100644 index 0000000..b36a351 Binary files /dev/null and b/source/images/ros_braking_node/braking_publisher.png differ diff --git a/source/images/ros_braking_node/can_interface.png b/source/images/ros_braking_node/can_interface.png new file mode 100644 index 0000000..bb75dc4 Binary files /dev/null and b/source/images/ros_braking_node/can_interface.png differ diff --git a/source/images/ros_braking_node/can_notifier.png b/source/images/ros_braking_node/can_notifier.png new file mode 100644 index 0000000..09c018b Binary files /dev/null and b/source/images/ros_braking_node/can_notifier.png differ diff --git a/source/images/ros_braking_node/listener_creation.png b/source/images/ros_braking_node/listener_creation.png new file mode 100644 index 0000000..d4d0f8d Binary files /dev/null and b/source/images/ros_braking_node/listener_creation.png differ