Last week, I explained that I am now able to publish motor speed commands from our lab’s logic controller to gazebo to make the quadcopter models fly. Although the model did not perform as expected, I can now look further into how to create and edit models and worlds in Gazebo, with the help of RotorS plugins, to achieve a more accurate experiments.
Pictured below is the rqt graph of the system when I am running the Gazebo simulator. The following are descriptions of the files that are most important to run the simulation:
Loaded once gazebo is started
Responsible for simulating the environmental factors such as gravity, wind, and lighting.
Plugins are attached by defining them inside of the world file. The plugin used in the world file currently is called ros_gazebo_interface, which converts gazebo messages to ROS messages, and publishes telemetry and mocap messages.
Multiple plugins can be attached to a world file. For example, RotorS has a plugin to simulate wind that can be added to world files.
Loaded after world
Visual representation of objects in the simulation. These can be created and defined while running gazebo or through .xacro files. In order to create a model, a mesh must first be created for the model by using either a .stl or .dae file. Then, the parameters (i.e. mass and inertia) and boundaries for the model are defined with .xacro or .sdf files. The current simulation uses the mesh from a .dae file and a .xacro file.
Plugins can also be attached to model files by defining inside the model file. The plugins used in the current simulation are the motor_model_plugin and imu_plugin (I will need to look further into what these plugins do).
RotorS has plugins for other sensors such as lidar.
Hiperlab Controller file:
Takes in radio messages from quad_mocap_rates_controller
Subscribes to sensors messages from Gazebo to run the code every 1 second
Initiates the Run function from QuadcopterLogic.
Publishes the vector from the function that calculates motor speeds to a ROS topic that is converted into a Gazebo message for actuators
I will be working towards importing a .stl file of a crazyfly into Gazebo and creating a .xacro file that matches the crazyfly parameters in the QuadConstants file so Gazebo mimics the lab’s current ROS simulator accuratley. I will also speak with Xiangyu and Junseok to begin the thought process of how to simulate the sensors that they are working with in Gazebo.
Last week, I discussed that I fixed the issue with using QuadcopterLogic functions that would cause the system to crash. My issue stemmed from trying to call the GetTelemetry function without calling the Run function first. This revelation also fixed my issue with trying to call the GetMotorSpeeds function from QuadcopterLogic. I also explained that I was having issues trying to subscribe to radio messages produced by quad_mocap_rates_controller and when I would start the controller, a seg fault would occur.
I have fixed my subscriber issue by using classes from the Subscriber Options namespace. Next, I focused on making the Gazebo model hover. Initially the model was not responding to the motor commands from our logic, but this was easily fixed by changing the rostopic name that is published from RotorS. The model now responds to our logic’s motor speed commands. The physical properties for the Gazebo model used and the quadcopters in QuadcopterConstants are not the same, so the simulation did not respond as expected (i.e. the model overshot the set point of 2 meters).
My plan this week is to change the physical parameters of the Gazebo model to mimic those in the Quadcopter constants file for a more accurate simulation. I will also look further into how to create models in Gazebo for structures and sensors.
Last update, I showed that I was able to create telemetry messages and mocap messages that come from the the position data of an object in Gazebo. However, I was having issues calling upon QuadcopterLogic functions, which would immediately cause a segmentation fault when starting the simulation.
I was able to correct the pointer issue with QuadcopterLogic and the plugin no longer crashes when started. When started the node graph clearly shows that the telemetry and mocap messages are being published by Gazebo, and the radio messages that are published by quad_mocap_rates_control is subscribed to by Gazebo.
Unfortunately, once I hit start on the keyboard controller, an error occurred and caused a segmentation fault. Using the gdb debugger, I was able to find the function where the fault was occurring. I stepped into the and found that the shared pointer I am using for radio messages causes the error.
I copied the style of the shared pointer from our ROS simulation file, so I am trying to recreate the error in our ROS simulator to give me an idea of how to fix the issue. Once this error is resolved, the simulator should work and I can begin to work on creating sensor models in Gazebo.
Last update, I explained that I was experiencing a segmentation fault with my previous method trying to run our logic controller and publish mocap messages. This week I wanted to create my own plugin for our logic, which will work with the other plugins used by RotorS (i.e. wind disturbance and sensors).
I used the online Gazebo plugin tutorials and the plugins in the RotorS package as references to create my plugin, however running it created a segmentation fault as I attempted to access the model data from Gazebo. I then looked to manipulate the main plugin that is ran whenever Gazebo is started with the RotorS package. I was able to create telemetry messages and mocap messages that come from the the position data of an object in Gazebo.
I am still having issues calling the function from our QuadcopterLogic file. I have defined it as a shared ptr variable and use the pointer (->) to call upon functions, but I am facing segmentation faults.
Over the next few days, I will work to call upon the QuadcopterLogic function without errors. I will use Quadcopter_T and Gazebo plugins to give me an an idea on how to mitigate this issue. Once I fix the error, I will work on the radio commands portion, which I believe will be a similar function to SimVehicle in our main simulator file.
Last update I discussed difficulties using my functions in conjunction with RotorS/Gazebo. This week I was focused on finding a method to that would not create a ‘segmentation fault’ while running the ROS nodes I created. I have discovered a few important details regarding why I was experiencing a ‘segmentation fault’ and how the RotorS package interacts with Gazebo.
A document from the group that created RotorS explained that motor commands to drones can be executed by publishing to a specific ROS topic. Trying to simply edit the functions that were provided in the RotorS nodes using calculations from our logic as the input did not yield any output because of differences in the type of variables used (i.e. our logic outputs an int while their logic needs a char). For the past month, I have created functions and executable nodes that would publish to the appropriate topic and publish to our mocap and telemetry messages for our state estimator. Any time I attempted to call the ROS publishers functions I created from inside of the main function of the executable nodes, I would receive a “segmentation fault” error. However, I noticed that even without running executable nodes, there were ROS topics still being shown when using ‘rostopic list’ in the terminal. I learned that Gazebo is primarily controlled by creating plugins and I was getting an error because I was trying to access a ROS topic that was already being used by them. This means that I need to change my focus from the executable nodes to the plugins to publish the values from our logic.
My objective is to create my own plugin for our logic, which will work with the other plugins used by RotorS (i.e. wind disturbance and sensors). I will attempt to publish telemetry messages first. The message name should show up in the terminal when I use ‘rostopic list’ after launching gazebo, since plugins go beyond RotorS logic and use header files directly from Gazebo. Fortunately, my functions can still be utilized with a few tweaks.
Last update I discussed how my node needed to be modified to include a mocap and telemetry publisher in order for the entire system to work, and I believed I was close to achieving my goal of integrating our logic with RotorS/Gazebo. This week I was able to complete the C++ class I enrolled in on edx, and finish my node with sections that publish to mocap, telemetry, and the ROS topic for Gazebo. The code successfully compiled, but to my disappointment the node still did not work.
Previously I was starting the entire system (i.e. Gazebo, Gazebo models, RotorS plugins, and my node) through a launch file, so I could only see an error message explaining that the process has died. To get to the root of the problem, I ran my node separately from the rest of the system and found that I was getting a “segmentation fault”. I tried commenting out different parts of my code to the point where I only had an empty main function to find where the issues occur. There are several sections that are causing the error and it appears to be linked to a pointer (->) issue.
I will need to find a way to debug the code through eclipse to see how the code is behaving from each line to fix this issue.
I am still in the process of implementing our logic into the Gazebo/RotorS system, but I have made steady advances this week. Previously, I mentioned analyzing the codes are used by the RotorS system and re-configuring certain section to implement in my script. With the help of the C++ course I am taking, I created a function that takes the motor speeds calculated by our logic and publishes them to a specific ROS topic. I also made our quad_mocap_rates_controller and keyboard_control nodes executable for the RotorS system to use. After starting all of the necessary nodes, I observed that the drone in the simulation was not moving. I used rqt to see if all of the nodes were running and found that quad_mocap_rates_controller was not communicating with the rest of the system. I then used the rostopic echo command on the motor speeds topic and found that no values were being published to the topic. From there I noticed that the rates controller never started in the terminal because it was “waiting for the MocapEstimator to start”.
Rqt Graph Using New Nodes
I ran our simulator to look at the differences in the rqt graphs, and examined the code to see what functions are necessary for the estimator to work. I found that my code is not publishing to the mocap_output and telemetry topics, so the estimator will not start.
Example of Variables Needed
Currently, I am creating a function in my node that converts the messages from Gazebo (i.e. position and attitude) into the variables used by our estimator. This seems straightforward and I believe Mark and I have discussed needing to do this in the past; it is now becoming clear to me how that conversation applies. Once I get this to work I will learn how to create/import new drone models and sensors.
Last week I discussed creating an executable C++ node that publishes values from QuadcopterLogic to a specific ROS topic. This week I continued to progress towards my goal and gained further knowledge on how the script should look. Initially, I believed that the script needed to define the same functions as a sample node in the RotorS package labeled lee_position_controller_node. Although the name implies that it was simply a position controller, it advertises values to the ROS topic I was looking for. Since it seemed to publish to the topic I was focused on, I suspected that some of the files the position controller imported were from the Gazebo library, so I wanted to understand what files I had to import into my node to communicate with Gazebo. After investigating the files that were imported, I concluded that these were simply more of the RotorS logic and there was only one file that was necessary to import into my script. This makes it easier to implement our lab’s state estimator since I will not need to change any variable names.
I also looked at the script that Mighty created as an example of how the lines of code should look to publish the motor speed topic. I proceeded to run the system using my code, but the model did not hover as expected. I learned this was caused from not running quad_rates_mocap_control to set a desired position value.
I feel confident that I am close to getting the system to work properly using our lab code. The biggest obstacle is my lack of experience with C++. I have enrolled in a free edx course for C++ that I use to understand syntax errors when online forums do not help. In the coming days, I hope to have a working example of our code working with the RotorS system. My next goal is to understand how to create/import new drone models for the simulator so I can create the quadcopters we need to analyze. I also want to look at how sensors can be used in Gazebo and start working with Junseok to look at how we want use Gazebo for testing.
Last week I noted that I should be able to create my own executable node that publishes commands to the motor_speeds topic handled by Gazebo. My plan this week was to make changes to the proper CMakelists and package files and create an executable node that publishes the “PropellerSpeedsFromThrust” values from our QuadcopterLogic.cpp file to said topic . I have made changes to the appropriate CMakelists and package files to import our logic folder, and I have started creating an executable node using the examples provided in the RotorS file system.
Section of Focus in QuadcopterLogic
The challenge for me moving forward is creating a c++ file that properly imports the value I want from QuadcopterLogic and publishes it to the topic. Once I successfully create the file, I will work towards implementing our state estimator.
I am still moving towards my objective to find that best avenue to simulate a quadcopter with visual hardware. Last week, I had trouble finding the appropriate method to implement out lab code into RotorS. It became difficult to find exactly how the system ran their own logic controller, since the package had so many files. This week I was able to obtain literature that described RotorS in-depth and explained how to use a custom controller. RotorS has two ways to integrate a controller. The default method is to have nodes subscribe to odometry and trajectory messages, and use parameters from a PID controller to send motor commands to the simulator. The method that allows me to implement our lab code details that I would need to import the messages from sensors and publish the thrust that comes from our mixer to a motor topic that Gazebo will read.
Next week, I will modify the CMakelists of the folder that contains the nodes needed for this process to work. Once I properly implement the code, I can refocus my efforts into understanding how to properly create new sensors, like lidar, into Gazebo.