For the footpaths, you want to ensure there's always at least one gap / clearing all the way through to the far side. Some ways you can do this:
Generate the trees/rocks randomly, then try to flood-fill the passable space from the near side. If your flood fill reaches the far side, then there's at least one passable route. If not...
Try again from scratch! This approach is easy, but relies on your randomization routine already having a good probability of making a passable result by luck. If passable results are rare, you might spend a lot of time re-generating only to fail.
Fix it: carve out one or more solution paths somewhere, either picking a random column to bulldoze to passable space, or selectively deleting an obstacle (eg at the thinnest point)
Start by picking one or more solution paths - say taking a few biased random walks from the passable tiles from the previous footpath, until they reach all the way to the far side of this footpath. Mark each tile these random paths touch as "reserved".
Now, randomly fill some/all of the non-reserved tiles with obstacles. You're guaranteed that your reserved solutions still work, possibly in addition to some other solutions if you've left gaps in the non-reserved tiles.
Pre-author a bunch of "chunks" of footpath in various thicknesses with a solvable route through it.
When generating a new footpath, randomly select from these chunks and snap them end-to-end like LEGO bricks.
This approach gives you a lot of stylistic control, curating arrangements of obstacles/powerups that look good to you, but the repetition can be perceptible to players.
For the lanes of traffic/logs, it may suffice to ensure that there is eventually a way through:
Set the traffic generation in each lane to produce at least some gaps (say, add a randomized cooldown between obstacle spawning in a single lane, or deal obstacles from a "deck" with several "gap" cards in it)
Set adjacent lanes to travel in opposite directions or at different speeds, so that even if sometimes an obstacle in one lane blocks a gap in another, it won't always do so.
This way you'll get gaps stochastically, and you can tune the spawning frequencies/speeds to control how often they arise.
But the other approaches above work too, if you add time as a variable. For instance, a "remix" strategy could use pre-authored blocks of cars in adjacent lanes that move at the same speed. Or a "solution first" approach could periodically plan a path for the player between adjacent footpaths, recording the time window they'll be in each tile, then veto random spawning of any obstacle that's projected to overlap that tile in that time window, based on the lane's speed. Try the simple/stochastic route first though, and see if you still have unsolvable situations cropping up too often.