There are a couple of ways you could handle this:
1. Use an iterator and manually build objects.
There is an iterator to go through data (i.e. non-culled essence-of-object) with. It's core and for power users, but it definitely exists. It's called map.objDatas(). Once you've implemented the iterator, however, you're kind of on your own... Dusk doesn't provide a means to build objects outside of core. I recommend option 2 (below).
for data in map.layer["object layer"].objDatas() do
-- 'data' will refer to each object's data stored in Dusk's core object data structure.
-- Some things you might need to know about the structure:
-- `data.type` = the type of object (viz. "rect", "ellipse", etc.)
-- `data.transfer` = properties which will be set on the object when it's created. For example, this has `transfer.x` set to the object's final X position, `transfer.rotation` set to the rotation, etc. Anything you set in here will show up on the object when it's built.
2. Use system time to sync object positions
This would be a good thing for future development, too, as it would allow you to implement better controls for objects' timing. What I mean is to set some properties on your objects to denote "start cycle time", "cycle length", etc., then in your code sync the objects according to that. You can use Dusk's addObjectListener function to specify objects with type = "spike" or something:
"type", "spike", -- Listen for all objects with type = "spike"
"drawn", -- Listen for when they're drawn
local spike = event.object -- event.object is the object that was drawn
-- Use this listener to sync the spike's position when it's created
if spikeShouldBeUp(spike) then -- This function would take the spike's properties and tell whether, given the current time and the spike's properties, it should be up or down
goUp(spike) -- STAB! (R.I.P Intrepid Adventurer.)
goDown(spike) -- Run for it! They're down!
-- Also, you probably won't need it, but event.name is the name of the event ("drawn" in this case)