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