Question on distances array in OBSTACLE_DISTANCE

Todays update… I have published the data as [300, UINT16_MAX,UINT16_MAX…] and lowered it to [100,UINT16_MAX,UINT16_MAX] in steps of 50 cm within the span of 8 secs. But still drone is going in all directions and not going in north direction.

Object distance msg setting:
Distances = [Data1 , others = UINT16_MAX]
Data1 = 300 – 100 in steps of 50 cm within 8 secs
Increment = 3
angle_offset = -1.5
Frame = 12

  1. I think, flight controller (PX4) not considering the frame FRAME_BODY_FRD sent by me and taking the global value of MAV_FRAME_GLOBAL.

  2. As you are saying drone should not fly in other direction when I am publishing UINT16_MAX value, that is also not happening.

Is there any other setting I need to do on flight controller side.

Do you publish your data directly on the mavlink topic, or do you publish a ROS topic and then let Mavros send the mavlink message?

I am not using ROS right now. I am just sending the OBSTACLE_DISTANCE message using python with the help of pymavlink files. I have generated the files for mavlink version 2 from common.xml file which is in dilects of V20.

Log files: I have created my profile on github and posted logs of drone testing.
Collision prevention message is present in it.

link: https://github.com/badave007/Autonomous_Drone/blob/master/log_110_2020-1-20-14-43-42.ulg

I have done firmware update from 9.2 to 10.1. I will check the results and update here.

@baumanta , After updating the firmware , I have done the setting of collision avoidance as below image:
image
And Obstacle distance message settings as :

distances = [data1= 500 to 200 , others = UINT16_MAX]
increment = 3
angle_offset = -1.5
frame = FRAME_BODY_FRD

expected result: Drone should fly only in forward directions and block other directions

actual result: It is working somewhat expected but it should be flying in front direction but it is flying in north direction.

So drone is blocking other directions but the frame argument is not considered.
please provide your insight what might be going wrong.

Hello @baumanta,

I have done the Lidar based collision prevention using ROS and MAVROS. Also I have used the mavros-extras plugins, Its working fine. Now I want to use AWR1642 radar sensor for that I created the node which receives the values from sensor but I am bit confused about filling the array of OBSTACLE_DISTANCE message, because radar sensor provides range scan data at each time stamp. Can you please help on this? e.g.How I should tell the PX4 that 1 object is on 100cm at 20 degree and other at 200 cm at 10 degree.
I am using only 1 sensor in front direction.

Thank you in advance.

Please see the first answer in this post: Question on distances array in OBSTACLE_DISTANCE

you just need to fill the array correctly with you sensor data, respecting resolution, orientation and fov of your sensor

Hello @baumanta,

Yes i have checked that and I am thankful to you, because of that answer I have implemented Lidar based collision prevention. There are few things which are not clear to me.
The obstacle distance plugin does not set the angle_offset. It was not an issue while using Lidar so much but now when I am using radar sensor, should I edit it?

@ashutosh_badave I’m not sure what is still unclear here, as the example I posted already contains how to set the angular offset. But here another example with one sensor with multiple data valued (like range sensor would report)

1 Like

@baumanta Thank you very much for the detailed answer. I did understand it from first reply. My question was related to ROS plugin code and not about what message should be send. I guess I have not asked it correctly. sorry for that.

Below is the re frame version and what I did for that.

I was unclear about angle_offset, as I am publishing Laser_scan message on /mavros/obstacle/send topic to Obstacle_distance plugin, Laser_scan message does not have provision to send angle_offset and this plugin does not set angle_offset. Because of that on flight controller side, I was receiving angle_offset as 0 every time.
But now I have edited that code, so it can consider angle_min from Laser_scan message as angle_offset for flight controller.

obstacle.angle_offset = static_cast<float_t>(req->angle_min);

Hi baumanta,

My current project is using a multicopter with 4 distance sensors for a wall following. I am currently using gazebo and mavros for my project. I created an iris model attached with 4 distance sensors and I want to publish all 4 distance sensors data to 4 ROS topics (for example: /mavros/distance_sensor/lidar0, /mavros/distance_sensor/lidar1 and etc).

However, when I am trying to use rostopic echo to check whether my data was publised to 4 ROS topics, only the “/mavros/distance_sensor/lidar0” shows the data that I wanted.

Other topics (/mavros/distance_sensor/lidar1 and etc) show me a warning which is “WARNING: no messages received and simulated is active. Is /clock being published?”
I believe that means my other distance_sensors data were not published to the topics that I wanted. Meanwhile, I also checked using Qgroundcontrol mavlink inspector and there is only 1 distance sensor data being output on the inspector.

I would appreciate some help from you if you know how to resolve this problem.

Regards,
ziimiin14

@ziimiin14 This seems to be a gazebo problem. Check again your model file and the plugin for the distance sensor.

Hi @baumanta,

Thank you for the quick reply!

I have been using this lidar model ->https://github.com/PX4/sitl_gazebo/blob/0823f5e006011d36858c2dd39881874c1edac10b/models/lidar/model.sdf which is the default built-in px4 lidar model. I do look through the lidar-plugin cpp file but that is too complicated for me and I am not sure where to edit.

Meanwhile the bottom attached is my cutomized iris sdf model, and it shows how i defined the lidar position and how it attached to the iris quadcopter.

<sdf version='1.6'>

    <model name='my_vehicle'>
        <include>
            <uri>model://iris</uri>
        </include>

        <!--forward-facing lidar-->
        <include>
            <uri>model://lidar</uri>
            <pose>0.1 0.05 0.06 0 -1.57079633 0</pose>
            <name>lidar0</name>
        </include>

        <joint name="lidar0_joint" type="fixed">
            <parent>iris::base_link</parent>
            <child>lidar0::link</child>
        </joint>

        <!--forward1-facing lidar-->
        <include>
            <uri>model://lidar</uri>
            <pose>0.1 0.05 -0.06 0 -1.57079633 0</pose>
            <name>lidar1</name>
        </include>

        <joint name="lidar1_joint" type="fixed">
            <parent>iris::base_link</parent>
            <child>lidar1::link</child>
        </joint>


        <!--forward2-facing lidar-->
        <include>
            <uri>model://lidar</uri>
            <pose>0.1 -0.05 0.06 0 -1.57079633 0</pose>
            <name>lidar2</name>
        </include>

        <joint name="lidar2_joint" type="fixed">
            <parent>iris::base_link</parent>
            <child>lidar2::link</child>
        </joint>

        <!--forward3-facing lidar-->
        <include>
            <uri>model://lidar</uri>
            <pose>0.1 -0.05 -0.06 0 -1.57079633 0</pose>
            <name>lidar3</name>
        </include>

        <joint name="lidar3_joint" type="fixed">
            <parent>iris::base_link</parent>
            <child>lidar3::link</child>
        </joint>
    </model>
</sdf>

Please let me know if you can see the possible existing problem that leads to my issue.

Regards,
ziimiin14

Hii!

This gives a good overview of things we should while use a range finder sensor.

I’m using a Velodyne Puck lite 360 degree lidar sensor. It gives a 3D scan points in ROS as input.
Can you please explain what should be the changes or format in order to do collision prevention with the sensor mentioned above.

Collision prevention is only implemented for in 2D. So you could convert your 3D data in a 1D array by just taking into account e.g. only the points at -20deg to +20deg elevation and taking the minimum distance at each azimuth angle. You would obviously be throwing away a lot of data but the collision prevention algorithm cannot handle elevation data. Another option is to look into PX4 Avoidance (GitHub - PX4/PX4-Avoidance: PX4 avoidance ROS node for obstacle detection and avoidance.) which does not stop at obstacles but avoid them. This algorithm works with 3D data but is a lot more compute intensive (it needs to be run on a companion computer). Also the project is not maintained anymore, so it will be some effort to get it to work again.

Thanks!
I already converted the 3D data into 2D. But Obstacle_message is not displayed by QGC. I’m sending some dummy data through /mavros/cmd/command with command : 330 .
Command_ack confirms that it is recieving the data but with result: 4 while broadcasting: True.
Can you explain why?

And I already setup comapnion computer but don’t have any node for velodyne data to give as input in avoidance node.
Suggest me someone or something with I can take help with?

hello @baumanta

i tried obstacle avoidance with answer from here
https://discuss.px4.io/t/question-on-distances-array-in-obstacle-distance/12911/2?u=suryaprakash_lokula

and i could find proximity data in the mission planner but the drone does not get effected by the obstacle ahead in (front)

below is the code which i tried


from pymavlink import mavutil
import time
import RPi.GPIO as GPIO 
from threading import Thread
from dronekit import connect, VehicleMode, LocationGlobalRelative
from pymavlink.dialects.v20 import ardupilotmega as mavlink2
import math


latt = "17.XXXXXX"
long = "78.XXXXXX"
alt = 1.5

vehicle = connect("/dev/ttyAMA0", wait_ready=True, baud=921600)
vehicle.wait_ready(True, raise_exception=False)

vehicle.parameters['LAND_SPEED'] = 25 ##Descent speed of 30cm/s
vehicle.parameters["WPNAV_SPEED"]=80
# vehicle.parameters["PRX_TYPE"]=2
# vehicle.parameters["OA_TYPE"]=2
# vehicle.parameters["OA_LOOKAHEAD"]=2
# vehicle.parameters["OA_BR_TYPE"]=1
# vehicle.parameters["OA_DB_EXPIRE"]=10
# vehicle.parameters["OA_DB_QUEUE_SIZE"]=100
# vehicle.parameters["OA_DB_OUTPUT"]=1
print("connected")
GPIO.setwarnings(False) 
GPIO.setmode(GPIO.BCM) 

obstacledist = 70
vehicleheading = 0

distance = 1
distancespeed = 1

FRONTTRIG = 4
FRONTECHO = 17

sonardist ={}

front = 300
UNIT16_MAX = 251


GPIO.setup(FRONTTRIG,GPIO.OUT) 
GPIO.setup(FRONTECHO,GPIO.IN)



def send_distance_message():
   
    abc = [int(front),  UNIT16_MAX,UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, 
    UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, 
    UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, 
    UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, 
    UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, 
    UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX,
     UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX, UNIT16_MAX]

    msg = mavlink2.MAVLink_obstacle_distance_message(
        0, #time
        1, #sensor type
        abc, # abc is usually the array of 72 elements
        15, #angular width
        10, #min distance
        250, #max distance
        10,#https://mavlink.io/en/messages/common.html#OBSTACLE_DISTANCE
        -40,
        12
        )
    time.sleep(0.3)
    if vehicle.location.global_relative_frame.alt  >= 1.0:
        vehicle.send_mavlink(msg)
        print(msg)
        vehicle.flush()




def frontsonar():
    global front
    while True:
        dist1=251
        GPIO.output(FRONTTRIG, True) 
        time.sleep(0.00001) 
        GPIO.output(FRONTTRIG, False) 
        echo_state=0 
        
        while echo_state == 0: 
            echo_state = GPIO.input(FRONTECHO) 
            pulse_start = time.time() 
        while GPIO.input(FRONTECHO)==1: 
            pulse_end = time.time() 
        pulse_duration = pulse_end - pulse_start 
        distance = pulse_duration * 17150 
        distance = round(distance, 2) 
        
        if(distance<250 and distance>5): #To filter out junk values 
            front=distance
                            
        else:
            front = dist1
        #print("front",front)
        time.sleep(0.1)

        
Thread(target = frontsonar).start()

def get_distance_meters(targetLocation,currentLocation):
    dLat=targetLocation.lat - currentLocation.lat
    dLon=targetLocation.lon - currentLocation.lon

    return math.sqrt((dLon*dLon)+(dLat*dLat))*1.113195e5



def arm_and_takeoff(aTargetAltitude):
        
        print("Arming motors")
        # Copter should arm in GUIDED mode
        vehicle.mode = VehicleMode("GUIDED")
        vehicle.armed = True

        # Confirm vehicle armed before attempting to take off
        while not vehicle.armed:
            print(" Waiting for arming...")
            time.sleep(1)

        print("Taking off!")
        vehicle.simple_takeoff(aTargetAltitude)  # Take off to target altitude
        
        while True:
            print(" Altitude: ", vehicle.location.global_relative_frame.alt)
            # Break and return from function just below target altitude.
            if vehicle.location.global_relative_frame.alt >= aTargetAltitude * 0.95:
                print("Reached target altitude")
                break
            time.sleep(1)
        
print(vehicle.battery.voltage)
arm_and_takeoff(alt)
vehicle.airspeed = 5
print("Take off complete")

# Hover for 10 seconds
time.sleep(3)
print("Vehicle going to the location")
point1 = LocationGlobalRelative(float(latt),float(long), alt)
distanceToTargetLocation = get_distance_meters(point1,vehicle.location.global_relative_frame)
vehicle.simple_goto(point1)
while True:
    send_distance_message()
    currentDistance = get_distance_meters(point1,vehicle.location.global_relative_frame)
    print("current distance: ", currentDistance,distanceToTargetLocation*.02,currentDistance<distanceToTargetLocation*.02)
    if currentDistance<distanceToTargetLocation*.02:
        print("Reached target location.")
        time.sleep(2)
        break
    time.sleep(1)
vehicle.mode = VehicleMode("LAND")
while True:
    print(" Altitude: ", vehicle.location.global_relative_frame.alt)
    # Break and return from function just below target altitude.
    if vehicle.location.global_relative_frame.alt <=0:
        print("Reached ground")
        vehicle.close() 
        break
    time.sleep(1)

i am using ultrasonic sensor at front , am i missing anything in the above code
and my aim is to perform bendyruler obstacle avoidance with px4(version: 4.1),raspberrypi,ultrasonic sensors

Thanks in advance.

@baumanta @ashutosh_badave @chipper
could you help me with this topic please

ArduPilot avoidance and PX4 avoidance aren’t interchangeable.
If you’re intending to use ArduPilot on your flight controller (you currently are), best to ask at discuss.ardupilot.org

Hello @baumanta,

I was able to get this message to work on my drone, however, we are also incorporating an ark flow sensor which creates an instance for a distance sensor. From my understanding the OBSTACLE_DISTANCE message also created a distance sensor instance. Is this correct? And is there anyway to nullify this instance so that it does not interfere with the position control by the flow sensor? The only thing that I can think of is to run a “stop” command in the shell to stop that instance.

Thank you for your time.