Garmin Lidar Lite v3 sensor characterization

The new Lidar Lite V3 sensor may be useful for height control of a quadcopter. We want to integrate one of this sensors into our new Asctec Firefly quadcopter for safe indoor flight. The first step of the integration is a complete sensor characterization in order to determine its parameters.

Experimental setup

Materials:

  • Arduino UNO
  • Electrolytic Capacitor with the value stated on the manual (or with more capacity).
  • Lidar Lite v3
  • Bosch professional GLM 50 C laser measure device (as ground truth)
  • Ruler on the ground

 

We connected the Lidar Lite v3 to the Arduino UNO using the example configuration found in the manual, we then fixed everything to a board for convenient manipulation. In the software side, we used as reference the example found in the Arduino Library for the Lidar Lite V3 provided by Garmin, we tested that everything was working with our configuration and finally we integrated this code with ROS Serial in order to be able to conveniently process the information in ROS. The final code used in the Arduino with a small tutorial for using with ROS can be found in our Github Repository: TODO!.

A ruler was attached to the ground which allows us to measure distances from 0 to 4 meters in our laboratory. The board with the laser was fixed at position 0 of the ruler.

Note: The base of the Lidar Lite V3 is the base distance reference for all the measurements provided by the laser.

We used for testing another board with a black diffuse material since it gives worse performance than a clear white paper. This board was moved from the maximum distance of the ruler (4m) until the closest distance possible to the laser in intervals of 10 centimeters, for each distance the board was situated perpendicular to the laser and 1000 measurements were obtained for each distance. We developed for this experiment a live histogram tool in ROS (TODO) which connect to the Laser distance topic and then creates a histogram with the data and provides as well the mean value and variance. Additional measurement every 5 centimeters were taken from 0 to 1.5m due to some unexpected non linear effects found on the first pass. The ground truth of the distance was measured using the high precision Bosch professional GLM 50 C device.

The results obtained can be seen in the following graph:

 

A zoom of the problematic area (distances between 0 and 1.5m):

Relative error (as a percentage of the measured distance):

Histogram at a distance of 3.95m:

Histogram at a distance of 1m:

Histogram at a distance of 50cm:

Histogram at a distance of 30cm:

Histogram at a distance of 10cm:

TODO: Result analysis

Potential Field Navigation: Obstacle definition in Python using a Gaussian Field

First let’s start with some basic assumptions.  We define a 2D environment of size x_max, y_max. We can easily represent this environment in Python as a Grid of size (x_max, y_max). The resolution of this Grid is not important for now, since later it is possible to convert Grid values to meters for example.  We want to simulate an obstacle in a particular position of this environment, let’s say that the obstacle position will be p_obs = (x_obs, y_obs) and that the complete shape of this obstacle can be fitted inside a circle of radius = 10 grid units.

One way of representing this obstacle for potential field navigation is by using a Gaussian repulsor field in the center of the obstacle. The following code creates a Grid and then calculates the potential field for the given obstacle position.

[code language=”python” wraplines=”true”]
def gaussian_obstacle(X,Y, x_obs, y_obs, size_robot, size_obstacle):
#We extend the size of the obstacle with the size of the robot (border expansion)
ext_size = size_robot + size_obstacle
sigma_x = (ext_size/2)/2.3548
sigma_y = (ext_size/2)/2.3548
theta = 0
A = 100 #Weight of the Gaussian
Z = zeros_like(X)
a = cos(theta)**2/2/sigma_x**2 + sin(theta)**2/2/sigma_y**2
b = -sin(2*theta)/4/sigma_x**2 + sin(2*theta)/4/sigma_y**2
c = sin(theta)**2/2/sigma_x**2 + cos(theta)**2/2/sigma_y**2
Z[:] = Z[:]+A*exp( – (a*(X-x_obs)**2 + 2*b*(X-x_obs)*(Y-y_obs) + c*(Y-y_obs)**2))
return Z

Z = gaussian_obstacle(X, Y, 50, 50, 10, 10)
[/code]

gaussian obstacle

We then create a gradient field based on the scalar field:

[code language=”python” wraplines=”true”]
def calculate_vector_field(Z):
U, V = gradient(Z,1,1)
U = -U
V = -V
return U, V

U, V = calculate_vector_field(Z)
[/code]

Which will produce this vectors centered in the position of the obstacle

gaussian obstacle vectors

 

Finally to obtain a vector reference (velocity) for a robot that is currently at position (41,41), you may use the following function:

def get_velocity_command(U, V, x_robot, y_robot):
return U[x_robot,y_robot], V[x_robot,y_robot]

Vx_robot, Vy_robot = get_velocity_command(U, V, 41, 41)

If you have many moving obstacles and a big environment it may be too computationally expensive to do the calculation for the whole Grid, a possible solution is to do the calculation only in the surrounding area of the robot and obtain only the reference vector for the current position of the robot:

[code language=”python” wraplines=”true”]
p_robot = (rob_x, rob_y)
#We create a minimal grid around the position of our robot
X, Y = mgrid[(rob_x-1):(rob_x+1)+1,(rob_y-1):(rob_y+1)+1]
[/code]

Complete code with plots using Mayavi from enthought.

[code language=”python” wraplines=”true”]
from pylab import *
import matplotlib.pyplot as plt
from mayavi import mlab

x_min = 0
y_min = 0
x_max = 100
y_max = 100
X, Y = mgrid[ x_min:x_max+1:1, y_min: y_max+1:1]

def gaussian_obstacle(X,Y, x_obs, y_obs, size_robot, size_obstacle):
#We extend the size of the obstacle with the size of the robot (border expansion)
ext_size = size_robot + size_obstacle
sigma_x = (ext_size/2)/2.3548
sigma_y = (ext_size/2)/2.3548
theta = 0
A = 100 #Weight of the Gaussian
Z = zeros_like(X)
a = cos(theta)**2/2/sigma_x**2 + sin(theta)**2/2/sigma_y**2
b = -sin(2*theta)/4/sigma_x**2 + sin(2*theta)/4/sigma_y**2
c = sin(theta)**2/2/sigma_x**2 + cos(theta)**2/2/sigma_y**2
Z[:] = Z[:]+A*exp( – (a*(X-x_obs)**2 + 2*b*(X-x_obs)*(Y-y_obs) + c*(Y-y_obs)**2))
return Z

def calculate_vector_field(Z):
U, V = gradient(Z,1,1)
U = -U
V = -V
return U, V

Z = gaussian_obstacle(X, Y, 50, 50, 10, 10)
U, V = calculate_vector_field(Z)

def get_velocity_command(U, V, x_robot, y_robot):
return U[x_robot,y_robot], V[x_robot,y_robot]

Vx_robot, Vy_robot = get_velocity_command(U, V, 40, 40)

# Plot
mlab.figure(size=(800, 600))
mlab.quiver3d(X, Y, zeros_like(X), U, V,zeros_like(U))
mlab.mesh(X, Y, Z)
mlab.show()

[/code]

Robotino Vrep scene with twist message controller (ROS)

The robotic platform Robotino is a nice omnidirectional Robot manufactured by the company Festo. It was surprising for me to find out that the Robot Simulator VREP doesn’t have a working model of this robot,  even though there exist an opensource model of this robot for the simulator Gazebo.

Just like I did before for a Quadcopter, now I implemented a model of the Robotino for Vrep based on the URDF model from Gazebo. The simulation of the omnidirectional wheels was based on the Kuka Youbot available in Vrep. Additionally I programmed a control script using velocity Twist reference messages from ROS, so just like the quadrotor it is possible to control this robot from ROS using a Joystick (or your custom Node).

 

VrepRobotino

Robotino Model in Vrep

This is the control script that I programmed in the Robotino Model:

[code language=”python” collapse=”true” wraplines=”true”]
— DO NOT WRITE CODE OUTSIDE OF THE if-then-end SECTIONS BELOW!! (unless the code is a function definition)
if (sim_call_type==sim_childscriptcall_initialization) then
——– START OF ROS INITIALIZATION ——————————–
— Check if the required plugin is there (libv_repExtRos.so or libv_repExtRos.dylib):
local moduleName=0
local moduleVersion=0
local index=0
local pluginNotFound=true
while moduleName do
moduleName,moduleVersion=simGetModuleName(index)
if (moduleName==’Ros’) then
pluginNotFound=false
end
index=index+1
end
if (pluginNotFound) then
— Display an error message if the plugin was not found:
simDisplayDialog(‘Error’,’ROS plugin was not found.&&nSimulation will not run properly’,sim_dlgstyle_ok,false,nil,{0.8,0,0,0,0,0},{0.5,0,0,1,1,1})
else
— Enable topic subscription:
simExtROS_enableSubscriber("/robotino_cmd_twist",1,simros_strmcmd_set_twist_command,-1,-1,’Command_Twist’)
end

——– END OF ROS INITIALIZATION ——————————–
— Put some initialization code here

— Make sure we have version 2.4.12 or above (the omni-wheels are not supported otherwise)
v=simGetIntegerParameter(sim_intparam_program_version)
if (v<20412) then
simDisplayDialog(‘Warning’,’The YouBot model is only fully supported from V-REP version 2.4.12 and above.&&nThis simulation will not run as expected!’,sim_dlgstyle_ok,false,”,nil,{0.8,0,0,0,0,0})
end

wheelJoints={-1,-1,-1}
wheelJoints[1]=simGetObjectHandle(‘wheel0_joint’)
wheelJoints[2]=simGetObjectHandle(‘wheel1_joint’)
wheelJoints[3]=simGetObjectHandle(‘wheel2_joint’)
robotino_handle = simGetObjectHandle(‘robotino’)

— Make sure you read the section on "Accessing general-type objects programmatically"
— For instance, if you wish to retrieve the handle of a scene object, use following instruction:

— handle=simGetObjectHandle(‘sceneObjectName’)

— Above instruction retrieves the handle of ‘sceneObjectName’ if this script’s name has no ‘#’ in it

— If this script’s name contains a ‘#’ (e.g. ‘someName#4’), then above instruction retrieves the handle of object ‘sceneObjectName#4’
— This mechanism of handle retrieval is very convenient, since you don’t need to adjust any code when a model is duplicated!
— So if the script’s name (or rather the name of the object associated with this script) is:

— ‘someName’, then the handle of ‘sceneObjectName’ is retrieved
— ‘someName#0’, then the handle of ‘sceneObjectName#0’ is retrieved
— ‘someName#1’, then the handle of ‘sceneObjectName#1’ is retrieved
— …

— If you always want to retrieve the same object’s handle, no matter what, specify its full name, including a ‘#’:

— handle=simGetObjectHandle(‘sceneObjectName#’) always retrieves the handle of object ‘sceneObjectName’
— handle=simGetObjectHandle(‘sceneObjectName#0’) always retrieves the handle of object ‘sceneObjectName#0’
— handle=simGetObjectHandle(‘sceneObjectName#1’) always retrieves the handle of object ‘sceneObjectName#1’
— …

— Refer also to simGetCollisionhandle, simGetDistanceHandle, simGetIkGroupHandle, etc.

— Following 2 instructions might also be useful: simGetNameSuffix and simSetNameSuffix
old_velx = 0
old_vely = 0
old_vel_angz = 0
acc_x = 0
acc_y = 0
acc_omega = 0

end

if (sim_call_type==sim_childscriptcall_actuation) then

— Put your main ACTUATION code here
— From CMDVEL
— Signals from ROS
local packedData=simGetStringSignal(‘Command_Twist’)
if (packedData) then
local ref_twist=simUnpackFloats(packedData)
— Process the twist data
— X and Y velocities (related to the heading of the robotino)
ref_velx = ref_twist[1]*0.18 –reference values between 0 and 1, Max Vel = 0.18 m/s
ref_vely = ref_twist[2]*0.18

— Angular velocity in Z (this changes the heading of the robotino)
ref_angz = ref_twist[6]
end

— Robotino Model (Open Loop control)
omega = ref_angz
vx = ref_velx
vy = ref_vely
— Sets the distance from robot center to wheel center.
rb = 0.13
— Sets the radius of the wheels.
rw = 0.040
— Sets the gear.
gear = 0.11 –revisar este numero
— Projection matrix
v0 = { -0.5 * math.sqrt(3), 0.5 }
v1 = { 0.0 , -1.0 }
v2 = { 0.5 * math.sqrt( 3.0 ), 0.5 }
— Scale omega with the radius of the robot
vOmegaScaled = rb * omega
–Convert from m/s to RPM
k = 60.0 * gear / ( 2.0 * math.pi * rw )
–Compute the desired velocity
m1 = (v0[1] * vx + v0[2] * vy + vOmegaScaled ) * k
m2 = (v1[1] * vx + v1[2] * vy + vOmegaScaled ) * k
m3 = (v2[1] * vx + v2[2] * vy + vOmegaScaled ) * k

— Transformation to obtain velocities related to the quadrotor heading
————————————————————————–
— Orientation of the quadcopter related to the World
euler_robotino = simGetObjectOrientation(robotino_handle,-1)
— We create a Transformation Matrix from this orientation
pos_robotino=simGetObjectPosition(robotino_handle,-1)
m_heading = simBuildMatrix(pos_robotino,euler_robotino)

— We create a Transformation Matrix for converting the global referenced velocities
— to a reference frame based on the heading of the quadrotor
global_pos = {0,0,0}
m_global = simBuildMatrix(global_pos,euler_robotino)
m = simGetInvertedMatrix(m_global)

vel_global, vel_angz = simGetObjectVelocity(robotino_handle)

vel_local=simMultiplyVector(m,vel_global)

— Velx Control
error_x = ref_velx – vel_local[1]
velxControl = error_x*0.1 +acc_x*0.01 + (vel_local[1]-old_velx)*0.001
old_velx = vel_local[1]
acc_x = error_x+acc_x

— Vely Control
error_y = ref_vely – vel_local[2]
velyControl = error_y*0.1 +acc_y*0.01 + (vel_local[2]-old_vely)*0.001
old_vely = vel_local[2]
acc_y = error_y+acc_y

— Omega Velocity Control
error_omega = ref_angz – vel_angz[3]
rotControl = error_omega*0.05 +acc_omega*0.01 — (vel_local[3]-old_vel_angz)*1.1
old_vel_angz = vel_angz[3]
acc_omega = error_omega+acc_omega

— Robotino Model (Closed Loop control)
— Sets the distance from robot center to wheel center.
rb = 0.13
— Sets the radius of the wheels.
rw = 0.040
— Sets the gear.
gear = 1.0 –revisar este numero
— Projection matrix
v0 = { -0.5 * math.sqrt(3), 0.5 }
v1 = { 0.0 , -1.0 }
v2 = { 0.5 * math.sqrt( 3.0 ), 0.5 }
— Scale omega with the radius of the robot
vOmegaScaled = rb * rotControl
–Convert from m/s to RPM
k = 60.0 * gear / ( 2.0 * math.pi * rw )
–Compute the desired velocity
m1 = (v0[1] * velxControl + v0[2] * velyControl + vOmegaScaled ) * k
m2 = (v1[1] * velxControl + v1[2] * velyControl + vOmegaScaled ) * k
m3 = (v2[1] * velxControl + v2[2] * velyControl + vOmegaScaled ) * k
–m1 = 1000
–m2 = 000
–m3 = -1000
–vel_global, vel_ang = simGetObjectVelocity(robotino_handle)
–print(vel_global[1],vel_global[2],vel_global[3],vel_ang[3])
print(‘Global’,vel_global[1],vel_global[2],vel_global[3],vel_angz[3])
print(‘Ref’,ref_velx,ref_vely,ref_angz)
print(‘Local’,vel_local[1],vel_local[2],vel_angz[3])
print(‘Motors’,m1,m2,m3)

— For example:

— local position=simGetObjectPosition(handle,-1)
— position[1]=position[1]+0.001
— simSetObjectPosition(handle,-1,position)
simSetJointTargetVelocity(wheelJoints[1],m1)
simSetJointTargetVelocity(wheelJoints[2],m2)
simSetJointTargetVelocity(wheelJoints[3],m3)

end

if (sim_call_type==sim_childscriptcall_sensing) then

— Put your main SENSING code here

end

if (sim_call_type==sim_childscriptcall_cleanup) then

— Put some restoration code here

end
[/code]

Here you can download the model. Any feedback will be greatly appreciated.

Download Robotino model

Vrep quadrotor control script using Twist messages from ROS

Vrep has a very nice quadrotor model, however for my research I needed a controller based on velocity Twist messages obtained from ROS.

 

VrepQuadcopter

Quadcopter simulated in Vrep

I programmed a new LUA control script  for the quadcopter based on the original script. With this new script it is possible to control the quadrotor using Twist messages from ROS. In my particular implementation I connected the generic ROS Joystick node to a simple Node that I programmed (quad_joy_control) which converts the information from the Joystick to a velocity twist message and publishes it in the topic /quad_cmd_twist. I launch the necessary nodes using this launch file:

[code language=”xml”]
<launch>
<node pkg="coop_uv_sim" name="quad_joy_control" type="quad_joy_control"/>

<arg name="joy_config" default="logitech_joy" />
<arg name="joy_dev" default="/dev/input/js0" />

<node pkg="joy" type="joy_node" name="joy_node">
<param name="dev" value="$(arg joy_dev)" />
<param name="deadzone" value="0.1" />
<param name="autorepeat_rate" value="20" />
</node>

</launch>
[/code]

rqtgraphVrepQuad

ROS Nodes Graph

 

To use your own code with this Vrep Quadcopter Model you have to create a Node in ROS that publish a Twist Message in the topic /quad_cmd_twist. If this message is not present the quadcopter won’t move.

This is the LUA script that is running inside the model of the quadcopter in Vrep, just replace the default Quadrotor script in Vrep with this one (Double click on it to select and Copy). You can change the name of the subscribed topic to one that better suit your needs.

[code language=”python” collapse=”true” wraplines=”true”]
if (sim_call_type==sim_childscriptcall_initialization) then
——– START OF ROS INITIALIZATION ——————————–
— Check if the required plugin is there (libv_repExtRos.so or libv_repExtRos.dylib):
local moduleName=0
local moduleVersion=0
local index=0
local pluginNotFound=true
while moduleName do
moduleName,moduleVersion=simGetModuleName(index)
if (moduleName==’Ros’) then
pluginNotFound=false
end
index=index+1
end
if (pluginNotFound) then
— Display an error message if the plugin was not found:
simDisplayDialog(‘Error’,’ROS plugin was not found.&&nSimulation will not run properly’,sim_dlgstyle_ok,false,nil,{0.8,0,0,0,0,0},{0.5,0,0,1,1,1})
else
— Enable topic subscription:
simExtROS_enableSubscriber("/quad_cmd_twist",1,simros_strmcmd_set_twist_command,-1,-1,’Command_Twist’)
end

——– END OF ROS INITIALIZATION ——————————–

— Make sure we have VREP version 2.4.13 or above (the particles are not supported otherwise)
v=simGetIntegerParameter(sim_intparam_program_version)
if (v<20413) then
simDisplayDialog(‘Warning’,’The propeller model is only fully supported from V-REP version 2.4.13 and above.&&nThis simulation will not run as expected!’,sim_dlgstyle_ok,false,”,nil,{0.8,0,0,0,0,0})
end

— Detatch the manipulation sphere:
target_obj = simGetObjectHandle(‘Quadricopter_target’)
simSetObjectParent(target_obj,-1,true)

— I modified the original quuadrotor control to receive Twist commands from ROS, feel free to play with the parameters.

quad_handle = simGetObjectHandle(‘Quadricopter_base’)

particlesAreVisible=simGetScriptSimulationParameter(sim_handle_self,’particlesAreVisible’)
simSetScriptSimulationParameter(sim_handle_tree,’particlesAreVisible’,tostring(particlesAreVisible))
simulateParticles=simGetScriptSimulationParameter(sim_handle_self,’simulateParticles’)
simSetScriptSimulationParameter(sim_handle_tree,’simulateParticles’,tostring(simulateParticles))

propellerScripts={-1,-1,-1,-1}
for i=1,4,1 do
propellerScripts[i]=simGetScriptHandle(‘Quadricopter_propeller_respondable’..i)
end

particlesTargetVelocities={0,0,0,0}

old_velx = 0
old_vely = 0
ref_velx = 0
ref_vely = 0
old_vel_angz = 0

pParam=2
iParam=0.001
dParam=0.001
vParam=-2

cumul=0
lastE=0
pAlphaE=0
pBetaE=0
psp2=0
psp1=0

prevEuler=0

fakeShadow=simGetScriptSimulationParameter(sim_handle_self,’fakeShadow’)
if (fakeShadow) then
shadowCont=simAddDrawingObject(sim_drawing_discpoints+sim_drawing_cyclic+sim_drawing_25percenttransparency+sim_drawing_50percenttransparency+sim_drawing_itemsizes,0.2,0,-1,1)
end

— Prepare 2 floating views with the camera views:
floorCam=simGetObjectHandle(‘Quadricopter_floorCamera’)
frontCam=simGetObjectHandle(‘Quadricopter_frontCamera’)
floorView=simFloatingViewAdd(0.9,0.9,0.2,0.2,0)
frontView=simFloatingViewAdd(0.7,0.9,0.2,0.2,0)
simAdjustView(floorView,floorCam,64)
simAdjustView(frontView,frontCam,64)
end

if (sim_call_type==sim_childscriptcall_cleanup) then
end

if (sim_call_type==sim_childscriptcall_sensing) then
end

if (sim_call_type==sim_childscriptcall_actuation) then
end

if (sim_call_type==sim_childscriptcall_cleanup) then
simRemoveDrawingObject(shadowCont)
simFloatingViewRemove(floorView)
simFloatingViewRemove(frontView)
end

if (sim_call_type==sim_childscriptcall_actuation) then
s=simGetObjectSizeFactor(quad_handle)
pos_quad=simGetObjectPosition(quad_handle,-1)
if (fakeShadow) then
itemData={pos_quad[1],pos_quad[2],0.002,0,0,1,0.2*s}
simAddDrawingObjectItem(shadowCont,itemData)
end

— Quadcopter Global Velocity
vel_quad_global, vel_ang = simGetObjectVelocity(quad_handle)

— Transformation to obtain velocities related to the quadrotor heading
————————————————————————–
— Orientation of the quadcopter related to the World
eulerQuad = simGetObjectOrientation(quad_handle,-1)

— We create a Transformation Matrix centered at the quadrotor and rotated only in Z
eulerHeading = eulerQuad
eulerHeading[1] = 0
eulerHeading[2] = 0
m_heading = simBuildMatrix(pos_quad,eulerHeading)

— We create a Transformation Matrix for converting the global referenced velocities
— to a reference frame based on the heading of the quadrotor
global_pos = {0,0,0}
m_global = simBuildMatrix(global_pos,eulerHeading)
m = simGetInvertedMatrix(m_global)
vel_quad_local=simMultiplyVector(m,vel_quad_global)

— We calculate the attitude of the Quadrotor in the frame based on the heading
m_quad=simGetObjectMatrix(quad_handle,-1)
m_heading_inv = simGetInvertedMatrix(m_heading)
m = simMultiplyMatrices(m_heading_inv,m_quad)
euler = simGetEulerAnglesFromMatrix(m)

— Signals from ROS
local packedData=simGetStringSignal(‘Command_Twist’)
if (packedData) then
local ref_twist=simUnpackFloats(packedData)
— Process the twist data
— X and Y velocities (related to the heading of the quadrotor)
ref_velx = ref_twist[1]
ref_vely = ref_twist[2]

— NOTE: twist.linear.z component its not de velocity in Z axis but a height reference.
— This is just for convenience. Feel free to modify it.
height = 2 + ref_twist[3]

— Angular velocity in Z (this changes the heading of the quadrotor)
ref_angz = ref_twist[6]
end

— Vertical control (from previous controler)
e=(height-pos_quad[3])
cumul=cumul+e
pv=pParam*e
thrust=5.335+pv+iParam*cumul+dParam*(e-lastE)+vel_quad_local[3]*vParam
lastE=e

— Horizontal control
vel_errorx = ref_velx – vel_quad_local[1]
vel_errory = ref_vely – vel_quad_local[2]

— Error in Alpha angle (simple PD controler)
alphaE = euler[1]
alphaCorr=0.25*alphaE+2.1*(alphaE-pAlphaE)

— Error in Beta angle (simple PD controler)
betaE = -euler[2]
betaCorr=-0.25*betaE-2.1*(betaE-pBetaE)
pAlphaE=alphaE
pBetaE=betaE

— We add the Velocity reference controller to the previous attitude control
— also a simple PD controler
alphaCorr=alphaCorr+vel_errory*0.05 + (vel_quad_local[2]-old_vely)*0.05
betaCorr=betaCorr-vel_errorx*0.05 – (vel_quad_local[1]-old_velx)*0.05
old_velx = vel_quad_local[1]
old_vely = vel_quad_local[2]

— Rotational control
vel_angz_error = ref_angz – vel_ang[3]
rotCorr= -vel_angz_error*1.0 – (vel_ang[3]-old_vel_angz)*1.0
old_vel_angz = vel_ang[3]

— Decide the motor velocities:
particlesTargetVelocities[1]=thrust*(1-alphaCorr+betaCorr+rotCorr)
particlesTargetVelocities[2]=thrust*(1-alphaCorr-betaCorr-rotCorr)
particlesTargetVelocities[3]=thrust*(1+alphaCorr-betaCorr+rotCorr)
particlesTargetVelocities[4]=thrust*(1+alphaCorr+betaCorr-rotCorr)

— Move Target Object (Green Sphere in the simulation)
— Just for visualization of the Reference Height assigned to the Quadrotor.
pos_target=simGetObjectPosition(target_obj,-1)
pos_target[1] = pos_quad[1]
pos_target[2] = pos_quad[2]
pos_target[3] = height
simSetObjectPosition(target_obj,-1,pos_target)

— Send the desired motor velocities to the 4 rotors:
for i=1,4,1 do
simSetScriptSimulationParameter(propellerScripts[i],’particleVelocity’,particlesTargetVelocities[i])
end
end
[/code]

If you prefer you can download the model of the quadcopter with the integrated script here: Download Quadcopter Vrep model with Twist control

Developing in ROS Indigo using QtCreator

The following is a guide on how to start using QtCreator in order to build projects in ROS Indigo (Ubuntu 14.04) with the new Catkin Tools.

1) Install Qt Creator:

[code language=”bash”]sudo apt-get install qtcreator[/code]

2) Install the new Catkin Tools

[code language=”bash”]sudo apt-get install python-catkin-tools[/code]

3)  Create a catkin workspace with catkin init. It will be assumed that the workspace is configured in ~/catkin_ws

3.1) Before adding your project to qtcreator it is recommended to first clean your workspace a build everything using Catkin tools

[code language=”bash”]
catkin clean
catkin build
[/code]

4) Start QtCreator from a new terminal with the ROS environment already configured in its .bashrc.

[code language=”bash”]qtcreator[/code]

5) Select the menu File -> “Open File or Project…”, then select ~/catkin_ws/src/YOUR_PACKAGE_NAME/CMakeLists.txt

6) Set the build dir to your catkin workspace location:
~/catkin_ws/build/YOUR_PACKAGE_NAME

7) Press Configure

8) Now in the Menu on the left of QtCreator select Projects -> Build Settings and add the following CMake arguments:

[code language=”bash”]-DCMAKE_INSTALL_PREFIX=~/catkin_ws/install -DCATKIN_DEVEL_PREFIX=~/catkin_ws/devel[/code]

9) Save all an close QtCreator

10) In a new terminal start Qtcreator again
qtcreator

10) Now your project should be available and ready to navigate and build.

I also add some lines to my CMakeLists.txt file for Qtcreator to detected the proper location of my header files:

[code language=”bash”]
##################
# FOR QT CREATOR
##################
FILE(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/YOUR_PACKAGE_NAME/*.hpp)
FILE(GLOB_RECURSE INC_ALL "include/YOUR_PACKAGE_NAME/*.hpp")
FILE(GLOB_RECURSE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)
[/code]

National geographic wallpapers

I have modified a script that I found in the internet and now you can download all the National Geographic Wallpapers from 2008, 2009, 2010 and first half of 2011.

Download this script:

natgeo2008-2011.sh

Then run in linux:

sh natgeo2008-2011.sh

Enjoy!

Becas de Phd e investigación del Gobierno de Suiza

CDBund Logo

 

El gobierno de Suiza está ofreciendo Becas de PhD, Postdoctorado y de investigación para Venezolanos. La fecha límite para aplicar es 31.10.2014. Los requisitos se pueden encontrar en la siguiente página:

http://www.sbfi.admin.ch/themen/01366/01380/02175/02366/index.html?lang=en

 

Oferta de empleo para Ingenieros Electrónicos

Saludos cordiales!

 

Sirva la presente para saludarle y para hacerle llegar la oferta de empleo que estamos ofreciendo a ingenieros electrónicos. Gracias de antemano por distribuirla entre sus conocidos que puedan ser posibles candidatos.

 

Ing. Alexander A. Nuñez Z.

Oferta de empleo

 

Empresa del ramo de la electrónica y la seguridad, busca Ingeniero Electrónico para el desarrollo y fabricación de dispositivos inteligentes.

 

Los requerimientos son:

  • ser recién graduado o estar próximo a graduarse
  • saber manejar y conocer herramientas para el diseño de circuitos impresos y esquemáticos como Altium Designer (no indispensable),
  • saber desarrollar programas usando lenguajes de programación tipo  C y Assembler y
  • ser competente en el manejo y programación de  micro-controladores de la familia microchip.

 

Entre los beneficios se encuentran:

  • aprendizajes en áreas de alta tecnología.
  • excelente ambiente laboral donde se propicia la creatividad, la innovación y el desarrollo.

El lugar de trabajo será en nuestras oficinas de La Urbina en Caracas. Los profesionales que estén interesados pueden enviar su sintesis curricular al correo electrónico gerencia@metalalca.com

Becas FullBright

Fulbright logo

Scholarship Opportunity Alert

Now Accepting Applications

The Fulbright Foreign Student Program is now accepting applications for
scholarships to pursue graduate study in the United States!

Programs by Country

Visit the Fulbright Program’s interactive map on the U.S. Department of
State’s Bureau of Educational and Cultural Affairs website to learn about
the programs offered in your country and how to apply.

Applications are accepted in a variety of fields of study with the
exception of Medicine, Nursing and Dentistry.

The Fulbright Program is sponsored by the U.S. Department of State’s Bureau
of Educational and Cultural Affairs and administered in part by LASPAU:
Academic and Professional Programs of the Americas.

Our mailing address is:
LASPAU: Academic and Professional Programs for the Americas
25 Mount Auburn Street
Cambridge, MA 02138-6095

http://www.iie.org/fulbright

Cupo electrónico Cadivi Cencoex Banco Mercantil

Para poder utilizar el cupo en el 2015 es necesario activar la tarjeta de crédito en Mercantil En Línea. La opción se encuentra en el menú de tarjetas de créditos – servicios adicionales. Me costó bastante encontrar esto, ojalá esta nota le sirva a alguien más.

Update: Ya pude realizar una compra electrónica sin problemas.

Top