README.md 7.64 KB
Newer Older
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
1 2 3 4 5 6
# Semi-Autonomous Drone Pilot

This ROS package is for a semi-autonomous drone pilot for the Parrot Bebop 2 using image processing (OpenCV) and unsupervised machine learning (Clustering).

## Quick Intro

jad's avatar
jad committed
7
This project has many parts,The first one is moving the drone at a constant velocity.
jad's avatar
jad committed
8 9 10
The Second part is built on the first one , is used to perform indoors navigation(hallways, stairs and doors crossing).

For more details, check the documentation file ```repport.pdf```(French Documentation).
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
11

jad's avatar
jad committed
12
## Use This Package
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
13 14
First Clone this repo in your catkin workspace
```
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
15
$ git clone https://gitlab.centralesupelec.fr/obeid_jad/dorne_project.git drone_project
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
16 17 18 19 20
```
Build your workspace
```
$ catkin build
```
jad's avatar
jad committed
21 22 23 24
## Drone Control

In this project we've built a module, that allows you to command the drone velocity.

jad's avatar
jad committed
25
To do this you need to launch the VelLaunch.launch 
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
26 27

```
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
28
$ roslaunch drone_project VelLaunch.launch
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
29
```
jad's avatar
jad committed
30

jad's avatar
jad committed
31
And now you can publish to ```/vel_in_x``` , ``` /vel_in_y``` to command linear x and y respectively,```/vel_in_z``` to command angular z,and finally ```/vel_in_alt``` to command the altitude.
jad's avatar
jad committed
32

jad's avatar
jad committed
33
The frequency of sending data to the drone is equal to 5Hz.
jad's avatar
jad committed
34

jad's avatar
jad committed
35 36 37 38 39 40 41 42
### PID parameters

To change PID parameters, open the corresponding ```compute``` file, like ```compute_x.py``` for the X axis for example,

```python
super(XCommand,self).__init__(P,I,D)
```

jad's avatar
jad committed
43
### Example Moving at constant Velocity:
jad's avatar
jad committed
44
The ``` move_tester.py ``` file is an example of moving with a constant velocity.
jad's avatar
jad committed
45

jad's avatar
jad committed
46
## Using The Interface
jad's avatar
jad committed
47 48 49

### Doors and Hallways

jad's avatar
jad committed
50
To run the indoors navigation modules , you just need to launch the file  ```Sequencer.launch```.
jad's avatar
jad committed
51 52 53 54

```
$ roslaunch drone_project Sequencer.launch
```
jad's avatar
jad committed
55 56 57 58 59
You will get an interface, that will let you choose the mode you want, you can click on Doors, to find opened doors and pass through them, Hallway to launch the autonomous navigation in the Hallways. 

### Stairs 

Be careful, the stairs module is still quite unstable in real-life tests because of the unstability of the odometry measures in stairs but you can test its logic on the unity simulation scene.
jad's avatar
jad committed
60 61 62 63 64 65 66 67 68

to test it, first download the unity simulation scene ```unityProjectStairs.zip```,and unzip it.

After loading the scene,
```
$ roslaunch drone_project SequencerUnity.launch
```
then click ```play``` to run he simulation and select ```stairs``` on the interface.

jad's avatar
jad committed
69

jad's avatar
jad committed
70
## Customize this project
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
71

jad's avatar
jad committed
72
### Nodes
jad's avatar
jad committed
73

jad's avatar
jad committed
74
Each node in this project have a unique name, used to activate it.
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
75

jad's avatar
jad committed
76
They also have the ability to send back confirmation after reaching a target .
Obeid Jad Abdul Rahman's avatar
Obeid Jad Abdul Rahman committed
77

jad's avatar
jad committed
78
Like for example the node responsible of searching for openned doors, it will send a confirmation when a door is detected.
jad's avatar
jad committed
79

jad's avatar
jad committed
80
### Create your sequence
jad's avatar
jad committed
81

jad's avatar
jad committed
82
In this project, you can run your own sequence, the sequence is a python list that has a specific format.
jad's avatar
jad committed
83

jad's avatar
jad committed
84
The Format is the following 
jad's avatar
jad committed
85

jad's avatar
jad committed
86
```python
jad's avatar
jad committed
87 88
new_seq_list = ["mode_name",[["node_1","node_2"],["cond_1","cond_2"]],...]
self.new_seq = Sequencer(new_seq_list)
jad's avatar
jad committed
89
```
jad's avatar
jad committed
90

jad's avatar
jad committed
91 92
Where ```mode_name``` is the string that when we receive on the ```/mode``` topic , the sequence will run.
Where ```node_1``` and ```node_2``` are the names of nodes that will be activated in the phase 1 of this sequence, and ```cond_1``` and ```cond_2``` are the names of nodes confirmations we are waiting for to continue to the next step.
jad's avatar
jad committed
93

jad's avatar
jad committed
94 95 96
### NB: 
Having ```[]``` as condition means always True, and having ```[""]``` means always False. 

jad's avatar
jad committed
97
### Running the sequence 
jad's avatar
jad committed
98

jad's avatar
jad committed
99
To run the sequence, you need to add 2 lines of code to the ```Sequencer.py``` class .
jad's avatar
jad committed
100

jad's avatar
jad committed
101 102
```python
def enter_loop(self,ros_data):
jad's avatar
jad committed
103 104 105
    ####Code
    #if(self.mode == self.new_seq.get_mode()):
        #self.new_seq.seq_fun()
jad's avatar
jad committed
106
```
jad's avatar
jad committed
107
Copy and paste these 2 lines, and after that Uncomment them and change the new_seq to the name of the sequence you've defined.
jad's avatar
jad committed
108

jad's avatar
jad committed
109
And now, whenever the mode is received in the mode topic, the sequence will run.
jad's avatar
jad committed
110

jad's avatar
jad committed
111 112
And to get sure your sequence will be reset after Init,
```python
jad's avatar
jad committed
113 114 115 116 117 118 119 120 121 122 123 124
def read_mode(self,ros_data):
    self.mode = ros_data.data
    if(self.mode == "init"):
        msg = actMsg()
        msg.node_name = "reset"
        msg.activate = True
        self.actv_publisher.publish(msg)
        self.doors_seq = Sequence(self.doors_seq_list)
        self.hallways_seq = Sequence(self.hallway_seq_list)
        #self.new_seq = Sequence(self.new_seq_list)
    else:
        self.loop_pub.publish(3)
jad's avatar
jad committed
125
```
jad's avatar
jad committed
126
Copy the ```self.new_seq = Sequence(self.new_seq_list)``` line , paste it and uncomment int and replace the ```new_seq``` by the name of your sequence.
jad's avatar
jad committed
127

jad's avatar
jad committed
128
### Creating your own node
jad's avatar
jad committed
129

jad's avatar
jad committed
130
You can also create you own node in this project.
jad's avatar
jad committed
131

jad's avatar
jad committed
132 133 134 135 136 137 138 139
To do so , and if you want your node to be able to work properly in the sequencer, you have to inherit from the class ```NodeActivate```
```python
from activation_class import NodeActivate
class myNewNode(NodeActivate)
    def __init__(self):
        super(myNewNode,self).__init__("newNodeName")
        #Your Code
```
jad's avatar
jad committed
140
This means that your node has the name ```newNodeName``` and this is the name that will be used to activate it seperatly if you want(Later).
jad's avatar
jad committed
141

jad's avatar
jad committed
142
and to check if the node is activated or not, the variable ```self.activate``` is true when node activated and false otherwise.
jad's avatar
jad committed
143

jad's avatar
jad committed
144
As mentionned above, the nodes may need to send confirmation after reaching the target, to do so, use the function ```send_conf()```.
jad's avatar
jad committed
145 146 147

```python
self.send_conf()
jad's avatar
jad committed
148 149
```

jad's avatar
jad committed
150
## Use project outside sequencer
jad's avatar
jad committed
151

jad's avatar
jad committed
152
This project can be used obviously outside the sequencer (You can define your own launch file and run the nodes you want).
jad's avatar
jad committed
153

jad's avatar
jad committed
154
But before doing that, there is few things you need to know.
jad's avatar
jad committed
155

jad's avatar
jad committed
156
### Activation
jad's avatar
jad committed
157

jad's avatar
jad committed
158
To activate a node , you have to publish a specific type of message called ```actMsg``` on the topic ```/activations```.
jad's avatar
jad committed
159

jad's avatar
jad committed
160 161 162 163 164 165 166 167 168 169
This message contains 2 fields, a string which is the name of the node you want to activate, the second field is a boolean , which is the activation.

```python
from drone_project.msg import actMsg
import rospy
pub = rospy.Publisher("/activations",actMsg,queue_size=1)
msg = actMsg()
msg.node_name = "nodeToAct" #Name of the node to activate
msg.activate = True #False to deactivate
pub.publish(msg)
jad's avatar
jad committed
170
```
jad's avatar
jad committed
171
### Getting Response
jad's avatar
jad committed
172

jad's avatar
jad committed
173
As mentionned above also, some nodes send confirmation whenever they reach the target. A node doing this will publish its name to the topic ```/return_resp```.
jad's avatar
jad committed
174

jad's avatar
jad committed
175
## Some Useful nodes
jad's avatar
jad committed
176

jad's avatar
jad committed
177 178
### Distance Estimation using camera
This project contains a node able to estimate distances of moving objects using dense optical flow with the "Gunnar Farneback" algorithm.
jad's avatar
jad committed
179

jad's avatar
jad committed
180
```nodeName = checkDoors```
jad's avatar
jad committed
181

jad's avatar
jad committed
182
To use this module you can just run the ```testDenseOpticalFlow.py``` node and activate it.
jad's avatar
jad committed
183

jad's avatar
jad committed
184 185 186 187 188
To view the histogram showing distances, run the rqt_image_view and choose the topic ```/image_graph```
```
$ rqt_image_view
```
Whenever an opened door is detected, this node will publish to the ```/return_resp``` Topic.
jad's avatar
jad committed
189

jad's avatar
jad committed
190
### Vanishing point detection
jad's avatar
jad committed
191

jad's avatar
jad committed
192
This project contains a node able to detect the vanishing point in a Hallway using DBSCAN clustering algorithm.
jad's avatar
jad committed
193

jad's avatar
jad committed
194
```nodeName = detectVanish```
jad's avatar
jad committed
195

jad's avatar
jad committed
196
To use this you need to run the ```image_proc.py``` node and activate it.
jad's avatar
jad committed
197

jad's avatar
jad committed
198
This node does not publish on ```/return_resp``` but it will publish the x of this point to the topic ```/centroids```.
jad's avatar
jad committed
199

jad's avatar
jad committed
200
### Turn to a specified angle
jad's avatar
jad committed
201

jad's avatar
jad committed
202
This project contains a node able to turn the drone to a specific angle.
jad's avatar
jad committed
203

jad's avatar
jad committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
```nodeName = turnAng```

To use this you need to import the ```TurnAngClass``` class and do like the following exemple :
```python
#!/usr/bin/env python
from TurnAngClass import TurnDrone
      
def main(args):
    rospy.init_node('TurnDrone', anonymous=True)
    sc = TurnDrone(90) ## the angle you want .
    #rospy.init_node('send_command', anonymous=True)
    rospy.spin()
if __name__ == '__main__':
    main(sys.argv)
```
Whenever the turn is done, this node will publish to the ```/return_resp``` Topic.