-
Notifications
You must be signed in to change notification settings - Fork 1
Simulation
The modular robot system is simulated using the V-REP simulator, this page describes how the robot is built inside the simulation, how it is controlled and which parameters are received from Java to test the robot. For a description on how the simulated environments are built see Simulated Environment.
#Module
The basic module can be seen in the following figure:
The basic module is composed of two parts which are built using basic shapes found in the simulator, the north part (modNorth) and the south part (modSouth), both parts are symmetrical and are joined together by an actuated rotational joint element. The modNorth part acts as the base part of the module, this can be seen in the model hierarchy in the left panel of the simulator.
The module parts do not posses a way to automatically attach to other modules but connections are simulated using force sensors which act as rigid mechanical joints. Force sensors have the advantage of being capable of registering force and torque information and can "break" if forces or torques go above a prespecified threshold which makes them useful for future tests. Following the original module prototype force sensors are only placed in two opposite faces as indicated by the picture and only chains of modules can be formed.
Each module possesses a set of 6 proximity sensors, as simulated IR sensors, which point in the 6 directions of the 6 planar faces of the module.
The module building process was based on the first tutorial of the V-REP [manual] (http://www.coppeliarobotics.com/helpFiles/en/bubbleRobTutorial.htm) and more in information about how to build robots in V-REP can be found there.
#Java Messages and Parameters
The parameters needed to define the robot morphology and the environment for testing in simulation are sent from the Java program by using the remoteAPI functions that come with V-REP. For this to work the continuous remoteAPI server must be enabled in V-REP (it is enabled by default but it is better to check the remoteApiConnections.txt inside the simulator files).
Messages from Java come encoded in a String format signal and have specific identifiers, for example the message identified by NumberandOri
is decoded by using the following function:
data = simGetStringSignal("NumberandOri")
Depending on how it was encoded in the Java side the signal the message can contain either one value or an array of values, for example the NumberandOri
message contains an array with the number of modules to use in the simulation, their orientation, and the max time allowed for the simulation, and must be unpacked:
data = simUnpackInts(data)
robotCount = data[1]-1
maxTime = data[2]
--print(robotCount)
for i=1,robotCount+1,1 do
ori[i] = data[i+2]
--print(ori[i])
end
There are four signals coming and going from the InitControl script: NumberandOri
which was described earlier, Maze
which contains the information about the environment, finished
which signals that the simulation has met one of the termination conditions, and Position
which communicates the Java side the results of the simulation.
#Control Script
Each robot model or element can have its own script on V-REP, in the case of the basic module the control script is attached to the modnorth part as in the following picture:
By double clicking the script icon a new window is opened in which the script controlling the module can be modified. The control scripts are witten in the LUA language and inside this script all the parts of the robot that are attached to the base part can be read and controlled, this includes the actuated rotational joint and the proximity sensors. More information about using control scripts inside V-REP can be found here.
The modules are controlled using a CPG (Central Pattern Generator) controller based on the oscillator controller in Crespi et al. The oscillator equations are solved using an Euler solver using the following functions:
function updateCPG(number)
if (teta3) then
teta1new = teta1 + dteta0() * dt;
ampli1new = ampli1 + dampli1 * dt;
dampli1new = dampli1 + ddampli1(dampli1,ampli1,amp) * dt;
offset1new = offset1 + doffset1 * dt;
doffset1new = doffset1 + ddoffset1(doffset1,offset1,offset) * dt;
teta1 = teta1new;
ampli1 = ampli1new;
dampli1 = dampli1new;
offset1 = offset1new;
doffset1 = doffset1new;
end
end
function ddampli1(dampli1, ampli1, amp)
ar = 50
return ar*((ar/4)*(amp-ampli1)-dampli1)
end
function ddoffset1(doffset1, offset1, offset)
ax = 30
return ax*((ax/4)*(offset-offset1)-doffset1)
end
function dteta0()
v = 0.65
wij = 7;
if (suffix==-1) then
return (2*math.pi*v)+(wij*math.sin(teta3-teta1+(phasediff1))) -- +phase
elseif (nextsuffix>=robotCount) then
return (2*math.pi*v)+(wij*math.sin(teta2-teta1-(phasediff0)))-- -phase
else
return (2*math.pi*v)+(wij*math.sin(teta2-teta1-(phasediff0)))+(wij*math.sin(teta3-teta1+phasediff1))
end
end
In here the oscillator parameters are teta1
, the oscillator phase, ampli1
, the oscillator amplitude, and offset1
, the oscillator offset point. The parameters teta2
and teta3
contain the phase information received from the next and last neighbors.
When replicated each module has a suffix number attached to its name, this number can be read by using the following function:
suffix= simGetNameSuffix(nil)
where nil
indicates the function to obtain the suffix of the module that the robot is attached to. The communication between modules is achieved by using the suffix number and each module will only send or receive information from the following and preceding numbered modules:
simSendData(nexthandle,2,'next',teta1)
simSendData(lasthandle,3,'last',teta1)
teta2 = simReceiveData(2,'next')
teta3 = simReceiveData(3,'last')
Each time step the script calculates a step of the oscillator during the actuation part of the simulation, the phase parameter teta1
is sent to the next and last neighbors and their phase information is received, finally the output of the oscillator is used to set the rotational actuator target position:
angle = (math.pi/2)*(offset1+(math.cos(teta1)*ampli1))
simSetJointTargetPosition(centralMotor,angle)
#Initialization Script
The initialization script is associated to the InitControl object in the simulation, this script receives the robot morphology parameters builds the robot. The general robot building process is as follows:
angle=0
robotHandleOrig=simGetObjectHandle("modNorth")
--saving the current selection of objects (if any)
oldSelection=simGetObjectSelection()
--removing the current objects selection
simRemoveObjectFromSelection(sim_handle_all)
--selecting only the original robot to duplicate
simAddObjectToSelection(sim_handle_single,robotHandleOrig)
--copy / paste the original robot to its current location
--simCopyPasteSelectedObjects() Deprecated
copied = simCopyPasteObjects({robotHandleOrig},1)
--rotate first module to desired orientation
simSetObjectOrientation(robotHandleOrig,robotHandleOrig,{0,0,ori[1]*math.pi/2})
--assign the newly copied robot s handle as robotHandleCopy
-- robotHandleCopy=simGetObjectLastSelection()
robotHandleCopy = copied[1]
--storing the last base robot to attach force sensor
robotHandleBase=robotHandleOrig
--get the latest copy robot's position
robotpos=simGetObjectPosition(robotHandleCopy,-1)
-- teleport the copy robot to an other location different from the just copied/paste one
simSetObjectPosition(robotHandleCopy,-1,{0,robotpos[2]+0.25,robotpos[3]})
--change robot orientation
simSetObjectOrientation(robotHandleCopy,robotHandleCopy,{0,0,ori[2]*math.pi/2})--math.pi/2
--add Force Sensor as a rigid link between modules
sensorHandle=simCreateForceSensor(0,{0,1,10,0,0},{0.05,100.0,10.0,0.0,0.0},nil)
--position the sensor before attaching
simSetObjectPosition(sensorHandle,-1,{0,robotpos[2]+0.075,robotpos[3]})
--get the copy robot's south side handle
jointchild=simGetObjectChild(robotHandleCopy,0)
southchild=simGetObjectChild(jointchild,0)
--attach Force Sensor to copy robot
simSetObjectParent(sensorHandle,southchild,true)
--attach Force Sensor to base robot
simSetObjectParent(robotHandleBase,sensorHandle,true)
The script first copies the robot to the next position, changes its orientation and attaches a force sensor between the two now consecutive modules. The building process is repeated until all the required robots are placed forming a chain.
This scripts is also constantly measuring the position of the robot in the environment and checking if the termination condition is met, if it is, it sends the results of the test back to Java.
if (Goal) then
out[1] = 0
out[2] = timer
data = simPackFloats(out)
simSetStringSignal('Position',data)
simSetIntegerSignal("finished",1)
--simPauseSimulation()
end
if (timer>10) then
if (CurrentTPart<1) then
-- Normalize Distance
sum = 0
for i=1,#mseq,1 do
sum = sum + TPoints[i][7]
end
Dout = D/sum
if(Dout>1) then
Dout = 1
end
--print(Dout)
-- Send to Java
out[1] = Dout
out[2] = 0
data = simPackFloats(out)
simSetStringSignal('Position',data)
simSetIntegerSignal("finished",1)
--simPauseSimulation()
end
end
if (timer>maxTime) then
-- Normalize Distance
sum = 0
for i=1,#mseq,1 do
sum = sum + TPoints[i][7]
end
Dout = D/sum
if(Dout>1) then
Dout = 1
end
--print(D)
--print(sum)
-- Send to Java
out[1] = Dout
out[2] = 0
data = simPackFloats(out)
simSetStringSignal('Position',data)
simSetIntegerSignal("finished",1)
--simPauseSimulation()
end
For the specific method by which the script measures the position of the robot in the maze see the Simulated Environment section.