LUA for CoppliaSim ROS2 integrationΒΆ

Detailed description of the code can be found here.

  1-- Custom function that fills a table with a replica of 'n' same 'value'
  2function table.fill(value, n)
  3    local t = {}
  4    for i = 1, n do
  5        table.insert(t, value)
  6    end
  7    return t
  8end
  9
 10-- Global declarations
 11q_home = {1.57, -1.57, 1.57 , -1.57, -1.57, 0.0}
 12joints = table.fill(nil, 6)
 13target = q_home
 14local max_vel = table.fill(180 * math.pi / 180, 6)
 15local max_acc = table.fill(40 * math.pi / 180, 6)
 16local max_jerk = table.fill(80 * math.pi / 180, 6)
 17
 18
 19-- Callback function of the ROS subscriber
 20function apply_joint_position(ros_msg)
 21    target = ros_msg.data
 22    if(tostring(target[1]) == "nan") then
 23        return
 24    end
 25    msg_received = true
 26end
 27
 28
 29-- Function that transforms the target configuration into movements for Coppelia
 30function move_to_config(handles, max_vel, max_acc, max_jerk, target_pos)
 31    local current_pos = {}
 32    local current_vel = {}
 33
 34    for i=1,#handles,1 do
 35        current_pos[i] = sim.getJointPosition(handles[i])
 36        current_vel[i] = sim.getJointVelocity(handles[i])
 37    end
 38
 39    sim.moveToConfig(-1, current_pos, current_vel, nil, max_vel, max_acc, max_jerk,
 40                     target_pos, nil, mov_callback, handles)
 41end
 42
 43
 44-- Callback function of the moveToConfig function builtin in Coppelia
 45function mov_callback(target_pos,vel,acc,handles)
 46    for i = 1, #handles, 1 do
 47            sim.setJointTargetPosition(handles[i],target_pos[i])
 48    end
 49end
 50
 51
 52-- Implementation of the function that's called when the simulation starts
 53function sysCall_init()
 54    if simROS2 then
 55        publisher = simROS2.createPublisher(
 56            '/coppelia_joint_states',
 57            'sensor_msgs/msg/JointState'
 58            )
 59        subscriber = simROS2.createSubscription(
 60            '/coppelia_set_joints',
 61            'std_msgs/msg/Float64MultiArray',
 62            'apply_joint_position'
 63            )
 64    end
 65
 66    joints[1] = sim.getObject('/shoulder_pan_joint')
 67    joints[2] = sim.getObject('/shoulder_lift_joint')
 68    joints[3] = sim.getObject('/elbow_joint')
 69    joints[4] = sim.getObject('/wrist_1_joint')
 70    joints[5] = sim.getObject('/wrist_2_joint')
 71    joints[6] = sim.getObject('/wrist_3_joint')
 72
 73    move_to_config(joints, max_vel, max_acc, max_jerk, target)
 74    msg_received = true
 75end
 76
 77
 78-- Function called during the actuation step of the simulation
 79function sysCall_actuation()
 80    if msg_received == true then
 81        move_to_config(joints, max_vel, max_acc, max_jerk, target)
 82        msg_received = false
 83    end
 84end
 85
 86
 87-- Function called during the sensing step of the simulation
 88function sysCall_sensing()
 89    local curr_pos = {}
 90    local curr_vel = {}
 91    local curr_torque = {}
 92    for i=1, #joints, 1 do
 93        curr_pos[i] = sim.getJointPosition(joints[i])
 94        curr_vel[i] = sim.getJointVelocity(joints[i])
 95        curr_torque[i] = sim.getJointForce(joints[i])
 96    end
 97
 98    local msg ={
 99        header={
100            stamp = simROS2.getSystemTime(),
101            frame_id = 'robot_base'
102        },
103        name = {
104            'shoulder_pan_joint', 'shoulder_lif_joint', 'elbow_joint',
105            'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint'
106        },
107        position = curr_pos,
108        velocity = curr_vel,
109        effort = curr_torque
110    }
111    simROS2.publish(publisher, msg)
112end