Skip to content
rmorenoga edited this page Oct 5, 2015 · 6 revisions

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.

Clone this wiki locally