cannot override post_types in WP_Query()

First of all,while( have_posts()): should be while( $ml_featured->have_posts()):

And secondly, in your pre_get_posts callback you check:

false == $query->query_vars['suppress_filters']

But this returns true for every WP_Query query and any get_posts query where ‘supress_filters’ is explicitly set to false. If you want to check if the query is the ‘main’ query (i.e. query associated with the global $wp_query), you can use:

$query->is_main_query();

(see documentation here). This returns true if $query is the main query and false otherwise. This function was introduced in 3.3. Before 3.3 you can probably check (untested):

global $wp_the_query;
if($query === $wp_the_query){
  //is main query
}else{
  // is not main query
}

Alternatively (but preferably use the methods above), to alter the main query only:

 global $wp_query;
 $wp_query->set( 'post_type', array( 'wod', 'attachment' ) );